关于C#和Java是一半语言的陈述意味着什么?[关闭]


32

在文章:为什么选择POCO中,有这句话:

Maciej Sobczak很好地指出:“我只是不喜欢有人给我一半的语言,并告诉我这是为了我自己的保护”。

我不明白他的意思,尽管C#是微软拥有Java的由Oracle拥有的,但这并不意味着他们持有一半的语言,不是吗?我没有发现任何证据可以证明这一句话,对此我感到很好奇。甚至对“为了我自己的保护”部分感到好奇。


12
我认为这是批评,反对让程序员做诸如自由分配和释放内存之类的事情以及那种“保护”,但是我不确定这是否就是他要提出的重点。
Kayaman '17

15
我不确定,因为他引用的文章似乎已经死了,但似乎他是在说Java和C#缺少许多C ++的“更危险”或有争议的功能,例如多重继承或模板元编程。
GoatInTheMachine

3
引号的上下文缺失(链接为404),所以您在这里只会看到人们猜测他可能的意思,或者(更可能是)人们只是表达自己的观点。如果您实际上想知道上下文,即丢失页面上的内容,最好的选择可能是直接写作者,或者尝试通过Wayback机器或类似工具查找丢失的页面。
JacquesB

2
该声明缺少要点,即使您可以处理它,也不一定总是希望用一种语言来公开软件开发的所有可能方面。当然,您可能不会在读取内存管理代码时遇到问题,但是其他开发人员可能并不会因为维护该代码而兴奋不已。 它类似于封装的概念。而且,C#确实允许您通过编译器指令,特殊属性和反射来访问很多内容,但是,并不是应该使用那些东西。
马克·罗杰斯

32
为了您自己的利益,请忽略那些认为某种语言必须具有C ++所有功能才能被视为“真实”和“完整”的人们。不必注意那些认为类型安全性,记忆安全性和明确定义的行为是“训练轮”的人。正确性已成为大多数行业中软件最重要的方面,以不关心它而感到自豪的人们很快将变得无关紧要。
Theodoros Chatzigiannakis

Answers:


162

Sobczak并不是在谈论公司所有权。他缺少的“半”语言是您在许多现代语言中无法做到的所有事情,尽管作为一名受过良好教育的计算机专家,他知道可以实现:从您喜欢的许多类中继承。将任何对象分配给任何其他没有类型约束的对象。手动控制分配和释放资源,而不是信任编译器和运行时来为他完成任务。

事实是,所有这些限制都是出于某种原因而被编入编程语言的。我们确实有允许所有这些的语言。随着时间的流逝,我们发现普通程序员在一定数量的限制和手动操作下会变得更好,因为犯下真正糟糕的错误的潜力实在太大了,以至于不值得拥有额外的功能和表现力。

(显然,这有时会使真正不需要那么多手把手的程序员感到烦恼。他们的抱怨有时是合法的。但是众所周知,人们在评估自己的技能方面很糟糕,而且许多认为不需要安全防护措施的人在实际上,很难区分真正的高级智力和普通编码人员,他们认为高级语言的限制使他们感到束缚,而普通编码人员只是认为抱怨会使他们看起来更高级,或者不知道好点。)


67
这是我转到答案。
尼尔

71
我还要补充一点,就是没有高级知识分子不需要这些限制。可以肯定地说,每个人迟早都会陷入困境。通常,智力越强,错误就越大。
尼尔

29
Java和C#的功能不仅仅在于阻止人们用脚射击自己。例如,在进行垃圾收集之前,管理内存需要大量的开发人员时间和精力,并且很难正确地进行手动内存管理。垃圾回收提高了程序员的生产率。
罗伯特·哈维

12
@RobertHarvey我100%同意。作为一名长期的C ++程序员,当我转向C#时,我对自动内存管理持怀疑态度。一旦我克服了这一点,它就解放了,不必在99%的时间担心它。它使我解放了思考其他问题的能力。
17年

8
“分配的任何对象的任何其他类型没有限制。” ......所以,dynamic
Arturo TorresSánchez17年

34

在引用的原始来源中得到了很好的解释:

