C#中的冗余?

时间:2008-09-26 02:43:28

标签: c# .net generics programming-languages

采取以下片段:

List<int> distances = new List<int>();

语言设计者是否打算实现冗余?如果是这样,为什么?

17 个答案:

答案 0 :(得分:74)

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

  1. 名为List<int>类型的距离的变量。
  2. 类型为List<int>的堆上的对象。
  3. 请考虑以下事项:

    Person[] coworkers = new Employee[20];
    

    这里非冗余更清晰,因为变量和分配的对象有两种不同的类型(如果对象的类型派生自或实现变量的类型,那么这种情况是合法的。)

答案 1 :(得分:15)

对此有什么减少?

List<int> listOfInts = new List<int>():

翻译成英文:(编辑,清理一点澄清)

  • 创建List&lt; int&gt;类型的指针并将其命名为listofInts。
  • listOfInts现在已创建,但它只是一个指向无处的引用指针(null)
  • 现在,创建一个List&lt; int&gt;类型的对象在堆上,并将指针返回给listOfInts。
  • 现在listOfInts指向List&lt; int&gt;在堆上。

当你想到它的作用时,并不是真的很啰嗦。

当然还有另一种选择:

var listOfInts = new List<int>();

这里我们使用的是C#的类型推断,因为你要立即分配它,C#可以确定你想要在堆中创建的对象创建什么类型。

为了完全理解CLR如何处理类型,我建议阅读CLR Via C#

答案 2 :(得分:10)

你总是可以说:

 var distances = new List<int>();

答案 3 :(得分:9)

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

幸运的是,Eric Lippert比我更有说服力地写了这篇文章: http://csharpindepth.com/ViewNote.aspx?NoteID=63 http://csharpindepth.com/ViewNote.aspx?NoteID=61

答案 4 :(得分:4)

因为声明类型并不一定与初始化有关。

我可以声明

List<int> foo; 

并让它稍后进行初始化。那么冗余在哪里呢?也许它从BuildList()等其他函数接收值。

正如其他人提到的那样,新的var关键字让你可以解决这个问题,但你在声明时初始化变量,这样编译器就可以知道它是什么类型。

答案 5 :(得分:4)

而不是将其视为多余的,请将该构造视为允许您保存一条线的功能。

而不是

列出距离; distance = new List();

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

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

这太多余了吗?也许。这样做会给你一些东西,不过

<强> 1 即可。将变量声明与对象分配分开。允许:

IEnumerable<int> distances = new List<int>();
// or more likely...
IEnumerable<int> distances = GetList();

2. 它允许编译器进行更强大的静态类型检查 - 当声明与赋值不匹配时给出编译器错误,而不是运行时错误。

编写软件是否都需要这些?没有。有很多语言没有这样做,和/或在许多其他方面有所不同。

“医生!我这样做会很疼!” - “不要那样做了”

如果您发现自己不需要或不想要c#提供的内容,请尝试使用其他语言。即使你不使用它们,了解其他的也可以为你解决问题提供巨大的推动力。如果你确实使用了一个,太棒了!

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

答案 6 :(得分:3)

也可以这样做:

var distances = new List<int>();

答案 7 :(得分:2)

C#3.0的编译器改进(与.Net 3.5相对应)消除了一些此类事情。所以你的代码现在可以写成:

var distances = new List<int>();

更新的编译器在根据语句中的附加信息计算类型方面要好得多。这意味着您需要为任务指定类型或作为通用的一部分的实例更少。

话虽如此,仍有一些领域可以改进。其中一些是API,有些只是因为强类型的限制。

答案 8 :(得分:2)

如果将它与动态类型语言进行比较,它只是“多余的”。它对于多态和在编译时发现错误很有用。此外,它使IDE的代码自动完成/智能感知更容易(如果使用的话)。

答案 9 :(得分:2)

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

现在使用 var 关键字进行类型推断,可以消除冗余。编译器很聪明,可以搞清楚。下一个C ++也有一个 auto 关键字,可以做同样的事情。

他们引入 var 的主要原因是匿名类型,没有名称:

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

答案 10 :(得分:1)

在添加功能支持后,C#肯定会变得更加冗长。

答案 11 :(得分:1)

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

distances = []

答案 12 :(得分:1)

如果显而易见的类型是读者,请使用var。

//Use var here
var names = new List<string>();

//but not here
List<string> names = GetNames();

来自microsofts C# programing guide

  

var关键字也很有用   何时变量的具体类型   在键盘上键入是很乏味的,或者   很明显,或者没有添加到   代码的可读性

答案 13 :(得分:0)

在这个问题的许多答案中,作者都​​在考虑编译器或辩护者。良好编程的一个重要规则是不要重复自己!

避免这种不必要的重复是Go的explicit design goal,例如:

  

使用foo.Foo* myFoo = new(foo.Foo) declare-and-initialize构造通过简单类型派生减少了口吃(:=)。

答案 14 :(得分:0)

我发现另外一个问题就是使用var来解决懒惰问题

var names = new List<string>();

如果使用var,名为“names”的变量将被键入为List<string>,,但最终只能使用List<T>.继承的接口之一

IList<string> = new List<string>();
ICollection<string> = new List<string>();
IEnumerable<string> = new List<string>();

您可以自动使用其中的所有内容,但是您可以考虑在编写代码时要使用的界面吗?

在此示例中,var关键字不会提高可读性。

答案 15 :(得分:0)

你的具体例子确实有点冗长,但在大多数情况下,C#相当精简。

我更喜欢这个(C#)

int i;

到此(VB.NET)

Dim i as Integer

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

答案 16 :(得分:-1)

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