specification - referencias de c#




Uso da palavra-chave var em c# (20)

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 pela 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<KeyValuePair<string, double>>();
FillList( list );
foreach( var item in list ) {
   DoWork( item ); 
}

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 usar 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<string>(); // Obvious what l will be.
var s = new SomeClass(); // Obvious what s will be.

Curiosamente LINQ parece ser um pouco de uma área cinza, por exemplo: -

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

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

É ainda pior quando se trata de LINQ para objetos, 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 <int> e IEnumerable <double> o chamador passasse inadvertidamente no tipo errado.

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


Dado o quão poderoso o Intellisense é agora, não tenho certeza se var é mais difícil de ler do que ter variáveis ​​de membro em uma classe, ou variáveis ​​locais em um método que é definido fora da área de tela visível.

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

IDictionary<BigClassName, SomeOtherBigClassName> nameDictionary = new Dictionary<BigClassName, SomeOtherBigClassName>();

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

var nameDictionary = new Dictionary<BigClassName, SomeOtherBigClassName>();

Eu acho que a coisa chave com o VAR é usá-lo apenas quando apropriado, ou seja, ao fazer as coisas no Linq que facilita (e provavelmente em outros casos).

Se você tem um tipo de algo no que você deve usar - não fazer isso é simples preguiça (em oposição à preguiça criativa que geralmente é encorajada - bons programadores frequentemente trabalham duro para ser 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 it in, say, a foreach but I'd disagree for reasons of both readability and maintainability).

Eu suspeito que este vai correr e correr (-:

Murph


Eu acho que o uso de var deve ser combinado com nomes de variáveis ​​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 probabilidade 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, 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.


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 é dinâmico ou fraco. Está parando maddnes assim:

List<somethinglongtypename> v = new List<somethinglongtypename>();

e reduzindo esse total mindclutter para:

var v = new List<somethinglongtypename>();

Nice, não tão bom quanto:

v = List<somethinglongtypename>();

Mas então é para isso que Boo é.


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 deveria 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 da 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).


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 dinâmico sobre isso.


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

Por exemplo:

Dictionary<string, List<SomeComplexType<int>>> data = new Dictionary<string, List<SomeComplexType<int>>>();

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

vs:

var data = new Dictionary<string, List<SomeComplexType<int>>>();

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.


Var não é como variante. A variável ainda é fortemente tipada, é só que você não aperta as teclas para fazer isso dessa maneira. 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 seguir.

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


Eu só uso var quando está claro para ver que tipo é usado.

Por exemplo, eu usaria var nesse caso, porque você pode ver imediatamente que x será do tipo "MyClass":

var x = new MyClass();

Eu não usaria var em casos como este, porque você tem que arrastar o mouse sobre o código e olhar para a dica para ver qual tipo MyFunction retorna:

var x = MyClass.MyFunction();

Especialmente, eu nunca uso var nos casos em que o lado direito não é sequer um método, mas apenas um valor:

var x = 5;

(porque o compilador não pode saber se eu quero um byte, curto, int ou qualquer outro)


Muitas vezes durante o teste, me vejo tendo código como este:

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

Agora, às vezes, quero ver o que o SomeOtherThing contém, SomeOtherThing não é o mesmo tipo que CallMethod () retorna. Já que estou usando var, apenas mudo isso:

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

para isso:

var something = myObject.SomeProperty.SomeOtherThing;

Sem var, eu teria que continuar mudando o tipo declarado no lado esquerdo também. Eu sei que é menor, mas é extremamente conveniente.


É uma questão de gosto. Toda essa confusão sobre o tipo de variável desaparece quando você se acostuma com linguagens dinamicamente tipadas. Isto é, se você começar a gostar deles (não sei se todos podem, mas eu sei).

C # 's varé muito legal na medida em que parece digitação dinâmica, mas na verdade é tipagem estática - o compilador impõe o uso correto.

O tipo de sua variável não é realmente tão importante (isso foi dito antes). Deve ser relativamente claro a partir do contexto (suas interações com outras variáveis ​​e métodos) e seu nome - não espere que customerList contenha um int...

Ainda estou esperando para ver o que meu chefe pensa sobre este assunto - eu tenho um cobertor "vá em frente" para usar qualquer novo construto em 3.5, mas o que faremos sobre manutenção?


@aku: Um exemplo são as revisões de código. Outro exemplo é refatorar cenários.

Basicamente eu não quero ir caçar com meu mouse. Pode não estar disponível.


Eu acho que depende da sua perspectiva. Eu pessoalmente nunca tive qualquer dificuldade em entender um pedaço de código por causa do var"uso indevido", e meus colegas de trabalho e eu o utilizamos bastante. (Eu concordo que o Intellisense é uma grande ajuda nesse sentido.) Eu aceito isso como uma maneira de remover o lixo repetitivo.

Afinal, se declarações como

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

eram realmente impossíveis de lidar, ninguém usaria linguagens dinamicamente tipadas.


Eu dividi var em todos os lugares, os únicos lugares questionáveis ​​para mim são tipos curtos internos, por exemplo, eu prefiro int i = 3;maisvar i = 3;



Para mim, a antipatia no sentido varilustra por que o bilinguismo no .NET é importante. Para os programadores C # que também fizeram o VB .NET, as vantagens varsão intuitivamente óbvias. A declaração padrão C # de:

List<string> whatever = new List<string>();

é o equivalente, em VB .NET, de digitar isto:

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

Ninguém faz isso no VB .NET, no entanto. Seria bobagem, porque desde a primeira versão do .NET você foi capaz de fazer isso ...

Dim whatever As New List(Of String)

... que cria a variável e inicializa tudo em uma linha razoavelmente compacta. Ah, mas e se você quiser um IList<string>, não um List<string>? Bem, no VB .NET isso significa que você tem que fazer isso:

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

Assim como você teria que fazer em C # e, obviamente, não poderia usar varpara:

IList<string> whatever = new List<string>();

Se você precisa que o tipo seja algo diferente, pode ser. Mas um dos princípios básicos da boa programação é reduzir a redundância, e é exatamente isso que o var faz.


Roubado do post sobre este assunto na CodingHorror :

Infelizmente, você e todos os outros entendem errado. Embora eu concorde com você que a redundância não é uma coisa boa, a melhor maneira de resolver esse problema seria fazer algo como o seguinte:

MyObject m = new ();

Ou se você está passando parâmetros:

Pessoa p = new ("FirstName", "LastName");

Onde na criação de um novo objeto, o compilador infere o tipo do lado esquerdo, e não o direito. Isso tem outras vantagens sobre o "var", pois também pode ser usado em declarações de campo (há também outras áreas que podem ser úteis também, mas não vou entrar aqui).

No final, apenas não pretendia reduzir a redundância. Não me entenda mal, "var" é MUITO importante em C # para tipos anônimos / projeções, mas o uso aqui é apenas WAY off (e eu tenho dito isso por um longo, longo tempo) como você ofusca o tipo que está sendo usado. Ter que digitar duas vezes é muito comum, mas declarar zero vezes é muito pouco.

Nicholas Paldino MVP .NET / C # em 20 de junho de 2008 08:00

Eu acho que se a sua principal preocupação é ter que digitar menos - então não há nenhum argumento que vai influenciá-lo a usá-lo.

Se você for sempre a pessoa que olha para o seu código, quem se importa? Caso contrário, em um caso como este:

var people = Managers.People

tudo bem, mas em um caso como este:

var fc = Factory.Run();

Ele faz um curto-circuito em qualquer tipo de dedução imediata que meu cérebro possa começar a formar a partir do "inglês" do código.

Caso contrário, basta usar seu bom senso e programar "cortesia" com outras pessoas que possam ter de trabalhar em seu projeto.


Usar em varvez do tipo explícito torna as refatorações muito mais fáceis (portanto, devo contradizer os pôsteres anteriores que queriam dizer que não fazia diferença ou que era puramente "açúcar sintático").

Você pode alterar o tipo de retorno de seus métodos sem alterar todos os arquivos em que esse método é chamado. Imagine

...
List<MyClass> SomeMethod() { ... }
...

que é usado como

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

Se você quisesse refatorar SomeMethod()para retornar um IEnumerable<MySecondClass>, você teria que alterar a declaração de variável (também dentro do foreach) em todo lugar que você usou o método.

Se você escreve

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

em vez disso, você não precisa mudá-lo.







var