c# - Action 的通用约束没有按预期工作

标签 c# .net generics covariance contravariance

我无法理解为什么下面的代码片段没有给我一个错误

public void SomeMethod<T>(T arg) where T : MyInterface
{
  MyInterface e = arg;
}

但是这个,由于泛型类型约束,我希望它能工作

private readonly IList<Action<MyInterface>> myActionList = new List<Action<MyInterface>>();

public IDisposable Subscribe<T>(Action<T> callback) where T: MyInterface
{
  myActionList.Add(callback); // doesn't compile
  return null
}

给出这个错误

cannot convert from 'System.Action<T>' to 'System.Action<MyInterface>'

我正在使用 VS2012 sp1 和 .NET 4.5。

谁能解释为什么约束不允许它编译?

最佳答案

这是一个逆变问题 - Action<MyInterface>应该能够采取任何 MyInterface实例作为参数,但是您正在尝试存储 Action<T>其中 TMyInterface 的一些子类型,这是不安全的。

例如,如果您有:

public class SomeImpl : MyInterface { }
public class SomeOtherImpl : MyInterface { }
List<Action<MyInterface>> list;

list.Add(new Action<SomeImpl>(i => { }));
ActionMyInterface act = list[0];
act(new SomeOtherImpl());

您只能分配 Action<T>给一些Action<U>如果类型 TU 类型“更小” .例如

Action<string> act = new Action<object>(o => { });

是安全的,因为字符串参数在对象参数所在的地方始终有效。

关于c# - Action 的通用约束没有按预期工作,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15610892/

相关文章:

c# - 如何使 C# 应用程序崩溃

c# - 如何将编码标签呈现为正确的 HTML,而不是文本?

c# - .net Dynamic Reference 但仍然有 intellisense

.net - ASP.NET:跨应用程序的表单例份验证:匹配密码加密设置

Java Collections.checked*() 与通用集合

generics - 无法定义 'a->' b 函数列表

c# - 一对一关系、不同的键列名称、 Entity Framework 、代码优先方法

c# - 使用 .NET Core 3.1 上传大于 100 MB 的文件将导致 400(错误请求)

.net - 如何发现哪个图像文件是 Windows 上的当前桌面背景?

java - 了解 Java 泛型的类型安全异常