О юзабельности var при разработке

284
15 сентября 2017, 18:39

Изучая Entity Framework натолкнулся на интересную вещь :

Для создания запроса мы можем использовать var :

var phones = db.Phones.Where(p=> p.Company.Name=="Samsung");

либо явно указывая тип запроса ,например :

Phone myphone = db.Phones.Where(p=> p.Company.Name=="Samsung");

что меня натолкнуло на интересный вопрос :

А можно ли при разработке использовать при создании переменных в большинстве случаев var вместо явного указания типа?Если нет, то почему нежелательно?

А теперь наведу несколько примеров ,в которых указаны различия между использованием var явным указанием типов,почему мне кажется что все-таки var в большинстве случаев будет юзабельней и читабельней для разработчиков :

1) Для объявления и дальнейшего использования таких структур как списки и словари(к примеру) которые имеют в себе уже вложенные типы:

Dictionary<Dictionary<String, String>, String> items = new Dictionary<Dictionary<String, String>, String>();

Соответственно через var :

var items = new Dictionary<Dictionary<String, String>, String>();

(Ссылка на вопрос : https://stackoverflow.com/questions/10572693/why-use-var-instead-of-the-class-name)

2) Использование var как итератор при перечислениях в коллекциях :

    class Item {
  public string Name; 
}
foreach ( Item x in col ) {
  Console.WriteLine(x.Name);
}

Код выше - скомпилируется без ошибок ,но при исполнении программы мы получим ошибку приведения типов . Потому что : сам цикл foreach может работать с обоими интерфейсами IEnumerable и IEnumrable<T> . Здесь же результат исполнения имеет тип object и C# компилятор кастит(приводит) это к типу Item . Следовательно , это небезопасно и может привести к ошибке работы программы ,потому что интерфейс IEnumerable может содержать объекты абсолютно любого типа.

Теперь вариант с var :

    foreach ( var x in col ) {
  Console.WriteLine(x.Name);
}

Здесь же тип x будет object если интерфейс IEnumerable и T если используется IEnumerable<T>

(Ссылка на вопрос : https://stackoverflow.com/questions/3425966/what-advantages-does-using-var-have-over-the-explicit-type-in-c)

3) И само собой - использование var при запросах + либо получение объекта с уже определенным типом :

 var l = new List<string>(); // думаю ,очевидно какой тип будет у var
 var s = new SomeClass(); //
 var results = from r in dataContext.SomeTable select r; // Получение выборки из БД(путем LINQ To Enities)

Или запрос через подход LINQ To Objects :

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

UPD: ну и пример с использованием анонимных типов :

var test = new {Id = 5,Name="Joseph"}
var result = context.MyTable.Select(x=>new {x.Id,x.Name}).ToArray();

