HTML5技术

那些年搞不懂的术语、概念:协变、逆变、不变体 - 农码一生(2)

字号+ 作者:H5之家 来源:H5之家 2016-08-30 17:00 我要评论( )

// 协变 IMotionTeacher x = new RunTeacher ();IMotion People y = (IMotionPeople ) x; // 逆变 IMotionPeople x2 = new RunPeople ();IMotion Teacher y2 = (IMotionTeacher ) x2;IMotion Teacher y3 = (IMotion

//协变 IMotion<Teacher> x = new Run<Teacher>(); IMotion<People> y = (IMotion<People>)x; //逆变 IMotion<People> x2 = new Run<People>(); IMotion<Teacher> y2 = (IMotion<Teacher>)x2; IMotion<Teacher> y3 = (IMotion<Teacher>)new Run<People>();

天才的我发现编译成功了,没有任何问题!且还可以同时协变、逆变??不对,真的天才了吗?我们运行试试:

看来我还是太单纯了,如果真的这么容易绕过去,Microsoft又何必去搞个out、in关键字。

对于同一个泛型参数,我们既想有协变性又想逆变性,咋办?答案是不可行。这就会出现第三种情况,既不可以协变又不可以逆变。称为不变性。

(我们在IMotion定义两个方法)

IMotion<T> { T Show(); void Match(T t); }

上面我们测试过,代码直接强制转换是不能实现协变、逆变的。那么我们只能通过out、in来实现。如果现在我们在泛型参数添加out或in属性会如何?:

我们发现out和in都不能用。在用out时,有个传入参数为泛型 void Match(T t) 的方法。使用in时,有个返回参数为泛型 T Show() 的方法。现在就出现了是矛更锋利,还是盾更坚硬的问题了。

最后结果是:都不能用,既不能协变,也不能逆变。此为不变体。

小知识:

C#4.0之前 IEnumerable<T> 、 IComparable<T> 、 IQueryable<T> 等接口都不支持可变性,在4.0及之后才支持。因为4.0之前定义的泛型接口没有添加out、in关键字,有兴趣可以切换版本看看。

延伸思考

为什么in[输入参数]就只能逆变?分析如下:

People { } Teacher : People { { get; set; } } IMotion<in T> { void Match(T t); } Run<T> : IMotion<T> { public void Match(T t) { //假设中间有很多逻辑..... } }

为什么out[返回值]只能协变?分析如下:

People { } Teacher : People { Salary { get; set; } } IMotion<out T> { T Show(); //void Match(T t); } Run<T> : IMotion<T> { public T Show() { return default(T); } //public void Match(T t) //{ // //假设中间有很多逻辑..... //} }

这里有两个关键点:

  • 传入参数(in)是把参数当成父类来用,显然可以逆变(子类当成父类来用[里氏替换原则]),但是却不可以把父类当子类来用(如:子类存在有而父类没有的方法或属性)
  • 返回值(out)返回值类型用父类来接收,显然可以协变(父类可以接收一切子类),但却不可用子类接收父类数据(如:父类代表的对象不能强制转给子类[string str = (string)objcet])
  • 。。。是不是有点越想越头晕,想不明白就慢慢想。自己动动手。

    如果实在想的头大,就把它当成是乌龟的屁股(龟腚\规定)吧,知道是C#做的一种安全限制!

    总结

    关于泛型接口、泛型委托的可变性:

  • IEnumerable<string> list = new List<string>();  
    IEnumerable<object> list2 = list; //协变
    IEnumerable<object> list2 = new List<string>();  //(也可以直接写成这样)

  • IComparable<

  • 注意:

     

    好了,今天就到这里。没啥高深的技术知识,主要为理解协变、逆变、不变体等术语和概念。

    本文已同步至索引目录:《》

     

    同类文章推荐:

     

     

    1.本站遵循行业规范,任何转载的稿件都会明确标注作者和来源;2.本站的原创文章,请转载时务必注明文章作者和来源,不尊重原创的行为我们将追究责任;3.作者投稿可能会经我们编辑修改或补充。

    相关文章
    • 开源的那些事儿 (一)- 如何看待开源 - LeftNotEasy

      开源的那些事儿 (一)- 如何看待开源 - LeftNotEasy

      2016-08-24 10:00

    • 那些年我们一起过的JS闭包,作用域,this,让我们一起划上完美的句号。 - 追梦子

      那些年我们一起过的JS闭包,作用域,this,让我们一起划上完美的句号

      2016-08-19 18:00

    • 【腾讯Bugly干货分享】H5 视频直播那些事 - 腾讯bugly

      【腾讯Bugly干货分享】H5 视频直播那些事 - 腾讯bugly

      2016-08-14 15:00

    • 那些牛掰的 HTML5的API(二) - 小花大方

      那些牛掰的 HTML5的API(二) - 小花大方

      2016-06-16 13:00

    网友点评
    s