假设不需要向后兼容,C#或.Net功能会中断吗?[关闭]


18

任何产品或框架都会发展。主要是为了满足用户需求,利用新的计算能力并使其变得更好而做的。有时,主要设计目标也会随产品而改变。C#或.net框架也不例外。我们看到,今天的第四版与第一版相比有很大不同。但是事情成为阻碍这种向后兼容的障碍。

在大多数框架/产品中,如果不需要支持向后兼容性,则某些功能将被切断。据您介绍,C#/。net中的这些功能是什么?

请为每个答案提及一项功能。



4
根据指导方针,该问题显然不是建设性的,而根据奇妙的答案显然是建设性的。投票重新开放。
psr

1
可惜它关闭了,也许埃里克(Eric)还是会在此发布博客,而不是在这里回答?
jk。

Answers:


35

匿名方法。我认为每个人都同意,与我们添加到C#3.0中的lambda语法相比,为C#2.0选择的匿名方法语法笨拙而笨拙。使用两种几乎完全相同的语法来完成同一件事是非常不幸的。


1
商定的匿名方法在没有lambda的情况下非常有用...现在它们只是多余的。
迈克尔·布朗

9
匿名方法有一个特殊功能,那就是比lambda表达式要好得多。
探索

1
在这一点上,我什至不记得C#中匿名方法的语法。如果出于某种奇怪的原因我需要使用一个而不是lambda,则必须查找它。
Kyralessa

33

我会摆脱非通用集合。他们真是可恶...在很多情况下,我在使用linq,不得不做类似的事情

var customObjects = container.CustomObjects.Cast<CustomObject>();

每次我必须这样做时,我的灵魂就会死掉一小部分。


太好了

1
并非.NET的所有端口都支持泛型。.NET Micro是一个示例。如果CustomObjects永远不会移到该平台,则可能不适用。
goodguys_activate 2011年

2
那是没有灵魂的好处。
CaffGeek 2011年

29

作为类型无效。为什么在地球上是“无效”类型?它没有实例,没有值,您不能将其用作泛型类型参数,形式参数类型,局部类型,字段类型或属性类型。它没有任何意义。实际上,这是关于方法调用对虚拟机堆栈有什么影响的事实但是虚拟机就是这样:虚拟机。实际的机器会将返回的值放在寄存器中(通常是x86上的EAX),根本不影响堆栈!虚空作为一种类型只是个坏主意。

更糟糕:在指针类型中使用时void*,意味着完全不同使用时,与在返回类型中使用时的。现在,它的意思是“指向未知类型的存储位置的指针”,这与“不返回任何值的方法”的含义没有任何关系。

我们可以将替换void*为指针类型IntPtr。(和void**IntPtr*等)。我们可以更换空与“单位”,有一个值,即空类型返回类型。然后,CLR的实现可以确定一个单元类型的函数调用可以适当地优化其对寄存器或堆栈的使用,因为知道可以安全地忽略“返回”的null。

在这样的世界里,你不再需要分开Func<A, R>Action<T>代表。Action<T>就是Func<T, Unit>


4
... Task只是一个Task<Unit>。重新实现异步CTP的库位让我真的很想...
Jon Skeet

24

空语句;。容易出错,几乎总是输入错误,并且没有给您带来尚未表达的附加含义{}


7
更不用说在64位JIT </ snark>下的巨大性能损失。
Jesse C. Slicer

7
空语句会影响性能吗?这是为什么?
2011年

22

引用类型数组的不安全协方差。启用类型安全协方差后IEnumerable<T>,至少对数组协方差的某些需求已消失。(如果我们有一个协变的只读列表接口,那么我们根本就不需要它。)


