仿制药的两种用法有什么区别(协方差)

时间:2016-11-01 23:18:28

标签: c# generics covariance

我认为我理解泛型不支持协方差,这就是为什么第一个例子不起作用并给出Invalid Cast异常的原因。但是一切都在编译。

但为什么第二个例子有效呢?我只能看到它是同一件事。

MyClass 是这样的:

public interface IGenericClass<T> { }
public class MyClass : IGenericClass<SomeType>
{
}

不工作:

public class SendingEmail<T>
{
    IGenericClass<T> abc;
    public void Send(IGenericClass<T> _abc)
    {
        this.abc = _abc;
    }
}

用法:

var myClass = new MyClass();
SendingEmail<MyClass> sendingEmail = new SendingEmail<MyClass>();
sendingEmail.Send(IGenericClass<MyClass>myClass);
//sendingEmail.Send(myClass); This was wrong

也尝试过:

删除,因为它从未编译

工作:

class SendingEmail
{
    void Send<T>(MyGenericClass<T> abc)
    {

    }   
}

用法:

SendingEmail sendingEmail = new SendingEmail();
sendingEmail.Send(myclass);

1 个答案:

答案 0 :(得分:2)

第一个例子与协方差无关。你很容易混淆T的真实含义; TSomeType,而非MyClass

在第二个例子中,你让编译器正确推断出类型,这就是它的工作原理。

修改

对您的问题的修改无法解决问题,您仍然会混淆T的内容:MyClass T中的SomeTypeSendingEmail<T>。在T SomeType 还应该abc,因为IGenericType<T>已键入IGenericType<SomeType>,您最终希望它为SendingEMail<MyClass> }。

在您的代码中,您创建了一个类型为abc的实例,这意味着IGenericType<MyClass>实际上是IGenericType<SomeType>,这是错误的;您无法将IGenericType<IGenericType<SomeClass>>转换为sendingEMail(MyClass),而这正是您在致电var sendingEmail = new SendingEmail<SomeType>()时所做的事情;

您需要做的是:IEnumerable<Animal> animals = Enumerable.Emtpy<Tiger>()

关于这与类型方差有关,事实并非如此。例如,类型差异允许您执行IList<T>,不允许您对IEnumerable执行相同操作; T中的IList是协变的,而T中的Animal[] animals = new Tiger[3]是不变的。

请注意,C#确实在数组中破坏了协方差,以下是合法的:animals[0] = new Turtle();。它已经坏了,因为现在你可以合法地做IList并且......哎......你刚刚得到一个运行时异常。这种情况正是TAppContext不变的原因。为什么C#在数组中破坏了协方差?我不知道,但我认为这是一个不幸(虽然可能是合理的)设计决定。