Uso da palavra-chave var em c #

Depois de discutir com colegas sobre o uso da palavra-chave ‘var‘ em C # 3, eu me perguntava quais eram as opiniões das pessoas sobre os usos apropriados da inferência de tipos via var?

Por exemplo eu prefiro preguiçosamente usado var em circunstâncias questionáveis, por exemplo: –

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. 

Mais usos legítimos de var são os seguintes:

 var l = new List(); // Obvious what l will be. var s = new SomeClass(); // Obvious what s will be. 

Curiosamente LINQ parece ser um pouco de uma área cinzenta, por exemplo: –

 var results = from r in dataContext.SomeTable select r; // Not *entirely clear* what results will be here. 

Está claro quais resultados serão em que ele será um tipo que implementa IEnumerable, no entanto, não é totalmente óbvio da mesma forma que um var declarando um novo object.

É ainda pior quando se trata de LINQ para objects, por exemplo: –

 var results = from item in someList where item != 3 select item; 

Isso não é melhor que o equivalente para o foreach (var item in someList) {// …} equivilent.

Há uma preocupação real sobre segurança de tipos aqui – por exemplo, se fôssemos colocar os resultados dessa consulta em um método sobrecarregado que aceitasse IEnumerable e IEnumerable o chamador passasse inadvertidamente no tipo errado.

var mantém uma tipagem forte, mas a questão é se é perigoso para o tipo não ser imediatamente aparente na definição, algo que é ampliado quando sobrecargas significam que erros do compilador podem não ser emitidos quando você inadvertidamente passa o tipo errado para um método.

Eu ainda acho que var pode tornar o código mais legível em alguns casos. Se eu tenho uma class Customer com uma propriedade Orders, e eu quero atribuir isso a uma variável, eu apenas farei isto:

 var orders = cust.Orders; 

Eu não me importo se Customer.Orders é IEnumerable , ObservableCollection ou BindingList – tudo que eu quero é manter essa lista na memory para iterar sobre ela ou obter sua contagem ou algo mais tarde.

Compare a declaração acima com:

 ObservableCollection orders = cust.Orders; 

Para mim, o nome do tipo é apenas ruído. E se eu voltar e decidir alterar o tipo de Customer.Orders na trilha (digamos de ObservableCollection para IList ), então eu preciso alterar essa declaração também – algo que eu não teria que fazer se Eu usei var em primeiro lugar.

Eu uso var extensivamente. Houve críticas de que isso diminui a legibilidade do código, mas nenhum argumento para apoiar essa afirmação.

Evidentemente, isso pode significar que não está claro com que tipo estamos lidando. E daí? Este é realmente o ponto de um design desacoplado. Ao lidar com interfaces, você não está interessado no tipo que uma variável possui. var leva isso muito mais longe, é verdade, mas eu acho que o argumento permanece o mesmo do ponto de vista da legibilidade: O programador não deve estar realmente interessado no tipo da variável, mas sim no que uma variável faz . É por isso que a Microsoft também chama a inferência de tipos de “tipagem de pato”.

Então, o que uma variável faz quando eu a declaro usando var ? Fácil, faz o que o IntelliSense me diz. Qualquer raciocínio sobre o C # que ignora o IDE fica aquém da realidade. Na prática, todo código C # é programado em um IDE que suporta o IntelliSense.

Se eu estou usando uma var variável declarada e fico confuso com o que a variável está lá, há algo fundamentalmente errado com o meu código. var não é a causa, apenas torna os sintomas visíveis. Não culpe o mensageiro.

Agora, a equipe de C # lançou uma diretriz de codificação declarando que var deve ser usado para capturar o resultado de uma instrução LINQ que cria um tipo anônimo (porque aqui, não temos alternativa real para var ). Bem, aperte isso. Contanto que a equipe do C # não me dê um argumento sólido para essa diretriz, vou ignorá-la porque, na minha opinião profissional e pessoal, é pura bobagem. (Desculpe, não tenho link para a diretriz em questão.)

Na verdade, há algumas (superficialmente) boas explicações sobre por que você não deveria usar o var mas eu ainda acredito que elas estão em grande parte erradas. Tome o exemplo de “searchabililty”: o autor afirma que var dificulta a busca de lugares onde o MyType é usado. Certo. Então faça interfaces. Na verdade, por que eu iria querer saber onde a aula é usada? Eu poderia estar mais interessado em onde ele é instanciado e isso ainda será pesquisável porque em algum lugar seu construtor tem que ser invocado (mesmo que isso seja feito indiretamente, o nome do tipo deve ser mencionado em algum lugar).

Var, na minha opinião, em C # é uma coisa boa tm . Qualquer variável assim digitada ainda é fortemente tipada, mas obtém seu tipo do lado direito da atribuição onde ela está definida. Como as informações de tipo estão disponíveis no lado direito, na maioria dos casos, é desnecessário e excessivamente detalhado também ter que inseri-lo no lado esquerdo. Eu acho que isso aumenta significativamente a legibilidade sem diminuir a segurança do tipo.

Do meu ponto de vista, usar boas convenções de nomenclatura para variables ​​e methods é mais importante de uma perspectiva de legibilidade do que informações de tipo explícitas. Se eu precisar da informação do tipo, eu sempre posso passar o mouse sobre a variável (no VS) e obtê-la. Geralmente, porém, informações explícitas de tipo não devem ser necessárias para o leitor. Para o desenvolvedor, no VS você ainda obtém o Intellisense, independentemente de como a variável é declarada. Tendo dito tudo isso, ainda pode haver casos em que faz sentido declarar explicitamente o tipo – talvez você tenha um método que retorne uma List , mas deseja tratá-lo como um IEnumerable em seu método. Para garantir que você esteja usando a interface, declarar a variável do tipo de interface pode tornar isso explícito. Ou, talvez, você deseje declarar uma variável sem um valor inicial – porque ela obtém imediatamente um valor com base em alguma condição. Nesse caso, você precisa do tipo. Se as informações de tipo forem úteis ou necessárias, vá em frente e use-as. Eu sinto, no entanto, que normalmente não é necessário e o código é mais fácil de ler sem ele na maioria dos casos.

Nenhum desses é absolutamente verdadeiro; var pode ter efeitos positivos e negativos na legibilidade. Na minha opinião, var deve ser usado quando qualquer um dos seguintes itens for verdadeiro:

  1. O tipo é anônimo (bem, você não tem escolha aqui, pois deve ser var neste caso)
  2. O tipo é óbvio baseado na expressão atribuída (ou seja, var foo = new TypeWithAReallyLongNameTheresNoSenseRepeating() )

var não tem impactos no desempenho, como é o açúcar sintático; o compilador infere o tipo e o define uma vez que é compilado em IL; Não há nada realmente dynamic sobre isso.

De Eric Lippert, engenheiro sênior de design de software da equipe de C #:

Por que a palavra-chave var foi introduzida?

Existem duas razões, uma que existe hoje, uma que surgirá em 3.0.

A primeira razão é que esse código é incrivelmente feio devido a toda a redundância:

Dictionary> mylists = new Dictionary>();

E esse é um exemplo simples – escrevi pior. Toda vez que você é forçado a digitar exatamente a mesma coisa duas vezes, isso é uma redundância que podemos remover. Muito melhor escrever

var mylists = new Dictionary>();

e deixe o compilador descobrir qual é o tipo baseado na atribuição.

Em segundo lugar, o C # 3.0 introduz tipos anônimos. Como os tipos anônimos, por definição, não possuem nomes, você precisa ser capaz de inferir o tipo da variável a partir da expressão de boot, se o tipo for anônimo.

Ênfase minha. O artigo inteiro, C # 3.0 ainda está datilografado estaticamente, honesto! e as séries seguintes são muito boas.

Isto é o que var é para. Outros usos provavelmente não funcionarão tão bem. Qualquer comparação com JScript, VBScript ou digitação dinâmica é total. Observe novamente que var é necessário para que outros resources funcionem no .NET.

Eu acho que o uso de var deve ser combinado com nomes de variables ​​escolhidos sabiamente.

Eu não tenho nenhum problema usando var em uma instrução foreach, desde que não seja assim:

 foreach (var c in list) { ... } 

Se fosse mais assim:

 foreach (var customer in list) { ... } 

… então alguém lendo o código teria muito mais chances de entender o que é “lista”. Se você tiver controle sobre o nome da própria variável de lista, melhor ainda.

O mesmo pode se aplicar a outras situações. Isso é bem inútil:

 var x = SaveFoo(foo); 

… mas isso faz sentido:

 var saveSucceeded = SaveFoo(foo); 

Cada um para o seu próprio, eu acho. Eu me vi fazendo isso, o que é simplesmente insano:

 var f = (float)3; 

Eu preciso de algum tipo de programa var de 12 etapas. Meu nome é Matt e eu (ab) uso var.

Adotamos o ethos “Código para pessoas, não para máquinas”, com base na suposição de que você gasta várias vezes mais tempo no modo de manutenção do que em novos desenvolvimentos.

Para mim, isso exclui o argumento de que o compilador “sabe” de que tipo é a variável – com certeza você não pode escrever código inválido na primeira vez porque o compilador interrompe seu código de compilar, mas quando o próximo desenvolvedor está lendo o código Em 6 meses, eles precisam ser capazes de deduzir o que a variável está fazendo de forma correta ou incorreta e identificar rapidamente a causa dos problemas.

Portanto,

 var something = SomeMethod(); 

é proibido por nossos padrões de codificação, mas o seguinte é incentivado em nossa equipe porque aumenta a legibilidade:

 var list = new List>(); FillList( list ); foreach( var item in list ) { DoWork( item ); } 

Não é ruim, é mais uma coisa estilística, que tende a ser subjetiva. Pode adicionar inconsistências, quando você usa var e quando não usa.

Outro caso de preocupação, na chamada seguinte, você não pode dizer apenas olhando o código do tipo retornado pelo CallMe :

 var variable = CallMe(); 

Essa é a minha principal queixa contra o var.

Eu uso var quando declaro delegates anônimos em methods, de alguma forma var parece mais limpo do que se eu usasse Func . Considere este código:

 var callback = new Func(delegate(IntPtr hWnd) { ... }); 

EDIT : atualizado o último exemplo de código com base na input de Julian

Var não é como variante. A variável ainda é fortemente tipada, é só que você não aperta as teclas para fazer isso. Você pode passar o mouse sobre ele no Visual Studio para ver o tipo. Se você está lendo um código impresso, é possível que você tenha que pensar um pouco para descobrir qual é o tipo. Mas há apenas uma linha que a declara e muitas linhas que a usam, então dar nomes decentes a coisas ainda é a melhor maneira de tornar seu código mais fácil de ser seguido.

Está usando o Intellisense preguiçoso? É menos digitação do que o nome inteiro. Ou existem coisas que são menos trabalhosas mas não merecem críticas? Eu acho que existem, e var é um deles.

O tempo mais provável que você precisará disso é para tipos anônimos (onde é 100% obrigatório); mas também evita a repetição para os casos triviais, e a IMO torna a linha mais clara. Eu não preciso ver o tipo duas vezes para uma boot simples.

Por exemplo:

 Dictionary>> data = new Dictionary>>(); 

(por favor, não edite o hscroll acima – isso prova o ponto !!!)

vs:

 var data = new Dictionary>>(); 

Há, no entanto, ocasiões em que isso é enganoso e pode causar bugs. Tenha cuidado ao usar var se a variável original e o tipo inicializado não forem idênticos. Por exemplo:

 static void DoSomething(IFoo foo) {Console.WriteLine("working happily") } static void DoSomething(Foo foo) {Console.WriteLine("formatting hard disk...");} // this working code... IFoo oldCode = new Foo(); DoSomething(oldCode); // ...is **very** different to this code var newCode = new Foo(); DoSomething(newCode); 

Um caso específico em que var é difícil: revisões de código offline, especialmente aquelas feitas em papel.

Você não pode confiar em mouse-overs para isso.

Eu não vejo qual é o grande problema ..

 var something = someMethod(); // Type of 'something' not clear <-- not to the compiler! 

Você ainda tem intellisense completo em 'alguma coisa', e para qualquer caso ambíguo você tem seus testes unitários, certo? ( você? )

Não é varchar, não é obscuro e certamente não é dynamic ou fraco. Está parando maddnes assim:

 List v = new List(); 

e reduzindo esse total mindclutter para:

 var v = new List(); 

Nice, não tão bom quanto:

 v = List(); 

Mas então é para isso que Boo é.

Se alguém estiver usando a palavra-chave var porque não deseja “descobrir o tipo”, esse é definitivamente o motivo errado. A palavra-chave var não cria uma variável com um tipo dynamic, o compilador ainda precisa conhecer o tipo. Como a variável sempre tem um tipo específico, o tipo também deve ser evidente no código, se possível.

Boas razões para usar a palavra-chave var são, por exemplo:

  • Onde é necessário, ou seja, declarar uma referência para um tipo anônimo.
  • Onde torna o código mais legível, ou seja, removendo declarações repetitivas.

Escrever o tipo de dados geralmente torna o código mais fácil de seguir. Ele mostra quais tipos de dados você está usando, para que você não precise descobrir o tipo de dados, primeiro, descobrir o que o código faz.

Dado o quão poderoso o IntelliSense é agora, eu não tenho certeza se var é mais difícil de ler do que ter variables ​​de membro em uma class, ou variables ​​locais em um método que é definido fora da área visível da canvas.

Se você tiver uma linha de código, como

 IDictionary nameDictionary = new Dictionary(); 

É muito mais fácil ou mais difícil de ler do que:

 var nameDictionary = new Dictionary(); 

Eu acho que a coisa chave com o VAR é usá-lo somente quando apropriado, ou seja, quando estiver fazendo coisas no Linq que ele facilita (e provavelmente em outros casos).

Se você tem um tipo de algo no meio, então você deve usá-lo – não fazê-lo é simples preguiça (em oposição à preguiça criativa que geralmente é encorajada – bons programadores frequentemente trabalham duro para serem preguiçosos e podem ser considerados a fonte da coisa em primeiro lugar).

Uma proibição geral é tão ruim quanto abusar da construção em primeiro lugar, mas precisa haver um padrão de codificação sensato.

A outra coisa a lembrar é que não é um tipo VB var em que ele não pode mudar tipos – é uma variável fortemente tipada é apenas que o tipo é inferido (é por isso que há pessoas que argumentam que não é razoável use, digamos, um foreach, mas eu discordo por razões de legibilidade e manutenção).

Eu suspeito que este vai correr e correr (-:

Murph

Claro, int é fácil, mas quando o tipo da variável é IEnumerable> , o var torna as coisas muito mais fáceis.

Stolen from the post on this issue at CodingHorror :


Unfortunately, you and everyone else pretty much got it wrong. While I agree with you that redundancy is not a good thing, the better way to solve this issue would have been to do something like the following:

MyObject m = new();

Or if you are passing parameters:

Person p = new(“FirstName”, “LastName);

Where in the creation of a new object, the compiler infers the type from the left-hand side, and not the right. This has other advantages over “var”, in that it could be used in field declarations as well (there are also some other areas that it could be useful as well, but I won’t get into it here).

In the end, it just wasn’t intended to reduce redundancy. Don’t get me wrong, “var” is VERY important in C# for anonymous types/projections, but the use here is just WAY off (and I’ve been saying this for a long, long time) as you obfuscate the type that is being used. Having to type it twice is too often, but declaring it zero times is too few.

Nicholas Paldino .NET/C# MVP on June 20, 2008 08:00 AM


I guess if your main concern is to have to type less — then there isn’t any argument that’s going to sway you from using it.

If you are only going to ever be the person who looks at your code, then who cares? Otherwise, in a case like this:

 var people = Managers.People 

it’s fine, but in a case like this:

 var fc = Factory.Run(); 

it short circuits any immediate type deductions my brain could begin forming from the ‘English’ of the code.

Otherwise, just use your best judgment and programming ‘courtesy’ towards others who might have to work on your project.

Using var instead of explicit type makes refactorings much easier (therefore I must contradict the previous posters who meant it made no difference or it was purely “syntactic sugar”).

You can change the return type of your methods without changing every file where this method is called. Imagine

 ... List SomeMethod() { ... } ... 

which is used like

 ... IList list = obj.SomeMethod(); foreach (MyClass c in list) System.Console.WriteLine(c.ToString()); ... 

If you wanted to refactor SomeMethod() to return an IEnumerable , you would have to change the variable declaration (also inside the foreach ) in every place you used the method.

Se você escreve

 ... var list = obj.SomeMethod(); foreach (var element in list) System.Console.WriteLine(element.ToString()); ... 

instead, you don’t have to change it.

@aku: One example is code reviews. Another example is refactoring scenarios.

Basically I don’t want to go type-hunting with my mouse. It might not be available.

It’s a matter of taste. All this fussing about the type of a variable disappears when you get used to dynamically typed languages. That is, if you ever start to like them (I’m not sure if everybody can, but I do).

C#’s var is pretty cool in that it looks like dynamic typing, but actually is static typing – the compiler enforces correct usage.

The type of your variable is not really that important (this has been said before). It should be relatively clear from the context (its interactions with other variables and methods) and its name – don’t expect customerList to contain an int

I am still waiting to see what my boss thinks of this matter – I got a blanket “go ahead” to use any new constructs in 3.5, but what will we do about maintenance?

In your comparison between IEnumerable and IEnumerable you don’t need to worry – if you pass the wrong type your code won’t compile anyway.

There’s no concern about type-safety, as var is not dynamic. It’s just compiler magic and any type unsafe calls you make will get caught.

Var is absolutely needed for Linq:

 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 }; 

Now look at anonEnumeration in intellisense and it will appear something like IEnumerable<'a>

 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 } 

