Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/.net/23.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/mercurial/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 将子类的枚举数强制转换为父类的枚举数是否错误?_C#_.net_Generics_Covariance - Fatal编程技术网

C# 将子类的枚举数强制转换为父类的枚举数是否错误?

C# 将子类的枚举数强制转换为父类的枚举数是否错误?,c#,.net,generics,covariance,C#,.net,Generics,Covariance,我的构建中有一个错误,上面写着: 错误12无法隐式转换 类型 'System.Collections.Generic.IEnumerator' 到 “System.Collections.Generic.IEnumerator”。 存在一个显式转换(您是吗 缺少演员阵容?) 简单地抛弃它是错误的吗 这是我的代码: public Dictionary<Int32, BaseClass> Map { get; private set; } public IEnumerator<B

我的构建中有一个错误,上面写着:

错误12无法隐式转换 类型 'System.Collections.Generic.IEnumerator' 到 “System.Collections.Generic.IEnumerator”。 存在一个显式转换(您是吗 缺少演员阵容?)

简单地抛弃它是错误的吗

这是我的代码:

public Dictionary<Int32, BaseClass> Map { get; private set; }

public IEnumerator<BaseClass> GetEnumerator()
        {
            return this.Map.Values.GetEnumerator();
        }

public IEnumerator<IParentClass> IEnumerable<IParentClass>.GetEnumerator()
        {
            return this.GetEnumerator(); // ERROR!
        }
致:

返回(IEnumerator)this.GetEnumerator();
(没有任何不良副作用)

接受答案:
我已将函数更改为以下内容(在阅读Jon Skeet的帖子后):

IEnumerator IEnumerable.GetEnumerator()
{
返回此.Map.Values.Cast().GetEnumerator();
}
IEnumerator
IEnumerator
是不相关的,尽管它们的通用参数是。我将改为使用LINQ
Select
扩展方法,如下所示:

return this.Select(x => (IParentClass)x).GetEnumerator();
Cast
扩展方法:

return this.Cast<IParentClass>().GetEnumerator();
返回此.Cast().GetEnumerator();

不,您不能,至少在C#3.0及以下版本中,不支持界面差异。请参阅Eric Lippert在这方面的优秀系列,尤其是。

不,你不能,因为泛型在C#中目前是不协变的。NET本身有一些支持(对于委托和接口),但它还没有真正被使用

如果返回的是
IEnumerable
,而不是
IEnumerator
(并假设为.NEt 3.5),则可以使用
Enumerable.Cast
——但当前需要编写自己的扩展方法,例如

public static IEnumerator<TParent> Upcast<TParent, TChild>
    (this IEnumerator<TChild> source)
    where TChild : TParent
{
    while (source.MoveNext())
    {
        yield return source.Current;
    }
}
公共静态IEnumerator向上广播
(此IEnumerator来源)
TChild:t租金在哪里
{
while(source.MoveNext())
{
产生返回源。电流;
}
}
或者,在您的情况下,您可以更早地使用Cast:

return this.Map.Values.Cast<BaseClass>().GetEnumerator();
返回此.Map.Values.Cast().GetEnumerator();

不,它不安全,请参见以下内容:

使用System.Collections.Generic; 类Foo{} 类栏:Foo{}

static class Program
{
    static IEnumerator<Foo> GetBase() {
        yield return new Foo();
        yield return new Bar();
    }
    static IEnumerator<Bar> GetDerived()
    {
        return (IEnumerator<Bar>)GetBase();
    }
    static void Main()
    {
        var obj = GetDerived(); // EXCEPTION
    }
}
静态类程序
{
静态IEnumerator GetBase(){
返回新Foo();
屈服返回新棒();
}
静态IEnumerator get派生()
{
返回(IEnumerator)GetBase();
}
静态void Main()
{
var obj=get派生();//异常
}
}
但是,您应该能够使用迭代器块为您执行强制转换

static IEnumerator<Bar> GetDerived()
{
    using (IEnumerator<Foo> e = GetBase())
    {
        while (e.MoveNext())
        {
            // or use "as" and only return valid data
            yield return (Bar)e.Current;
        }
    }
}
静态IEnumerator get派生()
{
使用(IEnumerator e=GetBase())
{
while(如MoveNext())
{
//或者使用“as”并仅返回有效数据
收益率返回(巴)e.电流;
}
}
}
要解释这不合适的原因,请使用图片而不是
枚举器、
列表。两者都使用泛型-编译器不会以与泛型参数相关的特殊方式处理任何一个

void doStuff() {
    List<IParentThing> list = getList();
    list.add(new ChildThing2());
}

List<IParentThing> getList() {
    return new List<ChildThing1>();  //ERROR!
}
void doStuff(){
List=getList();
添加(新的ChildThing2());
}
List getList(){
返回新列表();//错误!
}
第一种方法很好-一个
iparenthing
s列表应该能够接收
ChildThing2
。但是
ChildThing1
s列表不能处理
ChildThing2
,或者实际上不能处理
iparenthing
以外的
ChildThing1
的任何实现者-换句话说,如果
ListChildThing1>
被允许转换为
ListIParent>
,它必须能够处理
iparenthing
的所有子类,而不仅仅是
iparenthing
ChildThing1


请注意,Java泛型有一种说法,除了“我想要一个由此继承的任何东西的列表”之外,“我想要一个由此继承的任何东西的列表”,这允许对一些问题提供更有趣(而且在我看来是优雅的)的解决方案。

IEnumerator不行——您需要IEnumerable。(在这种情况下,首先使用Cast())我已经更正了这个示例。我还包括Cast()方法。
static class Program
{
    static IEnumerator<Foo> GetBase() {
        yield return new Foo();
        yield return new Bar();
    }
    static IEnumerator<Bar> GetDerived()
    {
        return (IEnumerator<Bar>)GetBase();
    }
    static void Main()
    {
        var obj = GetDerived(); // EXCEPTION
    }
}
static IEnumerator<Bar> GetDerived()
{
    using (IEnumerator<Foo> e = GetBase())
    {
        while (e.MoveNext())
        {
            // or use "as" and only return valid data
            yield return (Bar)e.Current;
        }
    }
}
void doStuff() {
    List<IParentThing> list = getList();
    list.add(new ChildThing2());
}

List<IParentThing> getList() {
    return new List<ChildThing1>();  //ERROR!
}