我认为很奇怪的是,只有C#和Java程序员似乎患有一种阻止他们从代码上下文中提取信息的疾病,而Python、JavaScript、Ruby、F#、Haskell等其他开发者似乎对此免疫。为什么他们似乎做得很好,而我们C#程序员需要进行这种讨论呢?
如果不使用显式类型声明就是草率或懒惰,那么是否意味着没有高质量、可读性强的Python代码?事实上,不是许多人称赞Python易读吗?虽然我对JavaScript动态类型的许多方面感到不满意,但缺乏显式类型声明并不是其中之一。
静态类型语言中的类型推断应该成为常态,而不是例外;它减少了视觉上的混乱和冗余,同时使您的意图更加明确,当您显式指定类型时,因为您希望获得一个不太派生的类型(IList<int> list = new List<int>();
)。
有人可能会反驳使用var
的情况如下:
var c = SomeMethod();
好的,对此我建议你给变量起更加合理的名称。
var customer = SomeMethod();
更好的方式:
var customer = GetCustomer();
让我们尝试显式类型转换:
Customer customer = GetCustomer();
你现在掌握了哪些你以前没有的信息?现在你确定它的类型是
Customer
,但你之前已经知道了,对吧?如果你已经熟悉这段代码,就能根据变量名知道可以期望
customer
具有哪些方法和属性。如果你还不熟悉这段代码,你就不知道
Customer
有哪些方法。显式地指定类型在此处并未增加任何价值。
也许
var
的某些反对者会承认,在上面的例子中,
var
并没有造成任何伤害。但是如果一个方法不返回像
Customer
或
Order
这样简单且常见的类型,而是一些处理过的值,比如某种字典类型呢?类似这样的东西:
var ordersPerCustomer = GetOrdersPerCustomer();
我不知道那个返回值是什么,可能是一个字典、列表、数组或者其他任何东西。但这有关紧要吗?从代码中我可以推断出我将会得到一个可迭代的客户集合,其中每个Customer
都包含一个可迭代的Order
集合。在这里我真的不关心类型。我知道我需要知道什么,如果最终结果是错的,那是因为这个方法的名称误导了我,这是无法通过显式类型声明来解决的问题。
让我们看看显式版本:
IEnumerable<IGrouping<Customer,Order>> ordersPerCustomer = GetOrdersPerCustomer();
我不知道你怎么看,但我发现从中提取所需信息要困难得多。这主要是因为实际信息(变量名)所在的位置更靠右,需要更长时间才能找到它,而且还被所有那些疯狂的
<
和
>
遮挡。实际类型是毫无价值的,它是胡言乱语,特别是因为要理解它,你需要知道这些通用类型的作用。
如果你对某个方法的作用或变量包含的内容不确定,仅从名称就可以判断,那么你应该给它一个更好的名称。这比看到它是什么类型要有价值得多。
显式类型声明不应该是必需的,如果需要,那么你的代码存在问题,而不是类型推断存在问题。它不可能是必需的,因为其他语言似乎也不需要它。
话虽如此,我确实倾向于对'原始数据类型'进行显式类型声明,比如
int
和
string
。但说实话,这更多是一种习惯,而不是一个有意识的决定。不过对于数字,如果忘记将
m
添加到字面数字中,以便将其视为
decimal
类型,类型推断可能会让你出错,但编译器不会让你意外失去精度,所以这并不是一个实际的问题。事实上,如果我在所有地方都使用
var
,那么在我正在处理的大型应用程序中,数量从整数到小数的变化将变得更加容易。
这又是
var
的另一个优点:它允许快速实验,而不需要强制更新所有类型以反映你的更改。如果我想将上面的示例更改为
Dictionary<Customer,Order>[]
,我只需更改我的实现,所有使用
var
调用它的代码将继续工作(至少变量声明会)。
var
关键字时,就会感觉代码不够规范。在我看来,那本书的作者是错的,除非有更多的上下文可以将这一点解释清楚。 - tdammersDictionary<string, int> map = new Dictionary<string, int>();
而不是var map = new Dictionary<string, int>();
吗?我知道,我不喜欢。 - Brian RasmussenIDictionary<string, int> map = new Dictionary<string, int>();
更好,因为它表达了我对于它是一个字符串/整数字典的兴趣,但实际实现的选择是次要的。强类型编程在多个场合都拯救了我,我更喜欢编译器向我报错而不是我的上司。 - tdammers