采取以下片段:
List<int> distances = new List<int>();
语言设计者是否打算实现冗余?如果是这样,为什么?
答案 0 :(得分:74)
代码看起来多余的原因是,对于新手程序员来说,它似乎是两次定义相同的东西。但这不是代码正在做的事情。它定义了两个恰好属于同一类型的独立事物。它定义了以下内容:
List<int>
类型的距离的变量。 List<int>
的堆上的对象。请考虑以下事项:
Person[] coworkers = new Employee[20];
这里非冗余更清晰,因为变量和分配的对象有两种不同的类型(如果对象的类型派生自或实现变量的类型,那么这种情况是合法的。)
答案 1 :(得分:15)
对此有什么减少?
List<int> listOfInts = new List<int>():
翻译成英文:(编辑,清理一点澄清)
当你想到它的作用时,并不是真的很啰嗦。
当然还有另一种选择:
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)
因为我们沉迷于编译器和编译器错误。