The C# compiler is pretty clever – anon types generated separately will have the same generated type if their properties match.

Outside of that, as long as you have intellisense it makes good sense to use var anywhere the context is clear.

 //less typing, this is good var myList = new List(); //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; 

I guess it depends on your perspective. I personally have never had any difficulty understanding a piece of code because of var “misuse”, and my coworkers and I use it quite a lot all over. (I agree that Intellisense is a huge aid in this regard.) I welcome it as a way to remove repetitive cruft.

After all, if statements like

 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 

were really that impossible to deal with, nobody would use dynamically typed languages.

I only use var when it’s clear to see what type is used.

For example, I would use var in this case, because you can see immediately that x will be of the type “MyClass”:

 var x = new MyClass(); 

I would NOT use var in cases like this, because you have to drag the mouse over the code and look at the tooltip to see what type MyFunction returns:

 var x = MyClass.MyFunction(); 

Especially, I never use var in cases where the right side is not even a method, but only a value:

 var x = 5; 

(because the compiler can’t know if I want a byte, short, int or whatever)

To me, the antipathy towards var illustrates why bilingualism in .NET is important. To those C# programmers who have also done VB .NET, the advantages of var are intuitively obvious. The standard C# declaration of:

 List whatever = new List(); 

is the equivalent, in VB .NET, of typing this:

 Dim whatever As List(Of String) = New List(Of String) 