(Ссылка на вопрос : https://stackoverflow.com/questions/41479/use-of-var-keyword-in-c-sharp?rq=1)

Краткий вывод из примеров выше : var - достаточно неплохая вещь ,поскольку он строго типизирован + правильное название переменных позволяет ещё и повысить читабельность . Что в суме значительно повышает эффективность кода без ущерба для безопасности

Вопрос в том : есть ли преимущества использования явного указания типов при объявлении переменных перед var?

Я просто новатор в этом деле и хотелось бы услышать мнение опытных людей.Спасибо за конструктивный ответ!

Answer 1

var - это ключевое слово для компилятора, а не для человека. Хорошее* использвование var - это когда вы хотите сказать компилятору:

Компилятор, тут тип для человека или очевиден из контекста, или вообще неважен. Выведи сам!

Плохое* использование var - тип важен для читающего ваш код, неочевиден из контекста, но вы все равно написали var. Тем самым вы говорите разработчику, читающему ваш код через год:

Вот ты пытаешься починить в моем коде хитрый баг, набрал себе в голову те 5-7 вещей которые можешь удержать. А теперь выбрось их и начни выяснять тип этой переменной!

Стандартное правило:

  1. Можно писать var, если при чтении кода человеком тип переменной прямо виден из контекста:

    • тип переменной явно написан в той же строчке: var a = new B()
    • тип переменной неявно написан в той же строчке:

      var some = BFacrory.Create();
      var tasks = dataContext.Tasks;
      
    • тип прямо следует из кода

      foreach (var task in dataContext.Tasks) ...
      
    • и еще куча случаев, которые можно описать как "тип очевиден".

  2. Можно писать var, если тип переменной не важен человеку, читающему код. Например, при использовании анонимных типов в цепочке LINQ-запросов. В этом случае важен не конкретный тип, а поля, которые в нем есть - а набор полей прямо виден из контекста.

  3. Можно писать var, если ваш код не будет читать никто и никогда. Например, если это временный набросок, который никогда-никогда не станет постоянным.

  4. Нельзя писать var во всех остальных случаях.

Существует альтернативный подход (с которым я в корне не соглаен), призывающий писать var вообще всегда и везде, кроме случаев, когда компилятор не может вывести тип, либо тип, выведенный компилятором не устраивает разработчика.

  • за такой подход: он очень устойчив к рефакторингу с переименованием и разделением типов
  • против: подобный рефакторинг происходит достаточно редко, отлично поддерживается даже чистой студией, а читабельность кода от принудительно неявного указания типа значительно* страдает.

* По мнению автора ответа. Почувствуйте себя человеком, который вынужден перестать читать код ради выяснения, что ж это за var^Wзвездочка.

Answer 2

Код должен хорошо читаться. Если var способствует этому - используй его. Если нет - не используй. Всё просто.

Если из-за обилия var ты не понимаешь в какой момент времени какой тип у тебя хранится в той или иной переменной - не используй var. В противном случае - почему бы и нет?

Пример с Dictionary плох тем, что наличие таких generic'ов в проекте - уже само по себе проблема.

Answer 3

Правило на самом деле очень простое: код должен легко читаться, пониматься и отлаживаться, как вами, так и вашими последователями. Всё, что служит этому — хорошо и правильно, всё, что препятствует этому — плохо и неправильно.

Когда у вас стоит выбор между явным именем типа или var (при условии, что нет разницы для программы), подумайте, интересен ли читателю в этой точке точный тип, или нет. Если без указания точного типа текст программы не проиграет в ясности, смело пишите var. Не стоит утомлять читателя ненужными подробностями: знание того, что объект имеет тип List<Task<byte[]>>.Enumerator, обычно не нужно. Но если с var читателю придётся угадывать нужный тип, и этот самый конкретный тип важен, укажите его.

В моей практике, чаще всего точный тип неважен: читателю в большинстве случаев всё равно, имеет ли id тип string, int или Id. Но в тех немногих местах, где с id производятся вычисления, точный тип может оказаться важен. Вот в этом-то случае и нужно его указывать явно.

Различение случаев, когда точный тип важен и когда неважен, зависит от вашего опыта (и, возможно, от отзывов коллег).

Да, а ещё есть случаи, когда язык за вас решает, использовать var или указывать тип. Например, для анонимных типов можно использовать только var (вне контекста обращённых методов, конечно).

READ ALSO
Диаграмма частотного распределения на c#

Диаграмма частотного распределения на c#

Имеется набор данных, отображаемый в столбце DataGridViewНеобходимо в ChartControl построить диаграмму распределения, например, как на изображении

248
Как создать шаблон Web-application ASP.NET на macOS?

Как создать шаблон Web-application ASP.NET на macOS?

У меня macOS, на которую установлен Visual StudioКак именно создать проект с шаблоном Web-application ASP

290
JetBrains Rider dotnet-sdk-2.0.0

JetBrains Rider dotnet-sdk-2.0.0

Как в JetBrains Rider настроить сборку проекта

242
Практическая разница между Linq To Entites и Linq To Objects

Практическая разница между Linq To Entites и Linq To Objects

Изучая различия между LINQ To Entites и LINQ To Objects в EntityFramework - столкнулся с интересной вещью :

323