C#中的冗余?

C#中的冗余?,c#,.net,generics,programming-languages,C#,.net,Generics,Programming Languages,以以下片段为例: List<int> distances = new List<int>(); 列表距离=新列表(); 冗余是语言设计者想要的吗?如果是,为什么?你可以说: var distances = new List<int>(); var距离=新列表(); 因为我们沉迷于编译器和编译器错误。C#在添加了功能支持之后,肯定变得不那么冗长。静态类型/C语法的历史产物;比较Ruby示例: distances = [] 这有什么可重复的 List&l

以以下片段为例:

List<int> distances = new List<int>();
列表距离=新列表();

冗余是语言设计者想要的吗?如果是,为什么?

你可以说:

 var distances = new List<int>();
var距离=新列表();

因为我们沉迷于编译器和编译器错误。

C#在添加了功能支持之后,肯定变得不那么冗长。

静态类型/C语法的历史产物;比较Ruby示例:

distances = []

这有什么可重复的

List<int> listOfInts = new List<int>():
List listofits=new List():
翻译成英文:(编辑,稍作澄清)

  • 创建一个List类型的指针,并将其命名为listofInts
  • listOfInts现在已创建,但它只是一个不指向任何地方的引用指针(null)
  • 现在,在堆上创建一个List类型的对象,并返回指向listOfInts的指针
  • 现在ListofIts指向堆上的列表
当你思考它的作用时,不会太冗长

当然还有另一种选择:

var listOfInts = new List<int>();
var listOfInts=new List();
这里我们使用的是C#的类型推断,因为您要立即为其赋值,C#可以通过刚刚在堆中创建的对象确定要创建的类型


要完全理解CLR如何处理类型,我建议阅读。

针对C#3.0(与.Net 3.5相对应)的编译器改进消除了一些此类内容。因此,您的代码现在可以编写为:

var distances = new List<int>();
var距离=新列表();
更新后的编译器更擅长根据语句中的附加信息确定类型。这意味着需要为赋值或作为泛型的一部分指定类型的实例更少


尽管如此,仍有一些领域需要改进。有些是API,有些只是由于强类型的限制。

您的特定示例确实有点冗长,但在大多数方面,C#相当精简

我更喜欢这个(C)

对此(VB.NET)


现在,您选择的特定示例是关于.NET的,这有点长,但我不认为这是C#的错。也许这个问题应该重新表述为“为什么.NET代码如此冗长?”

,因为声明类型不一定与初始化它有任何关系

我可以申报

List<int> foo; 
列出foo;
然后让它稍后初始化。那么冗余在哪里呢?可能它从另一个函数(如BuildList())接收值


正如其他人提到的,new-var关键字允许您绕过这个问题,但是您必须在声明时初始化变量,以便编译器能够知道它是什么类型

代码显得多余的原因是,对于新手程序员来说,它似乎在两次定义相同的东西。但这不是代码所做的。它定义了两个恰好属于同一类型的独立事物。它定义了以下内容:

Person[] coworkers = new Employee[20];
  • 一个名为距离的变量,类型为
    列表
  • 堆上类型为
    List
    的对象
  • 考虑以下几点:

    Person[] coworkers = new Employee[20];
    

    这里的非冗余更为明显,因为变量和分配的对象属于两种不同的类型(如果对象的类型派生自或实现变量的类型,则这种情况是合法的)。

    与其将其视为冗余,不如将该构造视为允许保存行的功能

    而不是

    列出距离; 距离=新列表()

    c#让你把它们放在一行上

    一行写着“我将使用一个名为distance的变量,它将是List类型。”另一行写着“分配一个新列表并调用无参数构造函数”

    这是不是太多余了?也许。不过,这样做会给你带来一些好处

    1。将变量声明与对象分配分开。允许:

    IEnumerable<int> distances = new List<int>();
    // or more likely...
    IEnumerable<int> distances = GetList();
    
    IEnumerable distance=new List();
    //或者更有可能。。。
    IEnumerable distance=GetList();
    
    2.它允许编译器进行更强大的静态类型检查——当声明与赋值不匹配时,编译器会出现错误,而不是运行时错误

    这两个都是编写软件所必需的吗?没有。有很多语言不这样做,并且/或者在许多其他方面存在差异

    “医生!我这样做很痛!”——“别再那样做了”

    如果你发现自己不需要或不想要c#提供给你的东西,试试其他语言。即使你不使用它们,了解其他的方法也能极大地促进你处理问题的方式。如果你真的用一个,太好了


    无论哪种方式,您都可以找到足够的视角,让自己说“我不需要c编译器强制执行的严格静态类型检查。我将使用python”,而不是将c定义为太过冗余。

    重新一致性本身并不是有意的,但这是所有变量和字段都需要有类型声明这一事实的副作用。当您考虑到所有对象实例化也在新表达式中提到类型名称时,您会得到冗余的语句

    现在使用var关键字进行类型推断,可以消除冗余。编译器足够聪明,可以把它弄明白。下一个C++也有一个<强> >自动>强>关键字。 不过,他们引入var的主要原因是匿名类型,它们没有名称:

    var x = new {Foo = Bar, Number = 1};
    

    正如其他人所说:
    var
    消除了冗余,但它具有潜在的负面维护后果。我想说,它也有潜在的积极维护后果

    幸运的是,埃里克·利珀特(Eric Lippert)写这篇文章比我更雄辩:

    如果读者明显知道类型,请使用var

    //Use var here
    var names = new List<string>();
    
    //but not here
    List<string> names = GetNames();
    
    //在这里使用var
    变量名称=新列表();
    /
    
    //Use var here
    var names = new List<string>();
    
    //but not here
    List<string> names = GetNames();
    
    var distances = new List<int>();
    
    var names = new List<string>();
    
    IList<string> = new List<string>();
    ICollection<string> = new List<string>();
    IEnumerable<string> = new List<string>();