Use of var keyword in C#
在与同事讨论了C 3中"var"关键字的使用后,我想知道人们对通过var进行类型推断的适当使用有什么看法?
例如,在有问题的情况下,我相当懒惰地使用var,例如:-
1 2 3 | foreach(var item in someList) { // ... } // Type of 'item' not clear. var something = someObject.SomeProperty; // Type of 'something' not clear. var something = someMethod(); // Type of 'something' not clear. |
VaR的更多合法用途如下:
1 2 |
有趣的是,Linq似乎有点灰暗,例如:-
1 2 | var results = from r in dataContext.SomeTable select r; // Not *entirely clear* what results will be here. |
很明显,结果会是这样的:它将是一个实现IEnumerable的类型,但是它并不像声明新对象的var那样完全明显。
当涉及到linq to对象时,情况更糟,例如:-
1 2 3 | var results = from item in someList where item != 3 select item; |
这并不比同等的foreach(somelist中的var项)/…等值。
这里真正关心的是类型安全性——例如,如果我们将查询结果放入一个接受IEnumerable
我仍然认为
1 | var orders = cust.Orders; |
我不在乎客户。订单是
将上述声明与以下内容进行对比:
1 | ObservableCollection<Order> orders = cust.Orders; |
对我来说,类型名只是噪音。如果我回去决定改变客户的类型,那么我也需要改变这个声明——如果我一开始使用var的话,我不需要这样做。
我广泛使用
诚然,这可能意味着还不清楚我们在处理什么类型的问题。那又怎么样?这实际上是一个分离设计的要点。在处理接口时,您显然对变量的类型不感兴趣。
那么,当我使用
如果我使用的是一个
现在,C团队发布了一个编码指南,声明
事实上,有一些(表面上)很好的解释解释为什么你不应该使用
在我看来,C中的var是一个很好的东西。任何这样类型的变量仍然是强类型的,但它的类型是从定义它的赋值的右侧获取的。因为类型信息在右侧是可用的,在大多数情况下,在左侧也必须输入类型信息是不必要和过于冗长的。我认为这会显著提高可读性,而不会降低类型安全性。
在我看来,从可读性的角度来看,对变量和方法使用良好的命名约定比显式类型信息更重要。如果我需要类型信息,我可以将鼠标悬停在变量(在vs中)上并获取它。不过,一般来说,对于读者来说,显式类型信息不应该是必需的。对于开发人员来说,在vs中,无论变量是如何声明的,您仍然可以获得intellisense。尽管如此,仍然有一些情况下显式声明类型是有意义的——也许您有一个返回
两者都不是绝对正确的;
来自C团队高级软件设计工程师Eric Lippert:
为什么引入
There are two reasons, one which
exists today, one which will crop up
in 3.0.The first reason is that this code is
incredibly ugly because of all the
redundancy:
Dictionary > mylists = new Dictionary >(); And that's a simple example – I've
written worse. Any time you're forced
to type exactly the same thing twice,
that's a redundancy that we can
remove. Much nicer to write
var mylists = new Dictionary >(); and let the compiler figure out what
the type is based on the assignment.Second, C# 3.0 introduces anonymous
types. Since anonymous types by
definition have no names, you need to
be able to infer the type of the
variable from the initializing
expression if its type is anonymous.
强调我的。整篇文章,c 3.0仍然是静态类型,诚实!接下来的系列也不错。
这就是
我认为var的使用应该与明智地选择的变量名相结合。
在foreach语句中使用var没有问题,前提是它不是这样的:
1 | foreach (var c in list) { ... } |
如果更像这样:
1 | foreach (var customer in list) { ... } |
…那么,阅读代码的人更有可能理解"列表"是什么。如果您可以控制列表变量本身的名称,那就更好了。
这同样适用于其他情况。这很没用:
1 | var x = SaveFoo(foo); |
…但这是有道理的:
1 | var saveSucceeded = SaveFoo(foo); |
我想每个人都是自己的。我发现自己在做这件事,简直是疯了:
1 | var f = (float)3; |
我需要某种12步无功程序。我叫马特,我(ab)用var。
我们采用了"人的代码,而不是机器的代码"的理念,基于这样一个假设,即您在维护模式上花费的时间比在新开发上花费的时间要长很多倍。
对我来说,这排除了编译器"知道"变量是什么类型的论点——当然,你不能第一次写无效的代码,因为编译器会阻止你的代码编译,但是当下一个开发人员在6个月的时间内读取代码时,他们需要能够推断出变量做的是正确的还是错误的,并且是正确的。确定问题的原因。
因此,
1 | var something = SomeMethod(); |
我们的编码标准禁止使用,但我们的团队鼓励使用以下内容,因为它提高了可读性:
1 2 3 4 5 | var list = new List<KeyValuePair<string, double>>(); FillList( list ); foreach( var item in list ) { DoWork( item ); } |
这还不错,它更像是一种风格化的东西,往往是主观的。它可以增加不一致性,在使用var和不使用var时。
另一个值得关注的情况是,在下面的调用中,您不能只通过查看代码就知道
1 | var variable = CallMe(); |
这是我对VaR的主要抱怨。
当我在方法中声明匿名委托时,我使用var,与使用
1 2 3 |
编辑:根据Julian的输入更新最后一个代码示例
var根本不像variant。变量仍然是强类型的,只是您不需要按键就可以实现。您可以将鼠标悬停在Visual Studio中查看类型。如果你正在阅读印刷的代码,你可能需要稍微考虑一下才能知道它的类型。但是只有一行声明它,并且有许多行使用它,所以给事物命名仍然是使代码更容易执行的最好方法。
使用IntelliSense是否很懒?打字比全名少。还是有工作少但不值得批评的事情?我认为有,VaR就是其中之一。
(P)The most likely time you'll need this is for anonymous types(where it is 100%required);but it also avoids replication for the triinas cases,and IMO makes the line clearer.I don't need to see the type twice for a simple initialization.(p)(P)For example:(p)字母名称(P)(请不要在前面编辑HSCROLL-It Kinda Proves the Point!)是吗?(p)(P)VS:(p)字母名称(P)There are,however,occasions when this is misleading,and can potentially cause bugs.如果原始变量和初始类型不具识别性,则应使用EDOC 0。For example:(p)字母名称
我不知道有什么大不了的。
1 | var something = someMethod(); // Type of 'something' not clear <-- not to the compiler! |
你仍然对"某物"有完全的智能感知,对于任何不明确的情况,你都有单元测试,对吗?(你呢?)
它不是varchar,也不是dim,当然也不是动态或弱类型。它阻止了马德内斯这样:
1 |
并将这种思维混乱减少到:
1 |
不错,不如:
1 | v = List<somethinglongtypename>(); |
但这就是布奥的目的。
VaR的一个特殊情况是很困难的:离线代码审查,特别是那些在纸上完成的审查。
你不能依靠鼠标来完成这个任务。
如果有人因为不想"找出类型"而使用
使用
- 如果需要,即声明匿名类型的引用。
- 它使代码更具可读性,即删除repetetive声明。
写出数据类型通常会使代码更容易执行。它显示了您正在使用的数据类型,这样您就不必通过首先确定代码的作用来确定数据类型。
考虑到IntelliSense的强大功能,我不确定var是否比类中的成员变量或在可见屏幕区域之外定义的方法中的局部变量更难读取。
如果您有一行代码,例如
1 | IDictionary<BigClassName, SomeOtherBigClassName> nameDictionary = new Dictionary<BigClassName, SomeOtherBigClassName>(); |
比以下更容易或更难阅读:
1 |
当然,
我认为使用var的关键是只在适当的地方使用它,即在Linq中执行它促进的操作时(可能在其他情况下)。
如果你有一个类型的东西,那么你应该使用它-不这样做是简单的懒惰(而不是创造性的懒惰,这通常是鼓励-好的程序员经常非常努力地工作,以懒惰,可以被认为是事情的源头在第一位)。
一个全面的禁令和首先滥用构造一样糟糕,但确实需要一个合理的编码标准。
另一件要记住的是,它不是一个vb类型的var,因为它不能更改类型-它是一个强类型变量,只是类型是推断出来的(这就是为什么有人会认为在foreach中使用它不是不合理的,比如说,因为可读性和可维护性的原因,我不同意)。
我怀疑这只会跑起来(—:
默普
在"编码恐怖"杂志上的这篇文章中被偷了:
不幸的是,你和其他人都错了。虽然我同意你的观点,冗余并不是一件好事,但解决这个问题的更好方法应该是做如下的事情:
myObject m=new();
或者,如果您正在传递参数:
person p=new("名字","姓");
在创建新对象时,编译器从左侧而不是右侧推断类型。这与"var"相比还有其他优点,因为它也可以用于字段声明(还有其他一些领域也可能有用,但我不会在这里讨论它)。
最后,它并不是为了减少冗余度。别误会我,"var"在c中对于匿名类型/投影非常重要,但是在这里的用法还远没有实现(我已经说了很长时间了),因为你混淆了正在使用的类型。输入两次太频繁了,但是声明为零的次数太少了。
Nicholas Paldino.net/c MVP,2008年6月20日上午8:00
我想如果你主要关心的是少打字——那么没有任何论据可以影响你使用它。
如果你只想成为一个关注你的代码的人,那么谁在乎呢?否则,在这种情况下:
1 | var people = Managers.People |
很好,但在这种情况下:
1 | var fc = Factory.Run(); |
它会使我的大脑从代码的"英语"开始形成的任何直接类型的推断短路。
否则,只需运用你最好的判断力和编程"礼貌"去对待那些可能需要为你的项目工作的人。
(P)Using EDOCX1 plography 0 anic instead of explicit type make refactorings much easier(there I must contradict the previous posts who meant it made no difference or it was purely"syntactic sugar".(p)(P)You can change the return type of your methods without changing every file where this method is called.想象(p)字母名称(P)What is used like(p)字母名称(P)如果你想把这个词改为大写字母2,回到一个大写字母3,那么你就必须改变你所使用的方法中的可变声明(同时也包含字母名称4)。(p)(P)如果你写(p)字母名称(P)Instead,you don't have to change it.(p)
这是一个品味问题。当您习惯了动态类型语言时,对变量类型的所有这些担忧都会消失。也就是说,如果你开始喜欢它们(我不确定每个人是否都喜欢,但我确实喜欢)。
C的
变量的类型并不那么重要(前面已经说过)。从上下文(它与其他变量和方法的交互)和它的名称来看,它应该是相对清晰的——不要期望客户列表包含一个
我仍在等待老板对这件事的看法——我得到了一个"继续"的毯子,可以使用3.5中的任何新结构,但是对于维护,我们会怎么做呢?
@AKU:一个例子是代码审查。另一个例子是重构场景。
基本上我不想用我的鼠标去打字。它可能不可用。
在您比较
由于
直线加速器绝对需要
1 2 3 4 5 6 7 8 9 | var anonEnumeration = from post in AllPosts() where post.Date > oldDate let author = GetAuthor( post.AuthorId ) select new { PostName = post.Name, post.Date, AuthorName = author.Name }; |
现在看看智能意义上的一个数,它会看起来像
1 2 3 4 5 6 7 8 | foreach( var item in anonEnumeration ) { //VS knows the type item.PostName; //you'll get intellisense here //you still have type safety item.ItemId; //will throw a compiler exception } |
C编译器相当聪明-如果属性匹配,单独生成的anon类型将具有相同的生成类型。
除此之外,只要你有理智,在任何上下文清晰的地方使用
1 2 3 4 5 6 7 8 | //less typing, this is good var myList = new List<UnreasonablyLongClassName>(); //also good - I can't be mistaken on type var anotherList = GetAllOfSomeItem(); //but not here - probably best to leave single value types declared var decimalNum = 123.456m; |
我想这取决于你的观点。我个人从来没有因为
毕竟,if语句
1 2 3 4 | var index = 5; // this is supposed to be bad var firstEligibleObject = FetchSomething(); // oh no what type is it // i am going to die if i don't know |
如果真的无法处理,没有人会使用动态类型语言。
我只在清楚看到使用了什么类型时才使用var。
例如,在这种情况下,我将使用var,因为您可以立即看到x将是"myclass"类型:
1 |
在这种情况下,我不会使用var,因为您必须将鼠标拖动到代码上,然后查看工具提示以查看MyFunction返回的类型:
1 | var x = MyClass.MyFunction(); |
尤其是,在右侧不是方法,而是值的情况下,我从不使用var:
1 | var x = 5; |
(因为编译器不知道我是否需要字节、短、int或其他内容)
在测试过程中,我发现自己有很多这样的代码:
1 2 | var something = myObject.SomeProperty.SomeOtherThing.CallMethod(); Console.WriteLine(something); |
现在,有时,我想看看someotherthing本身包含什么,someotherthing与callMethod()返回的类型不同。不过,由于我使用的是var,所以我只需更改以下内容:
1 | var something = myObject.SomeProperty.SomeOtherThing.CallMethod(); |
对此:
1 | var something = myObject.SomeProperty.SomeOtherThing; |
如果没有var,我也必须不断地更改左侧声明的类型。我知道它很小,但非常方便。
把它用于匿名类型——这就是它的用途。其他任何东西都是用得太远了。像许多在C语言环境中长大的人一样,我习惯于在声明的左边看到这个类型。除非有必要,否则我不会看右边。用
那些说"没关系,用你满意的东西"的人看不到整个画面。每个人都会在某一点上或另一点上获取他人的代码,并且必须处理他们在编写代码时所做的任何决定。处理完全不同的命名约定,或者经典的Gripe支撑样式,而不在组合中添加整个"EDOCX1"(0)或者不添加"EDOCX1"(0),这已经够糟糕了。最糟糕的情况是,一个程序员没有使用
标准确实是一件好事,因为它们意味着你更有可能提取随机代码并快速搜索。不同的事物越多,就越难得到。转向"VaR Everywhere"风格会有很大的不同。
我不介意动态输入,也不介意隐式输入——在为它们设计的语言中。我很喜欢Python。但是C被设计成一种静态显式类型语言,这就是它应该保持的方式。打破匿名类型的规则已经够糟糕的了;让人们更进一步,并且更进一步地打破语言的习惯,这是我不喜欢的事情。既然精灵已经从瓶子里拿出来了,它就再也回不来了。C将被巴尔干化为集中营。不好的。
对我来说,对
1 |
在vb.net中,是否等同于键入以下内容:
1 |
不过,在vb.net中没有人这样做。很傻,因为从.NET的第一个版本开始,你就能够做到这一点…
1 |
…创建变量并在一行中初始化所有变量。啊,但是如果你想要一个
1 |
就像你必须在C中做的那样,显然不能使用
1 |
如果您需要不同的类型,可以是。但是良好编程的基本原则之一是减少冗余,这正是var所做的。
对于认为
1 |
比
1 |
如果你不相信我,数一数……
19比21
如果有必要,我会解释的,但是试试看……(根据智能感知的当前状态,您可能需要为每个智能感知多键入几个)
你能想到的每一种类型都是如此!!
我个人的感觉是,除非不知道类型,否则不应该使用var,因为它会降低代码中的识别可读性。与一整行文字相比,大脑识别这一类型需要更长的时间。懂机器代码和位的老前辈们确切地知道我在说什么。大脑并行处理,当你使用var时,你强迫它序列化它的输入。为什么会有人想让他们的大脑更努力地工作?这就是电脑的用途。
我曾经认为var关键字是一项伟大的发明,但我对它进行了限制
- 仅在类型很明显的地方使用var(不滚动或查看返回类型)
我开始意识到这一点,然后没有给我任何好处,从我的代码中删除了所有var关键字(除非它们是特别需要的),因为现在我认为它们使代码的可读性降低,特别是对其他阅读您的代码的人。
它隐藏了意图,并且在至少一个实例中,由于类型的假设,在某些代码中会导致运行时错误。
(P)In most cases,it's just simpler to type it-image(p)字母名称(P)Instead of:(p)字母名称(P)有时这是需要的,例如:匿名类型,Like。(p)字母名称(P)I personally like using it,in spite of the fact that it make the code less ready and maintainable.(p)
没有,只不过不必写两次类型名。http://msdn.microsoft.com/en-us/library/bb383973.aspx
我将VaR分散到各个地方,对我来说唯一有问题的地方是内部短类型,例如,我更喜欢
从我昨天编写的代码来看,它当然可以使事情变得简单:
1 2 3 | var content = new Queue<Pair<Regex, Func<string, bool>>>(); ... foreach (var entry in content) { ... } |
如果没有
附录:花一点时间使用具有真正类型推理的语言(例如f),将说明编译器在正确获取表达式类型方面有多好。这当然意味着我倾向于尽可能多地使用
用LINQ的另一个很好的理由使用
如果你使用一个静态的两大战略的结果,你将它的execute assign IT的战略,但它可以与潜在的
在仇恨的实例,在把一些数据的查询,然后第一looped鸭子玩两个要求的数据打印出来的一个表。
这些婊子,LINQ并购的第一把"只读标识符。
然后在添加额外的信息安环槽和仇恨。有两个取出的数据包括在仇恨的原创。
当测试证明了这多更高效。
我们不习惯
(P)It's purely a conventience.The compiler will inferre the type(based on the type of the expression on the right hand side)(p)
我尽可能使用
如果您的代码写得好(例如,好的变量名、注释、清晰的结构等),那么局部变量的实际类型就不重要了。
var就像是孩子们书中的虚线空间,孩子们必须把它填满。除此之外,编译器将用正确的类型填充它,通常在=符号之后写入。
我在纽约的fairly C #世界,十年后作为一个Java专业。我的思想最初是沿着行的"哦,不!有生产型下的"安全"。然而,更多的是在读什么,在更喜欢它。
1)是一位冰AA型安全作为一个类型将是没有宣布。它的所有关于编译时的句法糖。
2)《大学信息follows主干(不要重复自己)。乾冰吗redundancies忌,鸭式命名的两个面上的冰一定冗余。avoinding冗余线阵的制作冰淇淋的所有关于你的代码更容易吗?两个转变。
3)对AA型的精确认识。嗯…………………我认为,你总是有一个总的想法你有一个整数,一个插座,一些用户界面的控制,或什么的。IntelliSense会引导你从这里。认识的或不精确的物。例如,我认为99%的时辰你不在乎一个变长或是一个int,float和一双。最后对1%的用例,在它真的事情,只是在鼠标指针悬停在上面的关键字。
4)见过《荒谬的说法,现在我们就需要去回到80年代风格的匈牙利warts为了区分"变量类型。毕竟,这是唯一的方式告诉银行后台类型变量的天提摩西道尔顿扮演詹姆斯·邦德。但这是2010年。我们要学会了我们的变量的名称为"他们和他们的内容和使用简单的理念引导美国作为其类型。继续做这鸭子是不会伤害你的。
两个笔吗,是不是一个大的冰的东西,但它是一个真的好的东西,它是一个更好的Java版的一件事,很快。全题元角色的攻击似乎是在季前fallacies的主意。我不hesitate两个使用它,和我快乐的R # helps我做母狗。
有人不喜欢对VaR的批评。所有答案都是否定的。哦,好吧。
@ Jon Limjap:我知道。:)我的意思是可读性会像在vb6中那样退化。我不想依靠intellisense来确定给定变量的类型。我希望能够单独使用源代码来解决这个问题。
命名约定也没有帮助-我已经使用了好名字。我们是不是要回到预混?
从对这个主题的讨论中,结果似乎是:
好:
争议:
忽略了错误的观点,即"var"可以神奇地帮助重构,对我来说最大的问题是人们坚持他们不关心返回类型是什么,"只要他们能枚举集合"。
考虑:
1 2 3 4 | IList<Customer> customers = dataAccess.GetCustomers(); var dummyCustomer = new Customer(); customers.Add(dummyCustomer); |
现在考虑:
1 2 3 4 | var customers = dataAccess.GetCustomers(); var dummyCustomer = new Customer(); customers.Add(dummyCustomer); |
现在,去重构数据访问类,让getCustomers返回
这里的问题是,在第一个示例中,您将getCustomers方法的期望明确化了——您的意思是希望它返回类似于列表的内容。在第二个示例中,这种期望是隐式的,并且从代码中看不出来。
(对我来说)很多pro-var参数说"我不关心它返回的类型",这很有趣,但是继续说"我只需要遍历它…"。(因此它需要实现IEnumerable接口,这意味着类型很重要)。
当我开始使用var关键字时,我也有同样的担心。不过,随着时间的推移,我已经习惯了它,不再使用显式变量类型。Visual Studio的编译器 IntelliSense在处理隐式类型变量方面做得非常好。
我认为遵循适当的命名约定可以帮助您更好地理解代码,而不是显式键入。
这似乎是类似于"我应该在变量名中使用前缀吗?".坚持使用好的变量名,让编译器考虑变量类型。
好吧,这一点在整个过程中都会被坚持,但我会尝试给出我的观点——尽管我认为我的观点是如此的混乱,以至于你无论如何都不会从中得到太多。
首先,有匿名类型,您需要使用"var"关键字来分配一个匿名类型的对象作为它的类,这里没有太多的讨论,"var"是必需的。
然而,对于更简单的类型,ints、long、strings等等,我倾向于输入正确的类型。主要是因为它是一个"懒人的工具",我在这里看不到太多的收获,很少的击键和可能的困惑,它可能提供了以后的道路只是不值得。尤其是浮点数的各种类型(浮点、双精度、十进制)使我感到困惑,因为我对文本中的后缀不确定——我喜欢在源代码中看到类型。
尽管如此,如果类型更复杂和/或在赋值的右侧显式重复,我倾向于使用var alot。这可以是
1 |
在这种情况下,我看不到重复类型两次的用处——尤其是当您开始更改代码和类型更改时——泛型类型可能会变得越来越复杂,因此必须更改它们两次只是一种痛苦。但是,当然,如果您希望对
因此,简言之,我做了以下工作:
- 当类型较短或无法从上下文中读取时,显式命名该类型
- 必须使用时使用var(duh)
- 当var(在我看来)不影响可读性时,使用var表示懒惰。
因此,它允许为集合中更少的列编写LINQ查询,比如说,集合。无需复制内存中的信息,只需加载完成所需操作所需的内容。
即使使用IntelliSense,当类型的名称很长时,它也特别有用。只需编写
就像使用
1 | public object SomeObject { get; set; } |
而不是:
1 2 3 4 5 6 7 8 9 | public object SomeObject { get { return _someObject; } set { _someObject = value; } } private object _someObject; |
每个人都知道该属性在做什么,因为每个人都知道
静态类型是关于契约的,而不是源代码。这个想法需要在一行上有静态信息,说明什么"应该"是一个小方法。一般指南建议每个方法很少超过25行。
如果一个方法足够大,以至于您无法跟踪该方法中的单个变量,那么您所做的其他错误操作将使对var的任何批评都相形见绌。
实际上,var的一个重要论点是,它可以简化重构,因为您不再需要担心您的声明过于限制(即,当您应该使用i list<>或ienumerable<>时,您使用了list<>)。您仍然需要考虑新的方法签名,但至少不必返回并更改声明以匹配。
除了可读性问题,使用"var"还有一个真正的问题。当用于定义在代码中稍后分配给的变量时,如果用于初始化变量的表达式类型更改为更窄的类型,则可能导致代码中断。通常,重构方法以返回比以前更窄的类型是安全的:例如,将"object"的返回类型替换为某个类"foo"。但是,如果有一个变量的类型是根据该方法推断出来的,那么更改返回类型将意味着可以更长时间地为该变量分配一个非foo对象:
1 2 | var x = getFoo(); // Originally declared to return Object x = getNonFoo(); |
因此在本例中,更改getfoo的返回类型会使getnonfoo的赋值非法。
如果getfoo及其所有用途都在同一个项目中,这不是什么大问题,但是如果getfoo在一个供外部项目使用的库中,您不能再确保缩小返回类型不会破坏某些用户的代码(如果他们使用这样的"var")。
正是因为这个原因,当我们向curl编程语言(在curl中称为"def")添加类似的类型推断功能时,我们阻止了对使用这个语法定义的变量的赋值。
令人惊讶的是,到目前为止还没有注意到这一点,但是使用
如果您改为指定一个特定的类型,则有可能让编译器将运行时强制转换无提示地插入到您的程序中!
1 2 | foreach (Derived d in listOfBase) { |
以上将进行编译。但是编译器插入了从
排除这种情况的唯一方法是使用
我认为您在您的问题中指出了VaR的主要问题:"我不需要找出类型"。正如其他人所指出的,VaR有一个位置,但是如果你不知道你要处理的类型,你很有可能会遇到问题-不是所有情况下,但那里有足够的气味,所以你应该是可疑的。
在转换到3.0和3.5框架之后,我了解了这个关键字,并决定试一试。在提交任何代码之前,我已经意识到它似乎是向后的,就像回到ASP语法中一样。所以我决定向上戳,看看他们的想法。
他们说继续,所以我用它。
有了这句话,我就避免在类型需要调查的地方使用它,比如:
var a=company.getrecords();
现在,它可能只是一个个人的事情,但我不能立即查看它并确定它是记录对象的集合还是表示记录名称的字符串数组。不管是哪种情况,我认为在这种情况下,明确的声明是有用的。
我认为你可能误解了VaR在C中的用法。它仍然是强类型,与vb变量类型不同,因此使用它或不使用它不会影响性能。
因为对最终编译的代码没有影响,所以它确实是一个样式师的选择。就我个人而言,我不使用它,因为我发现定义了完整类型的代码更容易阅读,但我可以想象几年后,完整类型声明将以与匈牙利符号相同的方式进行查看——额外的输入对于IntelliSense默认给我们的信息没有真正的好处。
在边缘案件附近肯定会有分歧,但我可以告诉你我的个人指导方针。
当我决定使用
- 从上下文来看,变量的类型对人来说是显而易见的。
- 变量的确切类型与[人类]无关。[例如,您可以在不考虑使用哪种容器的情况下,了解算法在做什么]
- 类型名很长,会中断代码的可读性(提示:通常是泛型)
相反,这些情况会迫使我不使用
- 类型名相对较短且易于阅读(提示:通常不是通用的)
- 类型在初始值设定项的名称中不明显
- 准确的类型对于理解代码/算法非常重要
- 在类层次结构上,当一个人无法轻易分辨正在使用的层次结构的级别时
最后,我绝不会将
这些都是指导方针。您还应该考虑同事的经验和技能、算法的复杂性、变量的寿命/范围等。
大多数时候,没有完美的正确答案。或者,这并不重要。
[编辑:删除了重复的项目符号]
克罗诺兹-在这种情况下(两者都超载)重要吗?如果您有两个采用不同类型的重载,那么本质上您会说要么可以传递,要么执行相同的操作。
不应该有两个重载根据传递的类型执行完全不同的操作。
虽然在这种情况下您可能会感到有些困惑,但它仍然是完全类型安全的,您只是让某人调用了错误的方法。
我在以下情况下使用VaR:
当类型与代码位于同一行时,例如
var emp=新员工();
很明显我们想要一个雇员(因为我们正在创建一个新的雇员对象),那么
1 |
当无法推断类型时,我不使用var,例如
1 | var emp = GetEmployee(); |
因为返回类型不是很明显(在雇员、IEemployee、与雇员对象完全无关的东西等处)?.
我发现使用var关键字实际上可以提高代码的可读性,因为您已经习惯了跳过"var"关键字。当您真正不关心特定类型是什么时,您不需要一直向右滚动来了解代码在做什么。如果我真的需要知道下面是什么类型的"项目",我只需将鼠标悬停在它上面,Visual Studio就会告诉我。换句话说,我宁愿读书
1 | foreach( var item in list ) { DoWork( item ); } |
一次又一次
1 | foreach( KeyValuePair<string, double> entry in list ) { DoWork( Item ); } |
当我试图消化代码时。我认为这在某种程度上归结为个人偏好。我将依赖于这一点的常识——为重要的东西(安全性、数据库使用、日志记录等)保存执行标准。
-艾伦。
我认为人们不理解var关键字。它们将其与Visual Basic/javascript关键字混淆,这是一种不同的动物。
很多人认为var关键字意味着弱类型(或动态类型),而实际上c是并保持强类型。
如果您在javascript中考虑到这一点:
1 | var something = 5; |
您可以:
1 | something ="hello"; |
对于C,编译器将从第一个语句推断类型,导致某个类型为"int",因此第二个语句将导致在例外情况下。
人们只需要理解使用var关键字并不意味着动态输入,然后决定他们要使用var关键字的程度,知道它将在编译什么方面完全没有区别。
当然,引入var关键字是为了支持匿名类型,但如果你看这个:
1 |
它非常冗长,我相信这是可读的,如果不是更多的话:
1 |
结果完全相同,所以是的,我在代码中使用它
更新:
也许,也许…他们应该用另一个关键字,那我们就不会讨论这个了…可能是"推断"关键字而不是"var"
我不明白为什么人们会这样争论。它真的没有任何意义,只不过是在火焰大战结束的时候发动,却什么也得不到。现在,如果C团队试图逐步淘汰一种风格而不是另一种风格,我可以看到对每种风格优点争论的理由。但既然这两种语言都要保持原样,为什么不使用你喜欢的语言,让每个人都这样做呢?这就像每个人最喜欢的三元运算符的用法:有的喜欢,有的不喜欢。一天结束时,它对编译器没有任何影响。
这就像和你的兄弟姐妹争论你最喜欢的父母是谁:除非他们离婚,否则没关系!
这次讨论来得有点晚,不过我想补充一下。
对于所有反对类型推断的人(因为这就是我们在这里真正讨论的),lambda表达式呢?如果您坚持总是显式声明类型(匿名类型除外),那么您如何处理lambda?"不要让我使用mouseover"参数如何应用于var而不是lambda?
更新
我刚刚想到一个反对"var"的论点,我认为还没有人提到过,它"中断"了"查找所有引用",这可能意味着(例如)如果您在重构之前检查类的使用情况,您将错过通过
我必须同意马特·汉密尔顿的观点。
当与好的变量名一起使用时,var可以使代码更易于阅读和理解。但是,var也会使您的代码在使用不当时无法像Perl那样读取和理解。
VaR的好用法和坏用法列表也不会有太大帮助。这是常识。更大的问题是可读性和写能力。很多开发人员不关心他们的代码是否可读。他们只是不想打字那么多。就我个人而言,我是一个读写的人。
(P)有时,竞争主管人也可以推断出,除了最不发达国家之外,还有哪些国家不了解投资政策评审的要求。(p)(P)For example-when using linq:(p)(P)例1(p)字母名称(P)例2(p)字母名称(P)In the above code-assuming one is using linq to Nhibernate or linq to sql,example 1 willBring the entire resultset for person objects back and then do filter on the client end.例如,2 however will do the query on the server(such as on sql server with sql)as the compiler is smart enough to work out that the where function should take a expression>rather than a fun.(p)(P)The result in example 1 will also not be further queryable on the server as an ienumable is returned,while in example 2 the compiler can work out if the result should rather be a iqueryable instead of enumerable(p)
因冗余原因删除。
1 2 3 4 5 | // If you change ItemLibrary to use int, you need to update this call byte totalItemCount = ItemLibrary.GetItemCount(); // If GetItemCount changes, I don't have to update this statement. var totalItemCount = ItemLibrary.GetItemCount(); |
是的,如果很难根据变量的名称和用法来确定它的类型,那么一定要显式地声明它的类型。
在我看来,大量使用
像其他节省时间的方法(例如自动属性)一样,在到处使用它之前,最好先了解它是什么以及它是如何工作的。
如果编译器足够聪明,能够从上下文中找出类型,那么您也是。你不必在申报表上把它写下来。而IntelliSense使得这一点变得更加不必要。
@Erlando,出于好奇,为什么你需要知道变量的类型来查看源代码?
在我的实践中,我发现变量类型对我来说只是在代码中使用它的时候才重要。
如果我试图在somevar编译器上执行一些不适当的操作,我会很高兴地给出一个错误警告。
如果我理解为什么在给定的上下文中使用somevar,我真的不在乎它有什么类型。
如果你知道这儿的类型,使用的类型。 如果你不知道的,为什么不呢? 如果你不知道的,好的,好吧,你已经发现的唯一的有效使用。
我很抱歉,但如果你能做的最好的冰淇淋"的信息,使全行的代码地址",这不是一个很好的答案。找一个不同的格式,你的代码的方式。
一个好的论点,为什么他们不应该被用来作为一个更"typlng shortcut",但应该是用来的场景,而不是因为他们是设计的主要是:resharper(至少usages v4.5)不能找到一个类型,如果它是作为一个冰阻碍。这可能是一个真正的问题,当重构或分析的源代码。
什么是最ignoring:
1 |
不是normally AA AA型房
1 | StringBuilder something = KEY'TAB'(); |
在我们的办公室,我们的CTO已经明确禁止使用var关键字,原因与您所说的相同。
我个人认为var的使用只在新的对象声明中有效,因为对象的类型在语句本身中很明显。
对于LINQ查询,可以将结果解析为:
1 | IEnumerable<TypeReturnedBySelectObject> |
(P)You can let the compiler(and the fellow who maintains the code next)infer the type from the right hand side of the initializer assignment.如果这一推论是可能的,那么竞争对手就可以这样做,这样他们就可以对你的第一部分进行某种类型的讨价还价。(p)(P)如果这对穷人来说是容易的,那么他们永远不会偷盗任何东西。如果地狱是硬的,你做了代码维护者和一般规则我不会那么做的(p)(P)最后,如果你打算把类型作为一个特定的,而你最初的表达方式实际上是一种不同的类型,使用某种方式将对你很难发现诱发的购买。通过明确告诉他们你想做的事情,当类型是不,你会得到一个立即的诊断。By sluffing on the type declaration and using"VAR",you won't get an mistake on the initialization;Instead,you'll get a type mistake in some expression that used the identifier assigned by the VAR expression,and it will be harder to understand why.(p)(P)So the moral is,use var sparingly;you generally aren't doing yourself or your downstream fellow maintainer a lot of good.and hope he reasons t he same way,so you aren't study guessing his intentions because he thought using VAR was easy.当一个有着漫长生命的系统编码时,你有多少是错误的。(p)
@基思
In your comparison between
IEnumerableand
IEnumerableyou don't need to
worry - if you pass the wrong type
your code won't compile anyway.
这并不完全正确-如果一个方法同时重载到IEnumerable
我想问题是,这种情况发生的可能性有多大!
我猜问题的一部分在于var在给定的声明中添加了多少混淆-如果不清楚什么类型的东西是什么类型(尽管强类型并且编译器完全理解它是什么类型),可能有人会掩盖类型安全错误,或者至少需要更长时间来理解一段代码。
"厄兰多,
谈到重构,通过将新类型的实例分配给一个变量,而不是在多个地方更改变量类型,似乎更容易更改变量类型,不是吗?
至于代码审查,我认为var关键字没有什么大问题。在代码审查期间,我更喜欢检查代码逻辑,而不是变量类型。当然,有些情况下开发人员可能会使用不合适的类型,但我认为这种情况的数量非常少,这并不是我停止使用var关键字的原因。
所以我重复我的问题。为什么变量类型对你很重要?
(P)You don't have to write out the type name and no this is no t less performant as the type is resolved at compile time.(p)
var是处理匿名类型的方法,不管是否来自linq语句。任何其他的使用都很大程度上取决于谁将阅读您的代码,以及有什么指导方针。
如果您是唯一的访问群体,或者您的访问群体对使用var很满意,或者非常熟悉您的代码,那么我想这并不重要。如果您像:var s=new sqlconnection()那样使用它,那么它在很大程度上不重要,而且可能提高了代码的可读性。如果人们不太挑剔,并且在不明显的情况下(大多数情况下不需要,在下面的陈述中如何使用它,通常会解释一切),他们可以做点小工作来了解类型,那么就没问题了。
但是,如果你有挑剔、心胸狭窄、喜欢抱怨的队友,或者如果你公司的设计准则明确禁止在类型不明显的时候使用var,那么你很可能会遇到强烈的反对。
如果使用var会使代码非常难以阅读,那么使用var可能会让您大吃一惊,即使它可能是您的应用程序设计造成的。
如果var引入了歧义(有点像IEnumerable/IEnumerable示例),那么不要使用它并且要显式。但是var确实有它的便利性,在某些情况下,imho甚至通过减少混乱来提高可读性。
"关于我的口味,你唯一能说的就是它是老式的,到时候你也会喜欢的。"—托尔金。
这不是错的,但也可能是不恰当的。请参阅所有其他响应以获取示例。
var x=5;(坏)
var x=new superdooperclass();(好)
var x=从db中的t。选择新的属性1=t.field12(更好)
我不认为var per say是一个糟糕的语言特性,因为我每天都用它来编写杰夫·耶茨描述的代码。实际上,几乎每次我使用var都是因为泛型可以生成一些非常复杂的代码。我活在冗长的代码,但泛型走得太远了。
也就是说,我(显然…)认为var已经成熟可以被滥用了。如果一个方法中的代码超过20行,而var则被丢弃,那么很快就会使维护成为一场噩梦。另外,教程中的var非常违反直觉,通常在我的书中是一个巨大的no。
在另一方面,var是一个"容易"的特性,新的程序员会喜欢它。然后,在几分钟/小时/天内,当他们开始达到极限时,就会遇到巨大的障碍。"为什么我不能从函数中返回var?"那种问题。此外,向强类型语言中添加伪动态类型很容易使新开发人员陷入困境。从长远来看,我认为var关键字实际上会使新程序员更难学习C。
也就是说,作为一个经验丰富的程序员,我确实使用var,主要是在处理泛型(显然是匿名类型)时。我坚持我的报价,我相信VaR将是最糟糕的滥用C功能之一。
第一。
我不认为使用
我将所有其他关于它的利弊的讨论归类为"宗教战争"。我的意思是比较和讨论…
…完全是主观的。
隐式类型化意味着对于使用
可以为局部变量提供var的推断"类型",而不是显式类型。var关键字指示编译器从初始化语句右侧的表达式推断变量的类型。
//z被编译为int
1 | var z = 100; |
//s被编译为以下字符串
1 | var s ="Hello"; |
//A编译为int[]
1 |
//expr编译为IEnumerable//或者可能是iqueryable
1 2 3 4 | var expr = from c in customers where c.City =="London" select c; |
//anon被编译为匿名类型
1 |
//列表编译为列表
1 2 3 |
var不能用于类范围内的字段。
使用var声明的变量不能在初始化表达式中使用。换句话说,这个表达式是合法的:int i=(i=20);但是这个表达式产生编译时错误:var i=(i=20);
不能在同一语句中初始化多个隐式类型变量。
如果名为var的类型在作用域中,var关键字将解析为该类型名,并且不会被视为隐式类型化局部变量声明的一部分。
来自Essential Linq:
除非绝对必要,否则最好不要显式声明范围变量的类型。例如,以下代码完全编译,但编译器可能在没有正式声明的情况下推断出类型:
1 2 3 4 5 | List<string> list = new List<string> {"LINQ","query","adventure" }; var query = from string word in list where word.Contains("r") orderby word ascending select word; |
显式声明范围变量的类型会强制对LINQ CAST运算符进行后台调用。此呼叫可能会产生意外的后果,并可能损害性能。如果您在LINQ查询中遇到性能问题,那么像这里所示的类型转换是开始查找罪犯的一个可能的地方。(此规则的一个例外是使用非能量可枚举的,在这种情况下,应使用强制转换。)
当你不想重复的时候,
1 | Dictionary<string, Dictionary<string, List<MyNewType>>> collection = new Dictionary<string, Dictionary<string, List<MyNewType>>>(); |
或
1 |
注意,在本例中使用
1 | var value= 5; |
当我能写出真正的类型,并消除
1 | double value = 5; |
它可以使代码变得简单和简短,特别是对于复杂的泛型类型和委托。
此外,它使变量类型更容易更改。
取决于,不知何故它使代码看起来"更干净",但同意它使代码更不可读…
当您将鼠标悬停在"var"上时,vs2008 w/resharper 4.1在工具提示中有正确的输入,所以我认为当您查找类的所有用法时,它应该能够找到这个。
不过,还没有测试过它能做到这一点。
我不使用VAR,因为它违背了C·C/C++/Java的根。尽管这是一个编译器的把戏,但它使语言感觉不太强类型化。也许20多年的C语言已经把它全部灌输到了我们(反VaR的人)的头脑中,我们应该在等号的左边和右边都有这个类型。
虽然我说过,我可以看到它对于长的一般集合定义和长类名(如codinghurror.com示例)的优点,但在其他地方,如string/int/bool,我真的看不到这一点。尤其
1 2 3 4 | foreach (var s in stringArray) { } |
保存3个字符!
对我来说,主要的烦恼是看不到var代表的方法调用类型,除非您将鼠标悬停在该方法或F12方法上。
埃里克的答案…
C中泛型类型的命名空间范围别名#
是相关的。
部分问题是C中没有强类型别名。许多开发人员使用var作为部分代理。
不要使用它,会使代码不可读。
总是尽可能严格地打字,拐杖只会让你的生活陷入地狱。
如果你是懒惰和使用了比其他任何匿名类型,你应该需要使用匈牙利表示法"这样的命名的变量。
生活!
男孩,我的小姐VB。