c#协变一般参数

c#协变一般参数,c#,generics,covariant,C#,Generics,Covariant,我试图理解这一点,但我没有从搜索中得到任何适当的结果 在c#4中,我能做到 public interface IFoo<out T> { } 公共接口IFoo { } 这和 public interface IFoo<T> { } 公共接口IFoo { } 我只知道,out使泛型参数协变(??)。 有人能举例说明零件的用法吗?为什么只适用于接口和委托,而不适用于类 抱歉,如果是重复的,请关闭它 这意味着如果您有:

我试图理解这一点,但我没有从搜索中得到任何适当的结果

在c#4中,我能做到

    public interface IFoo<out T>
    {

    }
公共接口IFoo
{
}
这和

    public interface IFoo<T>
    {

    }
公共接口IFoo
{
}
我只知道,
out
使泛型参数协变(??)。 有人能举例说明
零件的用法吗?为什么只适用于接口和委托,而不适用于类


抱歉,如果是重复的,请关闭它

这意味着如果您有:

class Parent { } 
class Child : Parent { }
然后,
IFoo
的实例也是
IFoo
的实例

有人能举例说明out T部分的用法吗

当然<代码>IEnumerable是协变的。这意味着您可以这样做:

static void FeedAll(IEnumerable<Animal> animals) 
{
    foreach(Animal animal in animals) animal.Feed();
}

...

 IEnumerable<Giraffe> giraffes = GetABunchOfGiraffes();
 FeedAll(giraffes);
好的,现在在继续之前仔细考虑这个问题是否可以在构造函数之外使用任何方法将字段
t
设置为默认值以外的值?

因为它必须是类型安全的,
C
现在可以没有将T作为参数的方法;T只能返回。那么谁设定了t,他们从哪里得到设定值呢

协变类类型只有在类不可变时才有效。我们没有一个好的方法在C#中生成不可变的类

我希望我们这样做,但我们必须接受我们得到的CLR类型系统。我希望将来我们能够更好地支持不可变类和协变类

如果这个特性让你感兴趣,请考虑阅读我的长系列关于我们如何设计和实现这个特性。从底部开始:


如果我们谈论的是一般差异:

协方差是指从操作返回给调用方的值

逆变相反,是关于调用者传递的值:

据我所知,如果类型参数仅用于输出,则可以使用out。但是,如果该类型仅用于输入,则可以在中使用。这很方便,因为编译器无法确定您是否能够记住哪种形式称为协方差,哪种形式称为逆变换。如果在声明类型后不显式声明它们,则相关的转换类型可以隐式地使用

类中没有方差(协方差或逆变),因为即使您有一个仅将类型参数用于输入(或仅将其用于输出)的类,您也可以
无法指定输入或输出修改器。只有接口和委托可以具有变量类型参数。首先,CLR不允许这样做。从概念的角度来看,接口代表了从特定角度看待对象的一种方式,而类则更多地是实际实现类型。

阅读以下内容:谢谢Eric!这给了我一个大概的想法,我会仔细阅读你的博客文章。PS:当我看到你的回答时,我希望看到一些酒店房间和被盗钥匙,但我会带上长颈鹿。如果
C
有多个字段,其类型涉及
T
,它可能有根据另一个字段中的信息设置
T
的方法。此外,即使只能在构造函数中设置字段,如果可以将
元组
之类的内容传递给需要
元组
的代码,这将非常有用。我认为协变类的一个更基本的问题是,从
Foo
生成的每个不同类都有自己的静态变量集。如果
Foo.Q()
…@Larsmael:微软每隔十年左右就会更换一次博客系统,所有的链接都会被弄乱。谢谢你的提醒,我会修复它。@ErickBrown:是的,如果有一种方法让编译器和运行时可靠地知道“这个类中的所有内容都设置了一次,然后才被读取”,那么我们可以推断这个不可变类型可以安全地协变。逻辑是正确的;因此,剩下的问题是设计一个类型系统的工程问题,该系统将跟踪不变性以及其他一切!这才是真正的工作。最近的C#9“记录类型”原型是朝着这个方向迈出的可能的一步,所以我期待着了解更多。@BorisB:这是你的第二个问题:如果类型系统可以对字段的“内部”和“外部”修改进行推理,那么是的,类型系统可以使某些类型的协方差合法,而现在是非法的。但在进行类型分析时,即使是字段的“只读性”这样的事实也没有考虑在内;理论上,它们可能是。
class C<out T>
{
    private T t;