Nobody does that in VB .NET, though. It would be silly to, because since the first version of .NET you’ve been able to do this…

 Dim whatever As New List(Of String) 

…which creates the variable and initializes it all in one reasonably compact line. Ah, but what if you want an IList , not a List ? Well, in VB .NET that means you have to do this:

 Dim whatever As IList(Of String) = New List(Of String) 

Just like you’d have to do in C#, and obviously couldn’t use var for:

 IList whatever = new List(); 

If you need the type to be something different, it can be. But one of the basic principles of good programming is reducing redundancy, and that’s exactly what var does.

Use it for anonymous types – that’s what it’s there for. Anything else is a use too far. Like many people who grew up on C, I’m used to looking at the left of the declaration for the type. I don’t look at the right side unless I have to. Using var for any old declaration makes me do that all the time, which I personally find uncomfortable.

Those saying ‘it doesn’t matter, use what you’re happy with’ are not seeing the whole picture. Everyone will pick up other people’s code at one point or another and have to deal with whatever decisions they made at the time they wrote it. It’s bad enough having to deal with radically different naming conventions, or – the classic gripe – bracing styles, without adding the whole ‘ var or not’ thing into the mix. The worst case will be where one programmer didn’t use var and then along comes a maintainer who loves it, and extends the code using it. So now you have an unholy mess.

