将Brevity引入C#/ Java

时间:2009-04-08 13:36:18

标签: c# java oop

背景

目前,如果我想在C#或Java中创建一个new对象,我输入的内容类似于以下内容:

  

List<int> listOfInts = new List<int>(); //C#
   ArrayList<String> data = new ArrayList<String>(); //Java

C#3.0试图通过实现以下编译器技巧来提高简洁性:

  

var listofInts = new List<int>();

问题

由于编译器已经知道我想要创建某个特定类型的新对象(事实上我在实例化它而没有为它分配null引用或指定一个特定的方法来实例化它),那为什么我不能做以下事情?

    //default constructors with no parameters:
    List<int> listOfInts = new(); //c#
    ArrayList<String> data = new(); //Java

跟进问题:

  1. 这种方法可能存在哪些缺陷。我可以遗漏哪些边缘案例?
  2. 是否还有其他方法可以缩短实例化(不使用VB6-esque var)并仍然保留意义?
  3. 注意:我在这样的功能中看到的主要好处之一是清晰度。让我们说var不受限制。对我来说它没用,它会从右边获得作业,为什么要这么麻烦?对我而言,New()实际上缩短了它的含义。它是一个新的()无论你声明什么,对我来说都是清晰简洁的。

15 个答案:

答案 0 :(得分:33)

C#保存在另一端:

var listOfInts = new List<int>();

答案 1 :(得分:16)

  

我可以遗漏哪些边缘案例?

我在1月份的blog上简要讨论了这种可能的C#语法。请参阅该帖子的评论,以获取一些读者对语法优缺点的反馈。

  

是否还有其他方法可以缩短实例化(不使用VB6-esque var)并且仍然保留含义?

可能,是的。

然而,C#中的“var”与VB6中的“变体”完全不同。 “var”与“对象”的含义不同,也不引入动态类型或鸭子类型。它只是eliminating the redundant stating of the type of the right hand side的语法糖。

答案 2 :(得分:14)

在C#3中,已经存在局部变量的镜像,隐式输入:

var listOfInts = new List<int>();

doesn't work for non-local variables

在Java中,类型推断会考虑到赋值目标,因此使用静态导入和狡猾库(如Google Java Collections)可以编写代码,例如:

List<Integer> integers = newArrayList();

请注意,这会保持变量基于接口,同时在构造方面指定实现,这很好。

答案 3 :(得分:5)

在新的Java 7提案中,有一个类型推断提议,这将使生活更轻松。仿制声明。

e.g。

Map<String, List<String>> anagrams = new HashMap<String, List<String>>();

VS

Map<String, List<String>> anagrams = new HashMap<>();

有关详细信息,请参阅here

答案 4 :(得分:4)

您的版本不太可读,抱歉。

代码意味着人类只能通过机器阅读。

答案 5 :(得分:4)

通常,在使用面向对象的方法时,通常会创建比变量更具体类型的实例。此外,使用不太具体的类型或界面通常是个好主意。在这些情况下,这没有意义。

想想接口:

IList<int> = new(); // What instance should the compiler infer?

此外,从技术角度来看,操作的签名不包括其返回类型,因此这种分配与正常情况完全不同。

答案 6 :(得分:2)

C#有:

var listOfInts = new List<int>();

实现了同样的目的。

答案 7 :(得分:2)

在C#中,有

var listOfInts = new List<int>();

答案 8 :(得分:2)

C#3.0有一种减少输入重复的机制,但它是通过对你声明的类型含糊不清来完成的,但在你构建的类型中是明确的:

e.g。

var listOfInts = new List<int>();

答案 9 :(得分:2)

我同意这将是一个很好的功能。一个更好的例子是需要更多打字的地方:

Dictionary<string, int> myDictionary = new Dictionary<string, int>();

如果可以将实例化为:

,生活会更容易,尽管只是轻微的
Dictionary<string, int> myDictionary = new();

Dictionary<string, int> myDictionary = { {"a",1}, {"b",2} };

