c# - <in From, out To> 是什么意思?

标签 c# generics covariance contravariance

Resharper 建议从

interface IModelMapper<TFrom, TTo>
{
    TTo Map(TFrom input);
}

进入

interface IModelMapper<in TFrom, out TTo>

所以我调查了一下并结束阅读this article (通过 Wikipedia 文章找到)和更多 Google。

我仍然不确定这对我的申请意味着什么,所以我很想不接受这个建议。此更改会带来哪些好处,我不会通过忽略该建议来考虑?

更明确地说,我为什么要接受它?

最佳答案

底线:Resharper 已调查您的类型,并发现 TFrom可以逆变地使用,并且TTo协变地。接受重构将使您能够更灵活地使用这些类型,如下所述。如果这可能对您有值(value),请接受它。

但是请注意,接受此重构会限制您将来如何使用这些类型。如果你曾经写过一个接受 TTo 的方法作为参数,你会得到一个编译器错误,因为无法读入协变类型。TFrom 也是如此。 : 你将永远无法拥有返回此类型或具有 out 的方法这种类型的参数。


这告诉你 TFrom是逆变的,并且TTo是协变的。这些是最近的功能 added to C#

类型协变意味着可以传入更多特定类型,而逆变意味着可以传入更少特定类型。

IEnumerable<T>是类型协变的一个很好的例子。由于 IEnumerable<T> 中的项目是只读,您可以将其设置为更具体的内容:

IEnumerable<object> objects = new List<string>();

考虑如果(假设地)您被允许对可读/写的集合执行此操作会发生什么:

List<object> objects = new List<string>();
objects.Add(new Car());
//runtime exception

要成为类型协变,泛型参数必须以严格的只读方式使用;它只能从类型中写出 out,永远不要读入 in(因此是关键字)。这就是为什么 IEnumerable<T>示例有效,但是 List<T>例子没有。顺便说一句,数组确实支持类型协变(我相信 Java 支持),因此数组也可能出现同样类型的运行时错误。

类型逆变意味着相反。为了支持类型逆变,泛型参数必须只被读入in,而绝不能写出。这允许您替换不太具体的类型。

Action<T>是类型违背的一个例子:

Action<object> objAction = (o => Console.WriteLine(o.ToString()));
Action<string> strAction = objAction;
strAction("Hello");

strAction被声明为采用字符串参数,但如果您替换为对象类型,它就可以正常工作。一个字符串将被传入,但如果它被设置为与之一起工作的委托(delegate)选择将其视为一个对象,那么就这样吧。没有伤害。

为了完整性,Func<T>Action<T> 的相反情况;这里T仅返回,因此它是协变的:

Func<string> strDelegate =  () => "Hello";
Func<object> myObjFunc = strDelegate;
object O = myObjFunc();

myObjectFunc被编码为返回一个对象。如果您将其设置为返回字符串的内容,那么同样不会造成任何伤害。

关于c# - <in From, out To> 是什么意思?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8317186/

相关文章:

c# - 多个匿名事件处理程序 - 但只调用最后一个

c# - 使用 Azure Devops 部署一次性应用程序?

java - Java 中嵌套集合/结构的类型安全展平

c# - 学习泛型的好资源有哪些?

php - 特化中的参数类型协方差

generics - 通用密封类的类型安全使用

c# - C#中的泛型约束,T是一样的TSomethingElse吧?

c# - ASP.NET Core 3.0 身份不向我的浏览器添加任何身份验证数据

java - 扩展类并实现接口(interface)的通用类

c# - 委托(delegate)协变和协变