Standards are a good thing precisely because they mean you’re that much more likely to be able to pick up random code and be able to grok it quickly. The more things that are different, the harder that gets. And moving to the ‘var everywhere’ style makes a big difference.

I don’t mind dynamic typing, and I don’t mind implict typing – in languages that are designed for them. I quite like Python. But C# was designed as a statically explicitly-typed language and that’s how it should stay. Breaking the rules for anonymous types was bad enough; letting people take that still further and break the idioms of the language even more is something I’m not happy with. Now that the genie is out of the bottle, it’ll never go back in. C# will become balkanised into camps. Not good.

Many time during testing, I find myself having code like this:

 var something = myObject.SomeProperty.SomeOtherThing.CallMethod(); Console.WriteLine(something); 

Now, sometimes, I’ll want to see what the SomeOtherThing itself contains, SomeOtherThing is not the same type that CallMethod() returns. Since I’m using var though, I just change this:

 var something = myObject.SomeProperty.SomeOtherThing.CallMethod(); 

to this:

 var something = myObject.SomeProperty.SomeOtherThing; 

Without var, I’d have to keep changing the declared type on the left hand side as well. I know it’s minor, but it’s extremely convenient.

For the afficionados that think var saves time, it takes less keystrokes to type:

 StringBuilder sb = new StringBuilder(); 

do que

 var sb = new StringBuilder(); 

Count em if you don’t believe me…

19 versus 21

I’ll explain if I have to, but just try it… (depending on the current state of your intellisense you may have to type a couple more for each one)

And it’s true for every type you can think of!!

My personal feeling is that var should never be used except where the type is not known because it reduces recognition readabiltiy in code. It takes the brain longer to recognize the type than a full line. Old timers who understand machine code and bits know exactly what I am talking about. The brain processes in parallel and when you use var you force it to serialize its input. Why would anyone want to make their brain work harder? That’s what computers are for.

I split var all over the places, the only questionable places for me are internal short types, eg I prefer int i = 3; over var i = 3;

It can certainly make things simpler, from code I wrote yesterday:

 var content = new Queue>>(); ... foreach (var entry in content) { ... } 

This would have be extremely verbose without var .

Addendum: A little time spent with a language with real type inference (eg F#) will show just how good compilers are at getting the type of expressions right. It certainly has meant I tend to use var as much as I can, and using an explicit type now indicates that the variable is not of the initialising expression’s type.

None, except that you don’t have to write the type name twice. http://msdn.microsoft.com/en-us/library/bb383973.aspx