我决定学习更多有关C ++的知识,并成为其忠实的热情者–这包括我对这种语言可能发展的方式的兴趣。而且,我注意到,开发有用的而不是实际应用程序需要最高端和最先进的技术。考虑到这一点,我尝试编写一些自己的库以用于不同目的(请参见下载页面),并且还尝试研究C ++ Boost开发人员的肩膀(请参见链接页面)以了解这些内容。高端技术。真正需要同时花时间开发本来应该通用且有用的库。这就是程序员永不停止学习的原因。

[…]

我一直在玩C ++和编写健壮软件的技术。为了在可靠软件领域获得更广阔的视野,我决定花一些时间来学习Ada(及相关知识),尽管Ada确实为复杂而可靠的设计而设计,但该语言似乎已被企业完全抛弃。系统。我必须承认,学习Ada确实对我有好处,因为它使我能够对自己的工作和开发方法有了更新鲜的了解。最重要的是,Ada世界中的某些想法或多或少可以直接应用于C ++,在健壮性和正确性方面取得良好的效果。

[…]

好我忘了 我发誓一天不学习Java。但是我做到了。好吧,在某种程度上,我可以读写工作代码。我读过“ Thinking in Java”(在线免费)和“ Core Java”(非在线,不是免费),我也间接参与了某些Java开发,而且...嗯,我不买它。我只是不喜欢有人给我一半的语言并告诉我这是出于我自己的保护。就像纸锤一样,它发光了,所以没有人在敲手指时会伤到自己……同样适用于C#。我选择钢制大锤,这样我就可以确定,当我要演奏男子气概时,它可以承受。
问题是-为什么这么多人使用它(Java,C#等)?嗯...也许是因为在某些地方很好。但是在某些情况下,语言和库都表明它们(最初)是为applet设计的,而不是成为万能的实用程序。它只提供了太多的东西,而提供的却很少。或作为一种解决方案,可能会加剧竞争。

当需要最大的功能和更广阔的视野时,我喜欢C ++。在C ++的表达能力不是必须的地方,像Tcl或Python这样的语言似乎很合适。它们不仅在进化方面是开放的,而且可以根据特定需要对其进行扩展和嵌入。在这些技术中,我看到了很多梦想。我也倾向于放弃C作为常规编程的语言-这似乎只是作为代码生成目标的一个合理选择,否则它很容易出错。今天,如果我有自由选择的权利(不幸的是,大多数时候并非如此),Ada可能是我更认真的项目的第二选择。

因此,换句话说,该引用的作者喜欢C ++,但他不喜欢Java,他认为Java缺少了一半的C ++。这就是报价的全部内容。


18
具有讽刺意味的是,他不喜欢C的原因与他喜欢C ++的原因完全相同,它非常开放,具有很多功能和许多错误。
GreySage

8
他认为C ++比Python更具有表现力
benxyzzy

12
@GreySage这也引起了我的注意... C容易出错,但是C#没有给您足够的功能?C与C ++相距甚远吗?C#没有“不安全”的角来提供更多控制权?有趣的观点多数民众赞成在肯定...
WernerCD

10
@WernerCD不能真正讲出不安全的C#,但是C和C ++几乎没有什么共同之处,只是您可以将基本的C90代码片段打入有效的C ++类代码片段,而编译器不会对此感到窒息。
昆汀,

23

您发布的博客中与之链接的文章已被删除,因此很难确定,但是正如Kilian所说,当他说“一半的语言”时,他可能意味着C#和Java感觉像C ++,但有很多删除了功能和结构,以使其更易于使用或更安全。

早在2006年,当撰写本文时,C#相对较年轻,Java在许多方面都还不成熟,并且在权衡安全与安全之间似乎是一个权衡取舍,而您只能选择一个,这并不是完全不合理的立场。

这些天来,这个职位根本不合理。仅考虑主流语言,C#和Java便已日趋成熟,它们借鉴了其他语言(特别是功能性)的功能来促进编写安全代码。我们也有从头开始构建的Rust和Swift等语言。

如果有人因为握住您的手而看不起一种语言,或者说某种语言难用是件好事,那么我会对他们所说的一言不发。您只需要查看由业界最聪明的人编写的每天都依赖于我们的代码中令人尴尬的错误数量,而使用“安全”语言可以避免这些错误,以了解原因。


6
我同意你在最后一段中的立场。C ++应该被称为“漏洞利用之泉”。
卡雷布·莫尔

3
另外,为了补充您的第二段内容,Java和C#都出于各种原因严重削弱了C和C ++语法,包括诱使现有C / C ++开发人员降低学习难度。随着他们的成熟,他们添加了自己的功能并拥有自己的风格,但是在早期,将它们视为“ C ++但功能较弱”更为容易,因为它们被直接定位为C ++的替代产品。
哈里森·潘恩

12

回顾档案,似乎这句话是2003年的(尽管该文章引用的是2006年的)。当时,C#的版本为1. x,它缺少许多现代功能

新的功能

C#2.0

  • 泛型
  • 部分类型
  • 匿名方法
  • 迭代器
  • 可空类型
  • getter / setter分别的可访问性
  • 方法组转换(委托)
  • 代表的协方差和反方差
  • 静态类
  • 委托推理

C#3.0

  • 隐式类型的局部变量
  • 对象和集合初始化器
  • 自动执行的属性
  • 匿名类型
  • 扩展方式
  • 查询表达式
  • Lambda表达式
  • 表达树
  • 部分方法

C#4.0

  • 动态绑定
  • 命名和可选参数
  • 通用协和逆
  • 嵌入式互操作类型(“ NoPIA”)

C#5.0

  • 异步方法
  • 来电者信息属性

C#6.0

  • 编译器即服务(Roslyn)
  • 将静态类型成员导入名称空间
  • 异常过滤器
  • 等待捕获/最终阻止
  • 自动属性初始化器
  • 仅限吸气剂的属性的默认值
  • 表情健全的成员
  • 空传播子(空条件运算符,简洁的空检查)
  • 字符串插值
  • 运营商名称
  • 字典初始化器

C#7.0

  • 输出变量
  • 模式匹配
  • 元组
  • 解构
  • 本地功能
  • 数字分隔符
  • 二进制文字
  • Ref返回和本地人
  • 广义异步返回类型
  • 表达式身体构造器和终结器
  • 表情浓郁的吸气剂和坐便器

C#7.1

  • 异步主
  • 默认文字表达式
  • 推断的元组元素名称

- “ C Sharp”,维基百科(已删除参考和链接)

在这种情况下,C#似乎是一种半语言,这可能更容易理解,因为它缺乏当今C#的许多功能。奇怪的是,它甚至没有static上课!

由于C#已与.NET绑定,因此也缺少更多内容。例如,WPF那时还不存在。都是WinForms。


静态类可能是缺少功能的不佳选择,因为Java仍然没有它们(C#类)。除非这对Java不利?
user253751 '17

1
@immibis不是故意破坏Java,但是jeeze真的吗? static类看起来像是一个原始特征。我有点想像它们早于实例化类。
纳特

2
似乎是说活塞发动机喷气机比喷气发动机喷气机早。“非实例化类”通常称为模块名称空间,除非在语言中所有代码都必须位于类内。(或将自行车称为手动车,或将固定电话称为固定电话,或...)
user253751 '17

@Nat-拥有静态类是不错的选择,但是没有静态类绝对不会改变。您可以仅使该类的所有成员成为静态成员,而如果您忘记了该类原本打算保持静态的话,那么您丢失的只是几种编译器错误。
Jirka Hanika '17

@JirkaHanika是的,static在大多数情况下,我都不是上课的忠实粉丝。老实说,我选择它作为调用的功能,因为它看起来确实很简单,是C#的原始部分。我不认为它们不是Java语言。
纳特

3

他抱怨缺乏可进行细粒度控制的语言功能。这些包括用于

  • 强制不变性(例如C ++ const关键字)
  • 控制对象的生存期和所有权
  • 控制内存使用,复制和分配方式

这使我想起了我对Java的批评之一:

一切都是指针,但指针不存在。

在C ++对象中,指针和引用是三个具有清晰语义的不同概念。在Java中,您只有伪对象指针。通过将它们混合并避免使用真正的指针语义,对象模型将变得不太清晰。

在定义良好的C ++程序中,程序员可以期望引用是有效的且非null。由于其简化的模型,Java无法做出相同的保证。

这种不太清晰的模型的症状包括空对象模式和yoda条件,例如5.equals(potentiallyNullIntegerReference)


5
这很困惑。指针(在Java中从逻辑上讲存在)不能随便使用它们。简化模型的全部目的是要提供更多保证。您可以假设更多有关某种语言的代码且限制较少的逻辑是倒退的。更多限制->更多保证。
JimmyJames

1
@JimmyJames这个短语的意思是,即使所有java类都具有隐式(yuck,btw)引用语义,您也不能拥有实际的指针。例如,无法获取对引用的“引用”。这会在几个地方削弱语言,有时需要疯狂的解决方法(请参阅Map.merge何时仅想更新地图中的值)。
昆汀,

3
@JimmyJames:在没有施加某些限制的情况下,实际上无法提供某些有用的保证。此外,某些有用的优化可能需要施加一些限制。但是,某些语言施加了毫无意义的限制,这些限制并没有为程序员提供任何有用的保证,因此不应该要求它们执行有用的优化。有些限制简直是不好的。
超级猫

3
@JimmyJames:另一方面,Java和“安全模式” C#的一些更基本的限制使它们提供了C ++不能提供的非常有用的保证:永远存在的任何引用(在C ++中是指针)被观察到可以识别特定的物体永远不会被观察到识别其他任何东西
超级猫

3
您能否提供一些报价来支持您的答案?例如AFAIK,页面未提及const。它确实提到了“函数式编程”,但是,他使用的语言是Scheme,它不是一种纯粹的函数式语言(实际上,Scheme的设计者要小心避免使用“ function”一词,并谈论“程序”),因此似乎他使用的是FP的“一流子程序”解释,而不是“参照透明性”。
约尔格W¯¯米塔格

1

我同意@Kilian的回答,但我会添加一些内容。

1-针对虚拟机而不是操作系统运行

由于Java和C#是通过虚拟机运行的,因此从逻辑上讲,由于直接在OS上进行操作,因此您可能无法完全按照自己的意愿进行操作,因为您可能会破坏VM中的某些内容。而且,由于Java被视为与平台无关的语言,因此它更具逻辑性。

2吨的应用程序不需要您需要这些东西。

确实有很多应用程序不需要您深入了解很多细节,但是如果使用要求您完成操作的语言来进行操作,则会得到:

  • 由于这些不必要的事情,有更多的可能会出现错误。
  • 更多的开发成本,管理内存和测试需要花费时间和金钱!

3-语言是根据某些选择权重成本/使用/风险来决定的,例如...一切。

使用C ++,您几乎可以做任何您想做的事情,这是C ++人员的选择。但是,数量越多,您需要处理的越多。

因此,诸如多重继承之类的事情不会仅仅因为它们是危险的事实而被放弃,它们之所以被放弃是因为实现它们需要付出一定的成本(开发,维护),而所有这些都是因为很少能正确使用并且可以通常以不同的方式重写。


多重继承的真正代价在于无法同时维持以下两项保证:(1)如果基类的成员B在中产阶级中被覆盖M,则B该成员的版本只能通过M' 访问。覆盖 (2)给定type的任何引用T,将其转换为任何超类型并转换回T将产生与原始等价的引用。这两种保证都是有用的,并且支持多重继承将需要放弃至少一个。
超级猫

-1

只需将所有限制放在高级语言(如C#和Java)中即可保护程序员。它们的存在并不是为了保护程序员免受他/她自己的侵害,而是为了保护程序员免受其他程序员的侵害!

作为程序员,我们有多少次遇到的库在其编码实践和设计上是彻头彻尾的,但是由于某种原因而被迫使用?

这些程序通常具有旧的过程编程方法的特点,缺乏封装性,大量直接内存写入,几乎没有错误捕获或处理。当在任何大型项目中尝试使用段隔离时,段追求的都是大量的。

这就是Java和C#等语言非常有用的地方。并不是说我们喜欢他们不让我们做其他语言所做的所有整洁的事情,而是因为我们享受着不必忍受的头痛,因为其他程序员会滥用其他语言可以做的整洁的事情做。

在我看来,接口在内存或执行速度方面都值得进行任何形式的权衡。我希望您可以看到,在任何限时任务关键型应用程序中,所有这些保护措施,适当的错误处理以及通常确定内存没有被占用都是好事!


这似乎并没有提供任何实质性的制作上分和5分之前解释的答案
蚊蚋

1
They exist not so much to protect the programmer from him/herself, but rather to protect the programmer from other programmers!还是要保护其他程序员免受程序员侵害?
Tobia Tesan '17

@TobiaTesan那也是:)
Akumaburn '17
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.