c# - 我在微软的逆变示例中遗漏了什么?
问题描述
我试图理解实践中的逆变。看书的时候好像是直截了当的,现在好像卡住了。我知道有很多关于逆变的主题,我用谷歌搜索了很多,没有一个帮助我理解这个特殊问题这是微软文档所说的https://docs.microsoft.com/en-us/dotnet/standard/generics/协方差和逆变
这是我的代码:
using static System.Console;
namespace CSharpTests
{
class Program
{
delegate void Action<T> (T obj);
static void Main(string[] args)
{
Action<Device> b = DeviceAction;
Action<Mouse> d = b; // Error cannot implicitly convert type CSharpTests.Program.Action<CSharpTests.Device> to CSharpTests.Program.Action<CSharpTests.Mouse>
d(new Mouse());
ReadLine();
}
private static void DeviceAction(Device target) {
WriteLine(target.GetType().Name);
}
}
class Device { }
class Mouse : Device { }
}
关键的区别是什么?我的代码甚至没有编译。如您所见,我有一个接受泛型类型的委托,据我所知,它允许逆变。但在实践中,我遇到了编译时错误。我也尝试用“out”参数来做,得到了同样的错误
using static System.Console;
namespace CSharpTests {
class Program {
delegate void Action<T> (out T obj);
static void Main(string[] args) {
Action<Device> b = DeviceAction;
Action<Mouse> d = b; // Error cannot implicitly convert type CSharpTests.Program.Action<CSharpTests.Device> to CSharpTests.Program.Action<CSharpTests.Mouse>
Mouse m;
d(out m);
ReadLine();
}
private static void DeviceAction(out Device target) {
target = new Device();
WriteLine(target.GetType().Name);
}
}
class Device { }
class Mouse : Device { }
}
解决方案
将签名更改为delegate void Action<in T>(T arg)
.
将类型参数声明为 in
表示逆变;out
表示协方差。
您通常可以分辨出使用哪一个,因为in
它用于输入(例如,参数)和out
用于输出(例如,返回值)。
推荐阅读
- javascript - 如何使 mapbox 地图在卡内响应?
- python - 根据选择列值划分组数据?
- json - 如何针对具有多级引用的复杂 json 模式验证 json
- asp.net-core - 使用从主 dbcontext 获取的信息更改辅助 dbcontext 的连接字符串
- r - 如何将列和行百分比添加到 R 中的交叉表(如在 excel 数据透视表中)?
- python - Plotly express 折线图不接受文档中的关键字
- python - 为什么会打印出函数外部的一行代码(在另一个文件中调用该函数时)?
- scala - Scala RDD按组获取最早日期
- laravel - 在 Laravel 中仅从数据库中获取少量数据
- elasticsearch - 如何在 Elasticsearch 中将前缀查询与同义词过滤器结合起来?