当前位置: 首页 > 编程语言 > C#

Java-C#类型系统有哪些缺点?分享

时间:2023-04-10 18:05:21 C#

Java/C#类型系统不足之处在哪?人们经常听说Haskell(我不知道)有一个非常有趣的类型系统。我对Java非常熟悉,对C#也有一点了解,但有时我会在类型系统上苦苦挣扎,所以一些设计适应或以某种方式更好地工作。这让我想知道...由于Java/C#类型系统的不足,不知何故出了什么问题?你如何对待他们?数组坏了。对象[]foo=新字符串[1];foo[0]=新整数(4);给你java.lang.ArrayStoreException你小心对待他们。可空性是另一个大问题。NullPointerExceptions无处不在。除了切换语言,或者尽可能使用避免它们的约定(正确初始化字段等)之外,您真的无能为力。更一般地说,Java/C#的类型系统的表现力不是很好。Haskell能给你的最重要的事情是,通过它的类型,你可以强制这些函数没有副作用。部分程序证明只是在编译时计算的表达式,使程序更可靠、可组合且更易于推理。(忽略Haskell的实现为您提供绕过它的方法这一事实)。与Java相比,调用方法几乎可以做任何事情!Haskell也有模式匹配,它给你不同的方式来创建程序;你有关于哪些函数运行的数据,通常是递归的。在模式匹配中,您可以破坏数据以查看它是什么类型,然后对其进行操作。例如,你有一个列表,它可以是空的,也可以是头和尾。如果要计算长度,可以定义一个函数:如果列表为空,length=0,否则length=1+length(tail)。如果你真的想了解更多,有两个很好的在线资源:UnderstandingHaskell和RealWorldHaskell,双倍的)。这通常很烦人,尤其是在编写通用代码时。本机类型无法泛化,您必须实例化一个包装器。泛型应该使您的代码更抽象并且更易于重用,但在Java中它们显然无缘无故地引入了限制。privatestaticTFirst(Targ[]){returnarg[0];}publicstaticvoidmain(String[]args){intx[]={1,2,3};整数y[]={3,4,5};第一(x);//首先是错误的(y);//Fine}在.NET中,即使有单独的值和引用类型,也没有这样的问题,因为他们严格地知道“一切都是对象”。ThisquestionaboutgenericsdemonstratestheinadequatenessoftheexpressivenessofthejavatypesystemMoreadvancedgenericsinJava我不喜欢这样的事实,类不是一流的对象,你不能做一些花哨的事情,比如让接口的静态方法成为一部分.Java/.net类型系统的一个基本弱点是它没有声明性的方式来指定对象的状态如何与其引用类型字段的内容相关,也没有允许方法保存引用类型参数的方式。虽然在某种意义上,运行时能够使用ICollection类型的字段Foo来表示许多不同的事物,但类型系统不可能为不变性、等价性测试、克隆等事物或任何其他此类功能提供真正的支持,不知道Foo是否代表:对集合的只读引用,没有被任何东西改变;该类可以自由地与外部代码共享此类引用,而不会影响其语义。该引用仅封装不可变状态,可能不封装身份。对类型可变但实际上未发生变化的集合的可写引用;该类只能与受信任的代码共享此类引用而不改变它。如上所述,引用仅封装不可变状态,可能不封装身份。唯一在宇宙中任何地方引用其突变的集合。引用将封装可变状态,但不封装身份(将集合替换为另一个包含相同项目的集合不会改变封闭对象的状态)。对它变异的集合的引用,它认为其中的内容是它自己的,但外部代码持有它希望附加到“Foo”当前状态的引用。该引用将封装标识和可变状态。对某个其他对象拥有的可变集合的引用,它希望附加到该其他对象的状态(例如,如果持有“Foo”的对象应该显示其他某个集合的内容)。该引用将封装身份,但不封装可变状态。假设有人想将包含Foo的对象的状态复制到一个新的分离对象。如果Foo表示#1或#2,则可以在新对象中存储Foo中引用的副本,或者对包含相同数据的新对象的引用;复制引用会更快,但两种操作都是正确的。如果Foo代表#3,那么一个适当的分离副本必须持有对一个新的分离对象的引用,该对象的状态是从原始对象复制而来的。如果Foo表示#5,那么正确的分离副本必须包含原始引用的副本——它不能包含对新分离对象的引用。如果Foo代表#4,则不能单独复制包含它的对象的状态;可以复制一堆相互连接的对象来生成状态与原始状态相同的新束,但不可能单独复制对象的状态。虽然类型系统不可能以声明方式指定对象之间可能存在的所有可能关系以及应该如何处理它们,但类型系统和框架应该可以正确生成代码以生成语义-正确的等价测试,克隆在大多数情况下,如果它知道哪些字段封装身份、可变状态、两者或两者都不封装,则方法、可变、不可变和“可读”类型可以顺利互操作等。此外,该框架应尽量减少防御性复制和包装,在这种情况下,它确保不会为传递的引用分配任何会更改它们的内容。(回复:特定于C#。)我是标记联合的忠实拥护者。类、方法、属性等的一流对象也是如此。虽然我从未使用过它们,但Python有类型类,它们基本上是表示类及其行为方式的类型。不可为null的引用类型,因此不需要进行null检查。它原本应该是C#,但被放弃了。(对此有一个StackOverflow问题。)协方差,因此我可以将List转换为List。这是次要的,但是对于当前版本的Java和C#,声明对象违反了DRY原则:Objectfoo=newObject;整数x=新整数;他们都没有元编程设施,说老C++狗有。使用“using”和缺少typedef进行复制是违反DRY的一个示例,它甚至会导致用户引发的“别名”错误等。Java'模板'根本不值一提...以上是C#学习教程:Java/C#类型系统的不足之处在哪里?如果所有分享的内容对你有用,需要进一步了解C#学习教程,希望大家多多关注。本文收集自网络,不代表立场。如涉及侵权,请点击右侧联系管理员删除。如需转载请注明出处: