2016-02-25 52 views
0

我想了解一些关于C#的泛型的细节。C#泛型:接口实现对象列表

如果我有一个方法定义为这样

public static void AssertContains<T>(IEquatable<T> val, List<IEquatable<T>> optionsObjs, XML xml, string context) 

和实现IEquatable类,

public class Tag : IEquatable<Tag> 
{ 
    public string id; 
    public bool Equals(Tag other) 
    { 
     return other.id == this.id; 
    } 
} 

为什么以下无效?

AssertContains(aTag, aListOfTags, el, ""); 

回答

2

这是因为List<T>不是,所以你不能转换到List<Type>List<BaseType>

在你的情况下List<Tag>List<IEquatable<Tag>>

您可以修复这个不断变化的optionsObjs参数类型IEnumerable<IEquatable<T>>

public static void AssertContains<T>(IEquatable<T> val, 
            IEnumerable<IEquatable<T>> optionsObjs, 
            XML xml, 
            string context) 

那是因为IEnumerable<T>,所以你可以做这样的事情:

IEnumerable<IEquatable<Tag>> list = new List<Tag>(); 
0

我想通了,限定所述方法

public static void AssertContains<T>(T val, List<T> optionsObjs, XML xml, string context) where T: IEquatable<T> 

使得AssertContains(aTag, aListOfTags, el, "");有效。

但是,如果有人能解释为什么我原来的帖子是错的,我会接受他们的回答。

+0

检查此问题http://stackoverflow.com/questions/2184551/difference-between-covariance-contravariance – MKMohanty

1

这不起作用,因为contravariance;基本上,List<Derived>不能被视为List<Base>

-1

我认为这个问题是在List<IEquatable<T>>中,因为它是通用的。在使用下面的语句时,您可以避免泛型问题。

public static void AssertContains<T>(T val, List<T> optionsObjs, XML xml, string context) where T: IEquatable<T> 

为了证明你是我下面写的使用2种泛型类型:

public static void AssertContains<T, Z>(IEquatable<T> val, List<Z> optionsObjs, XML xml, string context) where Z : IEquatable<T> 

可以算出以同样的方式,而是采取一个仔细看看导致我们上面的说法,因为IEquatable<T> val可能会被Z val替代。因此,如果您有一个通用参数,则2个通用类型非常有用:

public static void AssertContains<T, Z>(T anotherValue, IEquatable<T> val, List<Z> optionsObjs, XML xml, string context) where Z : IEquatable<T> 
2

几乎每天都会以某种形式询问这个问题。

在任何需要长颈鹿列表的情况下,动物列表均不得使用。为什么?因为动物列表可能包含一只老虎。

长颈鹿列表不能用于需要动物列表的任何场合。为什么?因为动物列表中可能会插入一只老虎,现在你已经插入一只老虎到实际上是长颈鹿列表中。

然而,长颈鹿的一个序列 - IEnumerable<T>可用作动物序列。为什么这是合法的,如果在列表中是非法的呢?因为序列没有方法可以让你将一只老虎添加到一系列动物中。

在本网站或互联网上搜索“C#中的协变和相反关系”,您会发现很多关于此主题的信息。