奇怪的是,人们在C#中忍受了什么

2020-08-15 18:18:17

这是隐含的信息丢失,对准确编程的腐蚀性几乎与空指针一样。与此类似,在C#笔记本中,

第一个函数计算表达式并显示它,第二个函数计算表达式并丢弃它。

21世纪的任何语言都不应该有隐性信息损失。可能有C#分析器可以防止这种错误,或者您有其他选择。

2.";没有对象表达式";(WAS";无法使用表达式实现接口或抽象类,这意味着愚蠢的额外类";)。

让我们假设您想要实现ICompeller<;T>;(或者其他一些没有现有实现方式的接口)。

数组。Sort(Candients,new SortByRlevanceAndOrder<;(Type type,String mimeType,int index)>;(tup=>;tup.。类型,tup=>;tup。Index));私有类SortByRlevanceAndOrder<;T>;:ICompeller<;T>;{Func<;T,Type>;_TypeKey;Func<;T,int>;_indexKey;public SortByRlevanceAndOrder(Func<;T,Type>;TypeKey,Func<;T,int。}public int Compare(T inp1,T inp2){var type1=_TypeKey(Inp1);var type2=_TypeKey(Inp2);var index1=_indexKey(Inp1);var index2=_indexKey(Inp2);if(type1.。IsRlevantFormatterFor(类型2)&;&;类型2。IsRlevantFormatterFor(Type1))返回比较器<;int>;。默认值。比较(index1,index2);Else if(type1.。IsRlevantFormatterFor(Type2))返回1;否则返回-1;}}。

这个类毫无意义,并且大喊“C#不能在表达式中创建对象实例!”(";C#t‘t create object instance in Expression!";)。相反,您应该能够使用表达式实现接口,例如F#对象表达式。

设Compeller={new ICompeller<;_>;成员x。Compare((type1:type,index1:string),(type2,index2))=if(type1.。IsRlevantFormatterFor(类型2)&;&;类型2。IsRlevantFormatterFor(Type1))返回Compare index1 index2 Else If(type1.。IsRlevantFormatterFor(Type2))返回1,否则返回-1}数组。排序(候选项、比较器)

有成百上千个这样的例子(其中很多也涉及到重要的变量捕获),缺少这个特性使得C#作为一种混合的函数-对象语言非常成问题。您可以使用委托实现函数,也可以用旧方法编写类,但是在函数代码中实现函数对象是非常扭曲、冗长且容易出错的。

注意,这不是Java的内部类,它是一个复杂的,而不是简化的野兽。

这是众所周知的(他们试图将其引入C#6),但基本上为什么要编写所有这些。

私有类SortByRlevanceAndOrder<;T>;:ICompeller<;T>;{Func<;T,Type>;_TypeKey;Func<;T,int>;_indexKey;public SortByRlevanceAndOrder(Func<;T,Type>;TypeKey,Func<;T,int>;Var type2=_TypeKey(Inp2);var index1=_indexKey(Inp1);var index2=_indexKey(Inp2);...}}。

私有类SortByRlevanceAndOrder<;T>;(Func<;T,Type>;TypeKey,Func<;T,int>;indexKey):i比较器<;T>;{public int Compare(T inp1,T inp2){var type1=TypeKey(Inp1);var type2=TypeKey(Inp2)。

这意味着在进行对象编程或函数对象编程时,您必须不断地手动填充类的字段,从而使将代码从表达式流畅地移动到成员变得更加困难。

这是C#在编写任何类型的对象编程代码时的一个长期问题。结果,C#程序员总是手工进行字段转换。

这个特性从90年代起就在很多语言中出现了(我不确定是不是第一个,OCaml从1994年开始就有这个特性),在我看来,21世纪的任何对象编程语言都应该支持这个特性。

4.";没有列表表达式,包括生成列表";(使HTML DSL变得一团糟)。

这里是一个用于HTML生成的C#DSL示例。这没问题,C#(问题出在语言上,而不是代码上)。

Var Headers=新列表<;IHtmlContent>;();Header。添加(th(i(";index";);标题。AddRange(df.。列。SELECT(c=>;(IHtmlContent)th(c.name);var row=new list<;list<;IHtmlContent>;>;();var Take=20;for(var i=0;i<;df)。排好了。Count;i++){var cells=新建列表<;IHtmlContent>;();单元格。Add(td(I));foreach(df中的var obj.。行[i]){单元格。Add(td(Obj));}行。Add(单元格);}var t=表格(标题(页眉),tbody(行。SELECT(r=>;TR(R);编写器。Write(T);

请注意,在此过程中,我们必须为集合创建可变数据。这是因为C#除了";C#迭代器方法之外,没有任何像F#列表/序列/数组表达式那样的表达式,这对于这种生成来说是矫枉过正的。与此进行比较:

表[][thead[][th[][str";index";]for c in df.Columns do th[][str c.Name]]tbody[][for i in 0..。Int df.Rows.Count do tr[][td[][Embed i]for o in df.Rows。[int64 i]执行td[][嵌入o]。

斜视,看起来像HTML(在F#服务器端代码和客户端代码中广泛使用)。

在C#中,有一些语法广泛地使用ParamArray(Params)参数加上LINQ,或集合初始化式,甚至LINQ查询。但。

这往往不能处理真正生成的情况,即元素有条件地位于集合中,使用或循环,或者将集合追加在一起。

在实践中,这需要使用真正扭曲的语言功能组合,而且看起来仍然不像HTML。

这里缺少的基本特性是构建不可变列表/集合表达式的轻量级方式,包括生成性。

用于生成简洁、不可变的数据的强大语言特性对于当今的客户端和服务器编程是必不可少的。