Javascript和C#中var实现的区别

30

我想提一个理论问题。如果我在Page_load中有以下C#代码:

cars = new carsModel.carsEntities();

var mftQuery = from mft in cars.Manufacturers 
               where mft.StockHeaders.Any(sh=> sh.StockCount>0) 
               orderby mft.CompanyName 
               select new {mft.CompanyID, mft.CompanyName};
               // ...

问题:

  1. 这段代码使用了 var 关键字,这种构造的好处是什么?
  2. var 在 Javascript 和 C# 中实现的主要区别是什么?

47
你可以问一下英语中的"die"和德语中的"die"之间的区别。前者是动词,意为"死亡",也是"骰子"的单数形式;后者则是冠词和代词(在这两种情况下,我只挑选了其中两个常见含义,当然还有更多)。它们是完全不同的东西(甚至发音都不同),只是在书写时看起来相同。在C#和JS中,“var”的情况也类似。 - user395760
5个回答

79

JavaScript是一种动态类型语言,而C#通常是一种静态类型语言。因此,像这样的比较总是会有问题。但是:

JavaScript的 var 关键字有点类似于C#的 dynamic 关键字。两者都创建一个在运行时不知道其类型的变量,并且其误用直到运行时才会被发现。这是JavaScript的一贯做法,但这种行为对于C# 4来说是全新的。

dynamic foo = new DateTime();
foo.bar();  //compiles fine but blows up at runtime.

JavaScript没有像C#的var那样的匹配项,因为JavaScript是一种动态类型语言,而C#的var(尽管有流行的误解)创建一个在编译时已知类型的变量。 C#的var有两个用途:声明类型难以书写的变量,并创建匿名类型变量,因此开发人员无法书写其类型。

对于第一个例子:

var conn = new System.Data.SqlClient.SqlConnection("....");

Linq-to-Sql或Entity Framework中的匿名类型投影是第二个例子的很好体现:

var results = context.People.Where(p => p.Name == "Adam")
                            .Select(p => new { p.Name, p.Address });

这里的resultsIQueryable<SomeTypeTheCompilerCreatedOnTheFly>类型。无论你多么想写出结果的实际类型而不是只写var,但由于你不知道编译器为匿名类型在底层创建的类型,因此没有办法。因此,这种类型被称为匿名

在这两种情况下,类型在编译时已知,随后说:

conn = new DateTime();
或者
results = new DateTime();

会导致编译错误,因为您正在将connresults设置为与它们声明为不兼容的类型。


10
好的回答!如果微软使用“推断”而不是“var”这个词,它会更准确,但出于简洁起见,我认为他们选择了正确的一个。多年以后,与其他开发技术相比,.NET 仍然让我惊叹其优美之处。我想这是因为微软开发团队需要自己使用他们开发的工具。顺便说一句,如果您使用 Resharper,var 的工作原理会立即变得明显。 - ATL_DEV
3
@Joel,谢谢,我发现C#非常优雅。Eric Lippert和他的团队做得很好。 - Adam Rackis
@Joel:C# 的唯一问题在于它基于 C,因此带来了许多 C 中糟糕的语法选择。当然,如果它不是基于 C 的,它就不会有近乎采用率,所以那 确实 是正确的选择...这是编程社区的问题,而不是 C# 设计者的错误 :\ - BlueRaja - Danny Pflughoeft
11
JavaScript中的var关键字与变量类型无关,但会影响变量作用域。未使用var声明的变量将成为全局变量,而使用var关键字声明的变量则是局部变量(JavaScript中的函数作用域,而非块级作用域)。 - Johan
@Johan - 非常正确。C#没有隐式全局变量的等价物。 - Adam Rackis

10

a) C#的var可以让你在变量声明时避免显式指定类型。这使你的代码更加简洁,有时右侧表达式的类型比较复杂,而你又不关心具体的类型。

b) JavaScript的var与C#的dynamic类似。它允许你声明一个变量,但是你可以改变它的类型。

var i = 1; 
i = "foo";  // legal in Javascript, illegal in C#

7
它们唯一的共同点是用于声明局部变量。
JS中var的C#等效项是dynamic。但由于大多数C#用户更喜欢静态类型,因此它通常仅在某种交互操作(使用COM或动态类型语言)中使用。
C# var仍然使用静态类型,但具有推断类型。由于JS仅支持动态类型,因此没有相应的等效项。
在这种情况下,显式静态类型不可能,因为new {mft.CompanyID, mft.CompanyName}创建了一个匿名类型,因此使用带有var的隐式静态类型。

1

C#中的var在设计时是动态的,但在编译时是静态类型。如果您执行以下操作,您将看到:

var mftQuery = from mft in cars.Manufacturers
    where mft.StockHeaders.Any(sh=> sh.StockCount>0) 
    orderby mft.CompanyName
    select new {mft.CompanyID, mft.CompanyName};

然后:

mftQuery = "Hello world!";

即使您没有指定任何类型,它也无法编译并抱怨类型不匹配。

这是一种有用的生产力增强功能,因为您可以轻松地将返回类型更改为类似的类型,而不会破坏任何内容,并且更容易编写。一个愚蠢的例子:

foreach(var animal in GetCats()){
   Console.WriteLine(animal.Owner);
}

可以改为:

foreach(var animal in GetDogs()){
   Console.WriteLine(animal.Owner);
}

你说的“设计时”是什么意思? - John Saunders

0

回答你的问题1,在所呈现的代码中使用var关键字的好处是可能很难确定LINQ查询的结果类型,并且可能会轻易受到查询更改的影响。事实上,它被引入到C#中正好与LINQ的首映相符。

总之,这是为了让程序员的生活更加轻松,同时也消除了Type t = new Type()的冗余。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接