【问题标题】:Why double declaration is needed while defining variable Types?为什么在定义变量类型时需要双重声明?
【发布时间】:2017-08-20 17:10:53
【问题描述】:

我是 C# 的新手,我现在无法理解的一件事是,为什么类型需要写两次,即

Dictionary<string, string> Lines = new Dictionary<string, string>();

为什么不能更简单,比如:

Lines= new Dictionary<string, string>();
// or
Dictionary<string, string> Lines = ();

这不是关于“Lines”变量的全部内容吗?它本来可以更容易。

【问题讨论】:

  • var Lines = new Dictionary&lt;string, string&gt;(); ?
  • @David:这只适用于局部变量的特定情况。它不适用于私有字段。
  • @David,就像你第一次一样,将其发布为答案,如果它是正确的答案,我会接受。我不知道为什么代码的作者(我现在正在通过它)使用我写的那个......
  • @T.Todua: "why the author of the code..." - 可能是个人喜好,甚至是公司/团队/等等。编码标准。我曾为那些坚持永远不要使用var 关键字的客户工作过。我什至曾经为一个坚持要求每个类型声明每次都完全限定的客户工作过。其他人的代码……并不总是很好。

标签: c#


【解决方案1】:

如果这是方法中的代码,那么这就是为什么 the var keyword 自 C# 3.0 以来就存在的原因:

var Lines = new Dictionary<string, string>();

如果这是在类声明中,则不能使用var 关键字。我承认不知道为什么在类级别不允许使用隐式类型的具体细节,但只要说不允许就足够了。需要显式输入:

private Dictionary<string, string> Lines;

与该声明完全分开将是该变量的初始化。 可以在同一行、构造函数或方法等中完成。但是任何new关键字本身都需要明确告知类型:

new Dictionary<string, string>()

这是两个完全不同的东西,它们都需要为自己的离散和非常好的理由指定类型。

最终,任何时候你问“为什么语言不这样做?”你应该真的问的是“应该语言这样做吗?真的有必要吗?”

正如 Eric Lippert 曾经对我说的 in a previous question:“通过消除 [那个不必要的功能],不需要考虑、争论、设计、指定、实施、测试 [那个不必要的功能] 的任何规则,记录、交付给客户,或与 C# 的所有未来功能兼容。”

在看台上很容易大喊大叫。设计和支持主要的编程语言不太容易。也许有一天这个功能会存在,欢迎您向团队提出它。但至于“为什么不存在”,团队根本就没有做到。

【讨论】:

  • 你说你不知道为什么字段上没有 var。好吧,考虑一下。你将如何实现class C { public static var x = D.y; } class D { public static var y = C.x; }?如果该程序是合法的,那么您必须准确地描述它是如何工作的,以便编译器开发人员可以实现它。如果程序是非法,那么你必须准确描述编译器作者应该如何确定它是非法的,以及你想得到什么错误信息。当您想将 var 放在字段上时,这种情况是您必须考虑的最简单的令人费解的场景。
  • 现在开始考虑更难的案例。如果其中一个字段是公共的但属于匿名类型怎么办?那是怎么产生的?如果字段声明包含 lambda 怎么办?在程序中所有字段的类型未知的世界中,lambda 主体上的类型推断如何工作?今天,我们可以放心地假设在分析单个 lambda 主体之前,所有字段的所有类型都是已知的,但在这个新世界中,情况并非如此。描述用于检测涉及所有可能 lambda 的所有可能问题的算法。
  • 一旦您开始进行所有必需的分析,您就会意识到 (1) 您将需要整个程序分析和可能的定点分析,以便有效地解决问题,并且 (2) 这设计、指定、实现、测试和调试将非常昂贵,并且 (3) 错误消息可能会非常混乱,并且 (4) 编译器将变得非常慢,并且 (5) 此功能可以节省用户可能十次击键。所有这些努力都可以花在设计一个开发人员真正从中获得价值的功能上。
  • 现在,你可能会问为什么局部变量不会出现这个问题,答案是:局部变量只需要局部分析;这就是为什么它们被称为局部变量。在声明之前使用本地已经是非法的,因此大多数循环已经被检测到并且是非法的。在自己的定义中使用本地是合法的:int x = M(out x); 很奇怪但合法。对于var,我们要做的唯一工作就是检测这种情况,这涉及分析单个表达式以查看它是否引用自身,而不是整个程序。
  • 话虽如此,我在局部变量 case 上做了很多工作,以确保 (1) 报告的错误是合理的,并且 (2) 即使在错误的程序中,类型推断也能正常工作, 和 (3) 整个事情尽可能便宜。在 IntelliSense 场景中,我们最终可能不得不进行任意多个“var”推断,但在 典型 程序中,您只需要做几个即可确定本地的实际类型;在您键入时以足够快的速度进行分析有点棘手。
【解决方案2】:

您这样做是因为变量的类型可能与它引用的类的类型不同;考虑

ICustomer customerInterface = new CustomerConcreteClass();

这样的案例很多;这使程序员能够定义他们与 Type 交互的范围,因为 Type 可以有多个范围集(由它们声明的接口定义)。

通过询问“我为什么要定义两次”,您隐含地将您的编程限制在您使用和声明具体类的单一情况。即使在那种情况下,您的代码也执行两个功能 - 声明使用范围,并将新的具体类分配给变量。看起来你在做两次工作,但实际上你在执行两个单独的编码任务。

【讨论】:

    【解决方案3】:

    这就是为什么你有 var 关键字:

    var Lines = new Dictionary<string, string>();
    

    它允许您只指定一次新变量的类型,因为编译器足够聪明,可以找出该变量的类型。有些人认为它会使代码不清楚,因为有时它会隐藏变量的类型:

    var data = GetData();
    

    你可以利用它,但要明智地使用它。

    【讨论】:

    • 谢谢,@O.R.Mapper 对此发表了一些评论,我会等他
    • @T.Todua 抱歉,没看过 cmets,但我知道这些人速度很快 :)
    猜你喜欢
    • 1970-01-01
    • 2012-08-17
    • 2018-01-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多