当我看到问题标题时,我绝对会写下这句话–你打败了我:(
Chris Smith

1
接收协变数组引用并安全地写入从中读取的数组引用的功能非常有用。如果像是IList<T>从继承而来的,IReadableList<out T>并且是非泛型的IPemutable,它可以支持排序之类的事情,但是数组更容易支持它。
超级猫

14

一元加运算符。一直以来都是最有用的运算符。如果我们不必为了向后兼容而保留它,我会心跳加速。谁用这个东西,有人吗?

(澄清:一元加运算符+x不是预增运算符++x,不是后增运算符x++,也不是二进制加法运算符x+y。)


1
(int i = 0; i <ceiling; i ++)
Michael Brown

13
他不是在谈论前增和后增运算符:他是在谈论一元加号,它与数字的负号相反+1 == 1。几乎没有操作,这真是太糟糕了。
Jesse C. Slicer

8
这不仅涉及对机器可读输出的影响,还可以改善人类代码的外观:if(a == +1 || a == -1){...}
Thomas Bratt

5
@ShuggyCoUK:尤其奇怪的是它是可重载的。因为那经常发生。您知道,您是如何编写JavaScript的,并且您认为,我希望JS使我能够像C#一样使用户定义的一元加运算符语义成为可能
埃里克·利珀特

2
@Eric我没有意识到它是可重载的。哇,您可以这样做:)
ShuggyCoUk 2011年

12

将数字文字默认为 double

对于大多数商务应用程序而言,decimal还是更合适……或者最好是删除默认值的概念,然后强迫开发人员真正做出选择。

(“删除默认值”也适用于其他一些情况。例如,我已经放弃说服所有人默认应该密封类,但是我认为说服人们应该考虑的内容更容易是否应该密封其新类,并使其明确。)


我可能倾向于识别那些隐含不能精确表示为double / float的值的​​字面量……
ShuggyCoUk 2011年

如果他们到Java -他们是指由Joshua布洛赫“设计或文档继承,否则禁止它”的神圣经文martinfowler.com/bliki/DesignedInheritance.html IIRC科特林默认完成了密封类,因此该行业正在走向在这方面更好的方向。
Elazar Leibovich 2012年

为什么要密封班级?
2013年

@詹姆斯:正是乔什给出的原因。设计一个以合理,一致的方式实现继承的类需要花费时间-而这样做却不知道如何使用继承会更糟。
乔恩·斯基特

1
@Pacerier:例如,考虑不变性。非密封类不能声称是不可变的,因为子类会引入可变性。
乔恩·斯基特

7

这不是功能,而是指南,但我认为这很重要,因为它已经成为人们公认的最佳解决方案,已经根深蒂固:

官方模式来实现IDisposable

这很麻烦,并且有更好的方法


6

知道各种计时器类之间有很大的差异。但是我们还是不能摆脱其中的一两个吗?


4

方法和类型的ArrayList<T>,成为过时的LINQ的,例如:

  • Array.TrueForAll 可以替换为 Enumerable.All
  • Array.FindAll 可以替换为 Enumerable.Where
  • List<T>.ConvertAll 可以替换为 Enumerable.Select
  • Predicate<T> 可以替换为 Func<T, bool>
  • Converter<T,R> 可以替换为 Func<T, R>
  • IComparer<T> 真的应该成为代表 Func<T, T, int>

3
我喜欢Predicate<T>它,因为它抓住了函数使用方式的意图,并节省了一点点键入。
Zebi

2

非泛型委托 与非泛型集合一样,由于我们具有Func和Action系列,因此非泛型委托也无济于事。我将在三个参数处截断变体。如果您有三个以上的参数,请构造一个结构并将其用作单个参数。声明用于事件处理的特定委托不是很干。


3
您将如何定义使用Action或Func进行引用int的方法的委托?您如何用Func 定义组合器?也就是说,没有办法说“代表DD(D d);”。与Func。
埃里克·利珀特

2
嗯...我纠正了。这就是为什么我放弃了
Michael Brown

@EricLippert:我想看到一个特殊的委托类,它将通过CLR magic包含“所有” arity的委托以及值/引用参数的组合[在魔术类中搜索具有适当格式的名称的委托将创建类型],并让所有具有适当签名的委托都从中继承。想要特定委托的代码仍需要精确的类型,但是想要特定签名的代码可以使用魔术名称。
2014年


-2

Winforms
不必在两个桌面平台之间导航会很高兴。WPF是前进的方向,因此对于拥有完整的平台级冗余感到沮丧。


的WinForms似乎更稳定,速度更快,并且bug更少比WPF ...
Pacerier

当您只需要破解一个小型桌面应用程序时,WPF就是一大杀手。
Kyralessa 2015年

WPF之间似乎已经过时了,而不再使用WinRT。但是,在我看来,Winforms在业务开发方面比WPF更活跃。另请参见stackoverflow.com/questions/913417/...
布朗博士
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.