我的构建中出现了错误:

  

错误12无法隐式转换   类型   <!>“System.Collections.Generic.IEnumerator LT; <!> BaseClass的GT;”   至   <!>“System.Collections.Generic.IEnumerator LT; <!> IParentClass GT;”。   存在显式转换(是你   错过演员?)

简单地把它丢掉是不对的?

这是我的代码:

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!
        }

我的问题是,我可以改变这一行:

return this.GetEnumerator();

为:

return (IEnumerator<IParentClass>)this.GetEnumerator();

(没有任何不良副作用)?

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

IEnumerator<IParentClass> IEnumerable<IParentClass>.GetEnumerator()
        {
            return this.Map.Values.Cast<IParentClass>().GetEnumerator();
        }
有帮助吗?

解决方案

不,你不能,因为仿制品目前在C#中并不协变。 .NET本身有一些支持(对于委托和接口)但它还没有真正使用过。

如果您返回IEnumerable<BaseClass>而不是IEnumerator<BaseClass>(并假设.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;
    }
}

或者在你的情况下你可以使用Cast:

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

其他提示

不,你不能,至少在C#3.0及以下界面方差不受支持。请参阅Eric Lippert关于此的优秀系列,特别是这个

不,它不安全,见下文:

使用System.Collections.Generic; Foo {} class Bar: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
    }
}

但是,你应该能够使用迭代器块为你做演员吗?

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;
        }
    }
}

要理解为什么这是不合适的,请拍照而不是EnumeratorList。两者都使用泛型 - 编译器不会以与通用参数相关的特殊方式处理任何一个。

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

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

第一种方法很好 - IParentThing s列表应该能够收到ChildThing2。但是ChildThing1的列表无法处理List&lt;ChildThing1>,或者除了List&lt;IParent>之外的<=>的任何实现者 - 换句话说,如果<=>被允许转换为<=>,它会必须能够处理的所有子类,而不仅仅是<=>和<=>。

请注意,Java泛型有一种方式可以说<!>;我想要一个从<!>引用继承的东西的列表;除了<!>之外,我想要一个这个继承的东西的列表,<!> quot;这使得一些问题的解决方案更加有趣(在我看来更优雅)。

IEnumerator<BaseClass>IEnumerator<ParentClass>是无关的,尽管它们的通用参数是。我会使用像这样的LINQ Select扩展方法:

return this.Select(x => (IParentClass)x).GetEnumerator();

Cast扩展方法:

return this.Cast<IParentClass>().GetEnumerator();
许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top