Что использовать:Тип имени var или объекта?[дубликат]
-
04-07-2019 - |
Вопрос
На этот вопрос уже есть ответ здесь:
- Использование ключевого слова var в C# 86 ответов
это вопрос, которым я всегда задаюсь при программировании:Что использовать, когда пишем код:
var myFiles = Directory.GetFiles(fullPath);
или
string[] myFiles = Directory.GetFiles(fullPath);
вар является новым и представляет собой Неявно типизированные локальные переменные, поэтому мы можем использовать его только локально, и у него есть такие правила, как не может быть нулевым и т. д., но мне интересно, получим ли мы какие-либо преимущества от его «обычного» использования.
В части «обычно» говорится, что не в Анонимные типы, Инициализаторы объектов и коллекций и Выражения запроса где было намерение использовать анонимный объект var, так что я имею в виду...точно так же, как в примере выше.
Что ты думаешь?
Решение
Помимо очевидного использования 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
там.
Редактировать:
Я только что перечитал пост Джона Скита, и мне в глаза бросилась цитата Эрика Липперта:
Неявно типизированные локальные переменные — это всего лишь один небольшой способ уменьшить значение «как» и тем самым подчеркнуть «что».
Я думаю, что на самом деле во многих случаях использование неявной типизации оставляет неявным то, что.Это нормально – не зацикливаться на том, что.Например, я случайно напишу запрос 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.И это вопрос «что», а не «как».
Другие советы
Вы получите огромное разнообразие мнений по этому поводу - от «Использовать var везде» до «использовать только VAR с анонимными типами, где вы в основном должны». Мне нравится Взгляд Эрика Липперта на этот счет:
Любой код — это абстракция.Что делает код «на самом деле» манипулирование данными?Нет.Числа?Биты?Нет.Напряжения?Нет.Электроны?Да, но понимание кода на уровне электронов - плохая идея!Искусство кодирования - выяснить, каков правильный уровень абстракции для аудитории.
На языке высокого уровня всегда существует такая напряженность между тем, что делает код (семантически) и тем, как код его выполняет.Программисты по техническому обслуживанию должны понимать как что, так и как, если они будут успешными в внесении изменений.
Весь смысл LINQ заключается в том, что он массово снижает «как» и массово подчеркивает «что».Используя понимание запроса, программист говорит для будущей аудитории: «Я считаю, что вы не должны знать и не знать, как именно вычисляется этот набор результатов, но вы должны очень заботиться о том, какова семантика полученного набора». Они делают код ближе к внедренному бизнес -процессу и дальше от битов и электронов, которые заставляют его уйти.
Неявно напечатанные местные жители - это всего лишь один маленький способ, которым вы можете снимать то, как и, таким образом, подчеркнуть, что.Правильно ли это делать в конкретном случае, это призыв суждения.Поэтому я говорю людям, что если знание этого типа актуально и его выбор имеет решающее значение для дальнейшей работы метода, то не используйте неявную набор.В явном наборе говорится: «Я говорю вам, как это работает по причине, обращать внимание».Неявное печатание говорит: «Не имеет значения, является ли это списком или клиентом [], что важно, так это то, что это коллекция клиентов».
Лично я не иметь тенденцию использовать его, если тип не достаточно очевиден - где я включаю запросы LINQ как «достаточно очевидные».Я бы не сделал этого ради Directory.GetFiles
например, поскольку не совсем очевидно, что это возвращает string[]
вместо (скажем) FileInfo[]
(или что-то совсем другое) — и это имеет большое значение для того, что вы будете делать позже.
Если в правой части оператора присваивания есть вызов конструктора, я с гораздо большей вероятностью выберу var
:совершенно очевидно, какой это будет тип.Это особенно удобно со сложными универсальными типами, например. Dictionary<string,List<int>>
.
Лично я использую var только в двух местах:
- С анонимными типами, т.е.Связанные с LINQ (где в некоторых случаях требуется var)
- Когда оператор объявляет и создает определенный тип того же типа.
то есть.это пример пункта 2:
var names = new List<String>();
Отредактировано:Это ответ на вопрос Джона Скита.
Приведенный выше ответ на самом деле был упрощен.В основном я использую вар где тип:
- Не нужно знать (правда, мест не так уж и много)
- Невозможно узнать (LINQ, анонимные типы)
- В противном случае известно или ясно из кода.
В случае фабричного метода все, что вам нужно знать в месте написания кода, это то, что возвращаемый объект является потомком некоторого типа, и что какой-то тип имеет статический фабричный метод, тогда я бы использовал вар.Так:
var connection = DatabaseConnection.CreateFromConnectionString("...");
Приведенный выше пример является реальным примером из моего кода.По крайней мере мне и людям, использующим этот код, ясно, что связь является потомком DatabaseConnection, но точный тип не нужен ни для понимания кода, ни для его использования.
Я попробовал стиль «использовать var везде»...и вот почему я не стал продолжать его использовать.
- Ухудшение читабельности в разы
- Ограничивает Intellisense после =
- Ввод «var» на самом деле был не намного короче, чем ввод «int», «string» и т. д., особенно с intellisense.
С учетом сказанного, я все еще использую его с LINQ.
Выходец из страны функционального программирования, где господствует вывод типов, я использую var
для всех местных жителей, где это возможно.
В Visual Studio, если вы когда-нибудь задаетесь вопросом, какой тип локального объекта, все, что вам нужно сделать, это навести на него курсор мыши.
Этот почта есть несколько хороших рекомендаций о том, когда использовать интерфейс типа var или типы объектов.
Я склонен использовать var
повсюду, но мои коллеги сказали: стоп, нам это менее читабельно.Так что теперь я использую var
только для анонимных типов, запросов LINQ и конструктора справа.
Я думаю, интересно отметить, как это обычно делается в Haskell.Благодаря Изоморфизм Карри-Говарда, (наиболее общий) тип любого выражения в Haskell может быть выведен, и, таким образом, объявления типов практически нигде не требуются, за некоторыми исключениями;например, иногда вы намеренно хотите ограничить тип чем-то более конкретным, чем можно было бы предположить.
Конечно, то, что требуется, и то, что рекомендуется, — это не одно и то же;на практике, по-видимому, соглашение заключается в том, что определения верхнего уровня всегда имеют объявления типов, тогда как в локализованных определениях объявления типов опускаются.Кажется, это обеспечивает хороший баланс между ясностью для читаемости определения в целом и краткостью для читаемости локальных «вспомогательных» или «временных» определений.Если я правильно понимаю, вы не можете использовать var
в первую очередь для определений «верхнего уровня» (таких как метод или глобальная функция), так что я думаю, это переводится как «использовать var
везде, где только можно» в мире C#.Конечно, набрав "int
" такое же количество нажатий клавиш, как "var
", но большинство примеров будут длиннее.