答案 10 :(得分:0)

在C#中,theres已经是这样的了:

var listOfInts = new List<int>();

答案 11 :(得分:0)

在Java中,这没有多大意义,因为您通常会使用接口类型声明变量:

List<String> myList = new ArrayList<String>();
但是,在大多数情况下,如果没有编译器警告,可以省略泛型类型的声明,例如:

List<String> myList = new ArrayList();

但是,由于Java总是非常明确且对所有内容都很冗长,所以这可能保持不变。

(为什么有人会在没有IDE的情况下编写C#或Java代码?)

编辑:

哦,有一个提议!甜。谢谢,Brian。

答案 12 :(得分:0)

Java已经

 List<String> data = newList(); //Java, where newList() is a helper method to create an ArrayList();
 List<String> data = newList("Hello", "World"); // a helper method which takes a T....
 Map<String, List<String>> anagrams = newMap(); // Java, where newMap creates a new  HashMap();

答案 13 :(得分:0)

从左到右阅读代码(如果您的语言不是从右到左)。

这意味着

var someTypeWithALongName = new TypeWithALongName<TypeParamOne,TypeParamTwo>(); 

将重要数据放到正确的部分(用于初始化变量的实际方法/类型构造函数,代码的读者可以从中推断出有关实际var类型的知识),这不太方便与它位于左侧时的情况相比。

然而作者建议从左到右阅读人类要好得多 - 我们声明一个已知类型的变量(不是一些未知的var类型)

TypeWithALongName<TypeParamOne,TypeParamTwo> someTypeWithALongName = new();

现在重要数据(变量将具有的实际类型)在左侧,我们可以扫描左侧的代码并注意实际类型,而不是var声明的栅栏

var x = ....;
var y = ....;
var z = ....;
var xy = ....;

Code Complete书指出可读性是最重要的,我发现很难不同意这一点。保存5(或更少)秒并使用var而不是真实类型很容易使得以后的代码审查更加困难,可能会使代码根据正确的部分无法读取,并且可能会产生很难注意到的意外错误。所有的值都是..节省5秒而不是为变量写一个声明类型?

现在众所周知,实际的代码编写并没有花费很多时间用于创建程序的整个时间,特别是如果它是产品程序) (通常有调试,系统测试,组件集成,设计,会议等,实际代码编写的时间很多

另一方面,当我们输入

TypeWithALongName<TypeParamOne,TypeParamTwo> someTypeWithALongName = new();

我发现很难不将该行解释为调用类型的默认构造函数并创建该类型的实例。

同样在初始化墙的情况下,我们在行的开头得到实际的类型名称,因此它易于从上到下扫描代码,我们不必将眼睛移动到字符串的末尾以了解实际的内容这个具体的var初始化确实如此。(如果你认为扫描行到结束是一个免费的滚动任务,首先它不是,并且var不仅仅是扫描,它还检查初始化的正确部分是否有错误(例如,调用具有不同返回类型的方法或var允许的一些其他类型的错误))

TypeWithALongName<TypeParamOne,TypeParamTwo> someTypeWithALongName = new();
AnotherTypeWithLongNname someAnotherTypeWithLongNname = new();
List<int> idList = new();
Dictionary<int,string> lookupDict = new ();

我反对var使用除了它是为(匿名类型,通常来自LINQ)创建的情况,如果我们要在代码中节省一些空间,我宁愿任何代码减少策略正在发生在右边。

我还认为使用var来声明变量并将其赋值给某个方法的返回值会使代码分析变得非常复杂,并且通常会引入难以捕获的错误,如果var不是,则可以完全避免可能对于这种情况,所以如果只有构造函数代码可以缩短为new()new(ParamType param)而不是其他方法,如

var x = someTypeLocalIstance.ComputeResults()

可读性只会再次获胜。

答案 14 :(得分:0)

我认为微软是这样做的:a)var xy = new MyClass();

而不是这样:b)MyClass xy = new();

因为a)能够持有匿名类,而b)是不可能的。