为何Func<TResult>的协变无法生效?——关于Func<int>无法赋值给Func<object>的技术问询
为什么
Func<int>无法赋值给Func<object>? 这是个很典型的协变场景疑问,先给你澄清一个核心事实:在C# 4.0及以上版本中,标准库的Func<int>其实是可以隐式转换为Func<object>的——因为System.Func<out TResult>的TResult参数是用out关键字标记的协变类型参数,完全符合你提到的协变原则(返回值类型可以从派生类安全转为基类)。
那你遇到编译器报错的情况,大概率是下面两种原因之一:
你使用的C#版本低于4.0
协变和逆变特性是C# 4.0才引入的语言功能,如果你的项目目标框架是.NET Framework 3.5或更早版本,或者编译器语言版本设置为4.0以下,这种隐式转换就会被禁止。你可以检查项目属性里的语言版本设置,或者升级到支持C#4.0及以上的框架版本。你自定义了非协变的
Func<T>委托
如果你的代码里自己定义了一个名为Func<T>的委托,比如:delegate T Func<T>(); // 没有out修饰符这个自定义委托没有标记
out,所以不支持协变。此时你需要要么改用系统内置的System.Func<T>,要么给自定义委托的类型参数加上out修饰符:delegate T Func<out T>(); // 现在支持协变了
举个验证的例子,在C#4.0+环境下,这段代码是完全合法的:
using System; class Program { static int FuncA() { return 0; } static void Main() { Func<int> a = FuncA; Func<object> b = a; // 编译通过,协变生效 Console.WriteLine(b()); // 输出0 } }
总结一下:协变在Func<TResult>上是正常生效的,你遇到的问题大概率是环境版本或者自定义委托的配置问题。
内容的提问来源于stack exchange,提问作者Cool Coder
相关产品推荐
相关产品推荐

