加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

c# – 在CoVariance和ContraVariance中输入安全性

发布时间:2020-12-15 03:57:39 所属栏目:百科 来源:网络整理
导读:我正在阅读Jon Skeet的深度C#.虽然我已经理解了协变量和对比变量的概念,但我无法理解这一行: Well,covariance is safe when SomeType only describes operations that return the type parameter—and contravariance is safe when SomeType only describes
我正在阅读Jon Skeet的深度C#.虽然我已经理解了协变量和对比变量的概念,但我无法理解这一行:

Well,covariance is safe when SomeType only describes operations that
return the type parameter—and contravariance is safe when SomeType
only describes operations that accept the type parameter.

有人可以用一个例子来解释两者,为什么两个都是一个方向的安全,而不是另一个方向?

Updated Question:

我仍然不明白答案.我将尝试使用与C#深度相同的例子来解释我的关注.

它解释了使用以下类层次结构:

COVARIANCE是:尝试转换IEnumerable< Circle>到IEnumerable< IShape>,但是提到这种转换是类型安全的,只有当我们在从某种方法返回时执行,而当我们将其作为IN参数传递时,这种转换不是类型安全的.

IEnumerable<IShape> GetShapes()
{
    IEnumerable<Circle> circles = GetEnumerableOfCircles();
    return circles; // Conversion from IEnumerable<Circle> to IEnumerable<IShape> - COVARIANCE
}

void SomeMethod()
{
    IEnumerable<Circle> circles = GetEnumerableOfCircles();
    DoSomethingWithShapes(circles); // Conversion from IEnumerable<Circle> to IEnumerable<IShape> - COVARIANCE
}

void DoSomethingWithShapes(IEnumerable<IShape> shapes) // Why this COVARIANCE is type unsafe??
{
    // do something with Shapes
}

CONTRA VARIANCE是:试图从IEnumerable< IShape>到IEnumerable< Circle>,其被提及为仅在作为IN参数发送时执行时被安全地类型安全.

IEnumerable<Circle> GetShapes()
{
    IEnumerable<IShape> shapes = GetEnumerableOfIShapes();
    return shapes; // Conversion from IEnumerable<IShape> to IEnumerable<Circle> - Contra-Variance
    // Why this Contra-Variance is type unsafe??
}

void SomeMethod()
{
    IEnumerable<IShape> shapes = GetEnumerableOfIShapes();
    DoSomethingWithCircles(shapes); // Conversion from IEnumerable<IShape> to IEnumerable<Circle> - Contra-Variance
}

void DoSomethingWithCircles(IEnumerable<Circle> circles) 
{
    // do something with Circles
}

解决方法

协方差

Covariance is safe when SomeType only describes operations that return the type parameter

IEnumerable< out T>界面可能是协方差最常见的例子.它是安全的,因为它只返回类型T的值(特别是IEnumerator< out T>但不接受任何T对象作为参数.

public interface IEnumerable<out T> : IEnumerable
{
    IEnumerator<T> GetEnumerator();
}

这是因为IEnumerator< T>也是共变的,只能返回T:

public interface IEnumerator<out T> : IDisposable,IEnumerator
{
    T Current { get; }
}

如果你有一个基类叫做Base,一个派生类叫Derived,你可以这样做:

IEnumerable<Derived> derivedItems = Something();
IEnumerable<Base> baseItems = derivedItems;

这是因为derivedItems中的每个项目也是Base的一个实例,因此我们完全可以按照我们刚才的方式进行分配.但是,我们不能指定另一种方式:

IEnumerable<Base> baseItems = Something();
IEnumerable<Derived> derivedItems = baseItems; // No good!

这不安全,因为不能保证Base的每个实例也是Derived的一个实例.

逆变

Contravariance is safe when SomeType only describes operations that accept the type parameter

动作< in T>代表是一个很好的例子.

public delegate void Action<in T>(T obj);

它是安全的,因为它只接受T作为参数,但不返回T.

Contravariance可以让你做这样的事情:

Action<Base> baseAction = b => b.DoSomething()
Action<Derived> derivedAction = baseAction;

Derived d = new Derived();
// These 2 lines do the same thing:
baseAction(d);
derivedAction(d);

这是因为将Derived的实例传递给baseAction是完全可以接受的.但是,它不会相反的方式:

Action<Derived> derivedAction = d => d.DoSomething()
Action<Base> baseAction = derivedAction; // No good!

Base b = new Base();
baseAction(b);    // This is OK.
derivedAction(b); // This does not work because b may not be an instance of Derived!

这不安全,因为不能保证Base的实例也是Derived的一个实例.

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读