百科问答小站 logo
百科问答小站 font logo



编程语言的类型推断怎么解决协变和逆变的问题? 第1页

  

user avatar   jeffz 网友的相关建议: 
      

轮百万和 @Ivony 讲的都太简单,其实协变逆变本身和C#什么的没什么关系,理论上来说协变逆变可以搞得很完备很复杂,复杂到以绝大部分人的脑力不能很快看出两个类型之间有没有协变逆变的关系。假如你准备好了可以看这里:


Programming Languages by Dan Grossman at Coursera.org


Section 8其中一部分是在讲Subtyping,基于一种自定义的也是最基本的Record类型(即 { a: { b: t1, c: t2 }, d: t3 } 这种)怎么判断类型之间是否兼容。视频的话可以从“Subtyping From the Beginning”部分开始看,看到“Depth Subtyping”,也可以直接看Reading Notes。


当然之前说了,因为这个判断实在太复杂,所以在真正使用的时候语言基本都是做了限制的,例如C#中只对interface和delegate提供了协变逆变。


此外,实现时C#也根据.NET的特性进行了限制,就像 @Ivony 说的那样,C#支持协变逆变的原则是“IL代码完全一致”。这导致了一点就是,虽然struct类型也是可以赋值给object的,但是IEnumerable<int>不能赋值给IEnumerable<object>,因为在使用IEnumerable<int>时的代码和IEnumerable<object>不同,而IEnumerable<string>和IEnumerable<object>是完全相同的。



总之理论是一回事,实现是另一回事情,是要考虑到程序员是否可以接受以及实现起来是否方便的。另外假如有兴趣的话,可以试着写一段程序,基于代码里的Record类型判断两个Record是否兼容,对编程能力是挺好的锻炼。


user avatar   Ivony 网友的相关建议: 
      

C#的协变和逆变本质上就是通知编译器忽略没有必要的类型检查。


如果你看IL就会发现,对于:

       ((object) str).ToString();//str是string类型     

       ((object) obj).ToString();//obj是object类型     

或者

       obj.ToString();//obj是object类型      

这几个表达式生成的IL没有区别的,也就是说这里的类型转换其实没有真正的转换,仅仅只是确保调用的ToString方法是object声明的那个。


这也就是派生类对象可以直接当作基类对象使用无需额外的指令。


我当初问 @装配脑袋 C#是如何处理协变和逆变的时候,他说:不需要处理,假装那个对象是这个类型就好了。




  

相关话题

  数学和编程中,「函数」的概念相同在哪里,不同在哪里? 
  python中的lambda 和java中的lambda有什么不同? 
  毫无编程基础的小白准备学习C语言,用VC6还是VS2015? 
  为什么C++的 extern "C" 里面可以使用C里面不存在的STL和引用&等C++才有的特性 ? 
  go语言,局部变量什么时候回收? 
  Python 语言有什么奇技淫巧吗? 
  我听说以前的系统没有图形界面,那他们是用 C# 等语言直接敲代码吗? 
  全世界有上千种编程语言,为什么程序员都只学习那几个主流语言? 
  应该如何理解 Erlang 的「任其崩溃」思想? 
  在C语言中,math.h中定义的各种数学函数在电脑上具体是怎么实现的? 

前一个讨论
Facebook 为什么不用 .NET?
下一个讨论
一个氢弹和一个原子弹绑在一起,同时爆炸,会发生什么情况 ?





© 2024-12-22 - tinynew.org. All Rights Reserved.
© 2024-12-22 - tinynew.org. 保留所有权利