IEnumerable <t>转换</t>

时间:2009-10-15 00:56:04

标签: c#

鉴于以下内容:


class Base<T> {/*...*/}
class Der<T>: Base<T> {/*...*/}

interface Sth<T>{
  IEnumerable<Base<T>> Foo {get;}
}

// and implementation...
class Impl<T>: Sth<T> {
  public IEnumerable<Base<T>> Foo {
    get {
      return new List<Der<T>>();
    }
  }
}

如何编译?显然,该错误不是从List&lt; Der&lt; T&gt;&gt;中找到的隐式转换。列出&lt; Base&lt; T&gt;&gt;。如果我显式地转换它会发生InvalidCastException。

5 个答案:

答案 0 :(得分:6)

从.NET Framework 3.5版开始,不支持您尝试进行的转换。由于添加了generic covariance/contravariance,它将在4.0版(Visual Studio 2010)中得到支持。虽然这仍然不允许您将List<Der>投射到List<Base>,但允许您将IEnumerator<Der>(列表实现的)投射到IEnumerator<Base> }。

与此同时,您可以编写自己的实现IEnumerable<Base>的类,并返回一个自定义IEnumerator<Base>,它只包含List<Der>的{​​{1}}。或者,如果您使用的是.NET Framework 3.5版,则可以像其他人所建议的那样使用Cast extension method

答案 1 :(得分:4)

List<Der<T>>无法转换为List<Base<T>>,因为后者可以添加Base<T>而前者不能。{/ p>

您可以使用Cast扩展程序方法解决此问题:return new List<Der<T>>().Cast<Base<T>>();

答案 2 :(得分:1)

让它编译......

class Impl<T> : Sth<T>
{
    public IEnumerable<Base<T>> Foo
    {
        get
        {
            return new List<Base<T>>(); //change the List type to Base here
        }
    }
} 

你总是可以这样做,这将从Der的实现中返回Base类的IEnumerable

class Impl<T> : Sth<T>
{
    public IEnumerable<Base<T>> Foo
    {
        get
        {
            List<Der<T>> x = new List<Der<T>>();

            foreach (Der<T> dt in x)
            {
                yield return dt;
            }
        }
    }
} 

答案 3 :(得分:1)

您可以使用以下命令使用LINQ从List<Der<T>>投射到IEnumerable<Base<T>>,

class Impl<T>: Sth<T>
{
    public IEnumerable<Base<T>> Foo
    {
        get
        {
            return new List<Der<T>>().Cast<Base<T>>();
        }
    }
}

正如其他答案所述,v3.5不支持通用转发,但您可以使用LINQ创建一个实现IEnumerable<Base<T>>.的包装器对象

答案 4 :(得分:0)

这些答案帮助了我,我只想发布我的解决方案以解决我遇到的类似问题。

我为IEnumerable编写了一个扩展方法,只要我想转换List&lt; Foo&gt;,就会自动转换TSource。到IEnumerable&lt; Bar&gt; (我还在3.5)。

public static SpecStatus Evaluate<TSource, TSpecSource>(this IEnumerable<TSource> source, ISpec<IEnumerable<TSpecSource>> spec)
        where TSource : TSpecSource
{
    return spec.Evaluate(source.Cast<TSpecSource>());
}