为什么 C# 中的 Func<int> 不能赋值给 Func<object>?

4

我已经学习了C#中的协变和逆变。下面我的代码有一个错误。

object a = new object();
int b = 10;

a = b; // not error


Func<object> acO = () => new object();
Func<int> acI = () => 1;

acO = acI; // error

错误信息:

无法隐式地将类型“System.Func”转换为类型“System.Func”。

我以为如果 int -> object 是可能的,那么 Func -> Func 也会是可能的。 但事实并非如此。

我认为值类型在返回时会被复制以供使用,而不像引用类型(对象)那样导致意外操作(如异常)。我的猜测正确吗?

期待您的智慧回答。 谢谢阅读。


5
int 转换为 object 是一种装箱转换,而不是派生类所得到的引用转换,这就是为什么(好或坏)编译器不会允许隐式地进行此转换,因为它需要在内部生成一个新的委托。acO = () => acI() 可以工作,因为你自己明确地进行了装箱。 - Jeroen Mostert
1个回答

2

来自C#中委托的方差文档:

泛型类型参数的方差仅支持引用类型。

Eric Lippert在他的博客文章中深入探讨了这个主题:

所有内置的引用转换都是保留标识的。这就是为什么接口和委托类型的协变和逆变转换要求所有不同的类型参数都是引用类型的原因。为了确保变体引用转换始终保留标识,涉及类型参数的所有转换也必须保留标识。确保所有类型参数上的非平凡转换都是保留标识的最简单方法是将它们限制为引用转换。


我曾以为委托(包括Func<T>)在.NET中是引用类型? - Mathias R. Jessen
1
@MathiasR.Jessen 是的,但是这个引用是关于类型参数的。类似的引用可以在有关泛型接口的变异性的文档中找到。 - Guru Stron

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接