简体   繁体   English

通用类协方差

[英]Generic Class Covariance

Is it possible to make the following code compile in C#?是否可以在 C# 中编译以下代码? I do compile similar in Java.我确实在 Java 中进行了类似的编译。

public interface IInterface
{
    ...
}

public class Class1 : IInterface
{
    ...
}

public abstract class Base<T> where T : IInterface
{
    ...
}

public class Class2<T> : Base<T> where T : IInterface
{
    ...
}

.
.
.

public SomeMethod()
{
    List<Base<IInterface>> list = new List<Base<IInterface>>();
    Class2<Class1> item = new Class2<Class1>();
    list.Add(item); // Compile error here
}

No, that is not legal in C#.不,这在 C# 中是不合法的。 C# 4 and above support covariance and contravariance of generic interfaces and generic delegates when they are constructed with reference types. C# 4 及更高版本支持泛型接口和泛型委托在使用引用类型构造时的协变和逆变。 So for example, IEnumerable<T> is covariant, so you could say:例如, IEnumerable<T>是协变的,所以你可以说:

List<Giraffe> giraffes = new List<Giraffe>() { ... };
IEnumerable<Animal> animals = giraffes;

but not但不是

List<Animal> animals = giraffes;

Because a list of animals can have a tiger inserted into it, but a list of giraffes cannot.因为动物列表可以插入老虎,但长颈鹿列表不能。

Do a web search on covariance and contravariance in C# and you'll find lots of articles on it.对 C# 中的协变和逆变进行网络搜索,您会找到很多关于它的文章。

Looks like .NET Framework 4.0 supports covariance in generic interfaces and delegates.看起来 .NET Framework 4.0 支持泛型接口和委托的协变。 So, I happened to compile the code by adding a generic interface.所以,我碰巧通过添加一个通用接口来编译代码。

public interface IInterface
{
    ...
}

public class Class1 : IInterface
{
    ...
}

public interface IBase<out T> where T: IInterface
{
    // Need to add out keyword for covariance.
}

public class Base<T> : IBase<T> where T : IInterface
{
    ...
}

public class Class2<T> : Base<T> where T : IInterface
{
    ...
}

.
.
.

public SomeMethod()
{
    List<IBase<IInterface>> list = new List<IBase<IInterface>>();
    Class2<Class1> item = new Class2<Class1>();
    list.Add(item); // No compile time error here.
}

you cannot use generic like this.list type is IInterface but you try to add Class1 type into the list.it should be as follows..您不能像这样使用泛型。列表类型是 IInterface 但您尝试将 Class1 类型添加到列表中。它应该如下所示..

        List<Base<Class1>> list = new List<Base<Class1>>();
        Class2<Class1> item = new Class2<Class1>();
        list.Add(item); 

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM