it-swarm.com.ru

Что использовать: var или тип имени объекта?

это вопрос, который я всегда задаю при программировании: что использовать, когда мы пишем код:

var myFiles = Directory.GetFiles(fullPath);

или же

string[] myFiles = Directory.GetFiles(fullPath);

var является новым и является неявно типизированными локальными переменными , поэтому мы можем использовать только локально, и у него есть правила, такие как не может быть нулевым и т. д., но мне интересно, получим ли мы какое-либо преимущество, используя его "нормально".

В "нормальной" части говорится не в анонимные типы, инициализаторы объектов и коллекций и выражения запросов где это было намерением использовать var anonymous объект, так что я имею в виду ... так же, как в примере выше.

о чем ты думаешь?

52
balexandre

Помимо очевидного использования var с LINQ, я также использую его для сокращения объединенных объявлений переменных для удобства чтения, например:

var d = new Dictionary<string, Dictionary<string, Queue<SomeClass>>>();

В целом, я получаю некое утешение (из-за отсутствия лучшего слова) от статической типизации, что заставляет меня неохотно отказываться от нее. Мне нравится ощущение, что я знаю, что делаю, когда объявляю переменную. Объявление переменной не просто говорит компилятору, это говорит человеку, читающему ваш код.

Позвольте привести пример. Предположим, у меня есть метод, который возвращает List<string>. Этот код, безусловно, правильный, и я думаю, что 90% разработчиков C #, вероятно, написали бы его:

List<string> list = MyMethod();

Очевидно, верно? На самом деле, вот место, где вы могли бы так же легко использовать var.

Правда достаточно. Но эта версия кода не просто объявляет переменную, она говорит мне, что намерен сделать человек, который ее написал:

IEnumerable<string> list = MyMethod();

Разработчик, который написал этот код, говорит мне: "Я не собираюсь изменять этот список, и при этом я не собираюсь использовать индекс для доступа к его членам. Все, что я собираюсь сделать, - это перебирать его". Это много информации, которую нужно передать в одной строке кода. Это то, от чего вы отказываетесь, если используете var.

Конечно, вы не откажетесь от этого, если не использовали его в первую очередь. Если вы разработчик, который написал бы эту строку кода, вы уже знаете, что не будете использовать var там.

Edit:

Я просто перечитал пост Джона Скита, и эта цитата Эрика Липперта выскочила на меня:

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

Я думаю, что на самом деле во многих случаях использование неявной типизации оставляет то, что подразумевается. Это нормально, чтобы не останавливаться на чем. Например, я случайно напишу запрос LINQ, например:

var rows = from DataRow r in parentRow.GetChildRows(myRelation)
           where r.Field<bool>("Flag")
           orderby r.Field<int>("SortKey")
           select r;

Когда я читаю этот код, одна из вещей, которые я думаю, когда я читаю, это "rows - IEnumerable<DataRow>". Потому что я знаю, что запросы LINQ возвращают IEnumerable<T>, и я могу видеть тип объекта, который выбирается прямо здесь.

Это тот случай, когда что не было сделано явным. Это было оставлено для меня, чтобы сделать вывод.

Теперь, примерно в 90% случаев, когда я использую LINQ, это не имеет значения. Потому что 90% времени следующая строка кода:

foreach (DataRow r in rows)

Но нетрудно представить код, в котором было бы очень полезно объявить rows как IEnumerable<DataRow> - код, в котором запрашивалось множество различных типов объектов, было невозможно разместить объявление запроса рядом с итерацией, и это было бы полезно иметь возможность проверять rows с IntelliSense. И это то, что, а не как.

61
Robert Rossney

Вы получите огромное разнообразие мнений по этому вопросу - от "везде используйте var!" До "используйте var только с анонимными типами, где вам в основном это нужно". Мне нравится Эрик Липперт возьмется за это :

Весь код - это абстракция. То, что код "действительно" делает, манипулирует данными? Номера? Биты? Напряжения? Электроны? Да, но понимание кода на уровне электронов - плохая идея! Искусство кодирования определяет, какой уровень абстракции подходит для аудитории.

В языке высокого уровня всегда существует такое напряжение между тем, ЧТО код делает (семантически), и КАК код выполняет это. Программисты по техническому обслуживанию должны понимать, что и как, если они собираются успешно вносить изменения.

Весь смысл LINQ заключается в том, что он в значительной степени уменьшает акцент на "как" и массивно подчеркивает "что". Используя понимание запросов, программист говорит будущей аудитории: "Я считаю, что вы не должны ни знать, ни интересоваться, как именно вычисляется этот набор результатов, но вы должны очень заботиться о том, какова семантика полученного набора". Они делают код ближе к внедряемому бизнес-процессу и дальше от битов и электронов, которые его запускают.

Неявно типизированные местные жители - это всего лишь один маленький способ, которым вы можете уменьшить внимание как и тем самым подчеркнуть, что. Правильно ли это делать в конкретном случае - это решение по делу. Поэтому я говорю людям, что если знание типа является релевантным и его выбор имеет решающее значение для продолжения работы метода, не используйте неявную типизацию. Явная типизация говорит: "Я говорю вам, как это работает по какой-то причине, обратите внимание". Неявная типизация гласит: "Неважно, является ли эта вещь списком или клиентом [], важно то, что это набор клиентов".

Лично я не склонен использовать его, если тип не является достаточно очевидным - где я включаю запросы LINQ как "достаточно очевидные". Я бы не стал делать это, например, для Directory.GetFiles, поскольку не совсем очевидно, что он возвращает string[] вместо (скажем) FileInfo[] (или чего-то еще полностью) - и это имеет большое значение для того, что вы будете делать позже.

Если в правой части оператора присваивания есть вызов конструктора, я с большей вероятностью пойду с var: совершенно очевидно, каким будет тип. Это особенно удобно для сложных родовых типов, например, Dictionary<string,List<int>>.

41
Jon Skeet

Лично я использую var только в двух местах:

  1. С анонимными типами, т.е. LINQ-related (где в некоторых случаях требуется var)
  2. Когда оператор объявляет и создает определенный тип в том же типе

то есть. это пример пункта 2:

var names = new List<String>();

Отредактировано: Это ответ на вопрос Джона Скита.

Приведенный выше ответ был фактически упрощен. Обычно я использую var , где тип:

  1. Не нужно знать (не так много мест, хотя)
  2. Невозможно знать (LINQ, анонимные типы)
  3. В противном случае известно или ясно из кода

В случае фабричного метода, где все, что вам нужно знать в месте написания кода, это то, что возвращаемый вами объект является потомком некоторого типа и некоторого типа имеет статический метод фабрики, тогда я бы использовал var . Как это:

var connection = DatabaseConnection.CreateFromConnectionString("...");

Приведенный выше пример является реальным примером из моего кода. Очевидно, по крайней мере для меня и людей, которые используют этот код, что соединение является потомком DatabaseConnection, но точный тип не нужен ни для того, ни для другого. понимание кода, ни его использование.

11
Lasse Vågsæther Karlsen

Я попробовал стиль "везде использую var" ... и вот почему я не продолжал его использовать.

  1. Ухудшенная читаемость в разы
  2. Пределы Intellisense после =
  3. Ввод "var" на самом деле не намного короче, чем "int", "string" и т.д., Особенно с intellisense.

С учетом сказанного, я все еще использую его с LINQ.

9
Inisheer

Я склонен использовать var везде, но мои коллеги сказали: "Стоп, он нам менее читаем". Поэтому я теперь использую var только для анонимных типов, запросов LINQ и где находится конструктор с правой стороны.

3
Aleš Roubíček

В этом post есть несколько хороших рекомендаций о том, когда использовать интерфейс типа var или типы объектов.

3
Andres Denkberg

Исходя из страны функционального программирования, где управление типами определяет день, я использую var для всех местных жителей, где это возможно.

В Visual Studio, если вы когда-нибудь задумывались о том, какой тип есть у любого локального пользователя, все, что вам нужно сделать, это навести на него курсор мыши.

3
yfeldblum

Я думаю, что интересно отметить, как это обычно обрабатывается в Haskell. Благодаря изоморфизму Карри-Ховарда можно вывести (наиболее общий) тип любого выражения в Haskell, и, таким образом, объявления типов практически нигде не требуются, за некоторыми исключениями; например, иногда вы намеренно хотите ограничить тип чем-то более конкретным, чем было бы выведено.

Конечно, то, что требуется и что рекомендуется, - это не одно и то же; на практике, согласно соглашению, определения верхнего уровня всегда имеют объявления типов, в то время как в локализованных определениях объявления типов не учитываются. Похоже, что это обеспечивает хороший баланс между четкостью для восприятия определения в целом, в отличие от краткости для удобства чтения локальных "вспомогательных" или "временных" определений. Если я правильно понимаю, вы не можете использовать var для определения "верхнего уровня" (например, метод или глобальную функцию), поэтому я предполагаю, что это переводится как "использовать var везде, где вы можете" в мире C #. Конечно, ввод "int" - это то же количество нажатий клавиш, что и "var", но большинство примеров будет длиннее.

1
mithrandi