После обсуждения с коллегами использования ключевого слова var в C# 3 мне стало интересно, каково мнение людей о подходящем использовании вывода типов через var?
Например, я довольно лениво использовал var в сомнительных обстоятельствах, например: -
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.
Более законные варианты использования var следующие:
var l = new List<string>(); // Obvious what l will be.
var s = new SomeClass(); // Obvious what s will be.
Интересно, что LINQ кажется немного серой зоной, например: -
var results = from r in dataContext.SomeTable
select r; // Not *entirely clear* what results will be here.
Понятно, какие результаты будут в том, что это будет тип, реализующий IEnumerable, однако это не совсем очевидно, так как var объявляет новый объект.
Еще хуже, когда дело доходит до LINQ to objects, например: -
var results = from item in someList
where item != 3
select item;
Это не лучше, чем эквивалентный foreach (var item in someList) {// ...} эквивалент.
Здесь есть реальная проблема безопасности типов - например, если бы мы поместили результаты этого запроса в перегруженный метод, который принимал IEnumerable <int> и IEnumerable <double>, вызывающий мог бы случайно передать неправильный тип.
varделает поддерживает строгую типизацию, но вопрос в том, действительно ли опасно, что тип не будет сразу очевиден при определении, что усиливается, когда перегрузки означают, что ошибки компилятора могут не возникать, если вы непреднамеренно передаете метод неправильного типа.
Педантный момент - var не ключевое слово ... это токен контекстных данных;)
Использование var - это нормально, но "Мне не нужно определять тип" кажется причиной очень плохой для его использования ... вы должны знать, что это за тип, var - это просто ярлык, чтобы не вводить его
@Thomas Levesque: Это тоже показалось мне плохой причиной. С ярлыками проблем нет. Я бы никогда не отказался от своей IDE ради блокнота.
var i = 0; == ошибка! var c = new CrazyFrigginLongClassName(); == победа!
«Var также напоминает мне вариантный тип VB / VBA. Он также имел свое место. Я вспоминаю (много лет назад), что его использование было нежелательным и требовало больших ресурсов». <- показывает, что это вопрос-наживка, поскольку тип 'var' в C# не имеет ничего общего с типом варианта VB / VBA.
var readabilityBeDamned = true;
В чем разница между var и auto в C++ 0x? Не пытаясь найти его, я ничего не вижу.
Некоторое время назад я писал о var и dynamic, itcrowd.be/post/C-40-About-the-dynamic-keyword.aspx. На мой взгляд, это улучшает читаемость .... и устраняет избыточность ... многие люди, кажется, путают var из C# с динамически типизированными ключевыми словами с тем же именем на других языках, таких как JavaScript
Проблема со всеми приведенными здесь примерами в том, что мы смотрим на ОДНУ строку кода. Когда я вижу строку за строкой объявления var, одно за другим, это выходит из-под контроля. Читаемость субъективна, но я считаю, что var злоупотребляют гораздо больше, чем прилично.
@sixlettervariables: разница в том, что вариант VB принимал любые типы во время выполнения. C# var вызывает явное объявление типа во время компиляции и допускает использование только одного типа в течение времени существования переменной. Следовательно, C# var практически аналогичен явному объявлению в скомпилированном исполняемом файле.
@awe: Я знаю о различиях, я указывал на подстрекательский язык в исходном вопросе.
Этот вопрос, кажется, уже задавался и обсуждался здесь: C# - Используете ли вы «var»? Рискуя повториться, я свяжусь со своим ответом в этом связанном вопросе, который, учитывая положительные голоса, кажется довольно общим консенсусом для многих люди (но также вызвали некоторые интересные комментарии!): Мой ответОбновлено: Что ж, кажется, этот конкретный вопрос на самом деле предшествует тому, который я связал с [шлепает лбом], однако я оставлю его здесь, так как
Раньше я об этом говорил блоггинг, и в комментариях тоже есть некоторые обсуждения.





Я считаю, что использование var должно сочетаться с грамотно подобранными именами переменных.
У меня нет проблем с использованием var в операторе foreach, если это не так:
foreach (var c in list) { ... }
Если бы это было больше так:
foreach (var customer in list) { ... }
... тогда кто-то, читающий код, с большей вероятностью поймет, что такое «список». Это даже лучше, если у вас есть контроль над именем самой переменной списка.
То же самое можно сказать и о других ситуациях. Это довольно бесполезно:
var x = SaveFoo(foo);
... но в этом есть смысл:
var saveSucceeded = SaveFoo(foo);
Думаю, каждому свое. Я обнаружил, что делаю это, что просто безумие:
var f = (float)3;
Мне нужна какая-то 12-ступенчатая программа var. Меня зовут Мэтт, и я (ab) использую var.
Ну, единственное, что не так с "var f = (float) 3;" в том, что это должно быть «var f = 3f» или «var f = 3.0 (вызывает отстой с одинарной точностью)».
Хе да 3f или 3.0 - это то, что вам нужно! Нам, вар маньякам, нужно держаться вместе!
Настоящая проблема в первом примере - это «список», а не «с». "список" Какие? "list" следует переименовать в "customers", или "customersWhoOweMoney", или "currentCustomers", или что-нибудь более информативное. И как только у вас есть это, «c» может оставаться как есть, потому что вы уже знаете, что он будет содержать.
Привет, Мэтт! Меня зовут Кенни и я вараддикт.
var MattHamil = "Люк Скайуокер"; // лишили тонны
В нашем офисе наш технический директор категорически запретил использование ключевого слова var по тем же причинам, которые вы указали.
Лично я считаю, что использование var допустимо только в объявлениях новых объектов, поскольку тип объекта очевиден в самом заявлении.
Для запросов LINQ вы можете разрешить результаты в:
IEnumerable<TypeReturnedBySelectObject>
Это должно быть новое употребление слова «потрясающий».
В этом случае ваш технический директор также должен запретить использование LINQ, но, честно говоря, я думаю, он должен попытаться понять ключевое слово var в C# и то, как оно не имеет ничего общего с ключевым словом var в VB или JavaScript ... Может быть, им просто нужно выбрал другое ключевое слово для этого
Вы не всегда можете разрешить результаты в IEnumerable <SomeSpecificType> в запросах LINQ. Если вы выбираете определенные поля, вы получите анонимный тип, и вы имеют для использования var.
У меня были те же опасения, когда я начал использовать ключевое слово вар. Однако со временем я к этому привык и не собираюсь возвращаться к явным типам переменных. Компилятор \ intellisense Visual Studio очень хорошо справляется с задачей значительно упростить работу с неявно типизированными переменными.
Я думаю, что соблюдение правильных соглашений об именах может помочь вам понять код намного лучше, чем явная типизация.
Похоже, это такие же вопросы, как: «Может, я использую префиксы в именах переменных?».
Придерживайтесь хороших имен переменных и позвольте компилятору подумать о типах переменных.
Кому-то не нравится критика вар .. Все ответы занижены .. да ладно ..
@Jon Limjap: Я знаю. :) Я имел в виду, что читаемость ухудшается, как в VB6. Мне не нравится полагаться на Intellisense, чтобы выяснить, к какому типу относится данная переменная. Я хочу выяснить это, используя только исходный код.
Соглашения об именах тоже не помогают - я уже использую хорошие имена. Вернемся к префиксу?
Я думаю, что ключевым моментом с VAR является использование его только там, где это уместно, то есть при выполнении действий в Linq, которые он облегчает (и, вероятно, в других случаях).
Если у вас есть тип получил для чего-то в, тогда вы должны использовать его - не делать этого - просто лень (в отличие от творческой лени, которую обычно поощряют - хорошие программисты часто очень много работают, чтобы быть ленивыми, и их можно считать источник вещи в первую очередь).
Общий запрет так же плох, как и злоупотребление конструкцией в первую очередь, но нужен разумный стандарт кодирования.
Еще нужно помнить, что это не переменная типа VB, поскольку она не может изменять типы - это является строго типизированная переменная, это просто вывод типа (вот почему есть люди, которые будут утверждать, что это не является необоснованным для использовать его, скажем, в foreach, но я бы не согласился по причинам как удобочитаемости, так и ремонтопригодности).
Я подозреваю, что этот будет работать и работать (-:
Мерф
Один конкретный случай, когда var затруднен: автономная проверка кода, особенно на бумаге.
Для этого нельзя полагаться на наведение курсора мыши.
Какого черта вы рецензируете код на бумаге? Подумайте о деревьях! ;)
У вас может быть такая же проблема без использования var. Проблема не в var; проблема в неправильных именах переменных. Если имена переменных выбраны правильно, использование var не имеет значения.
В моей команде есть парень, который проверяет свой код и ищет ошибки, распечатывая свой код. Его стены ЗАКРЫТЫ кодом. Однажды я вошел, и у него была целая большая доска, покрытая одним из его упражнений по отладке. Вероятно, это было ~ 10000 мест.
Сами по себе имена переменных не решают проблему, если вы не вернетесь к венгерской системе обозначений, где тип является частью имени.
Я все еще думаю, что var может сделать код более читабельным в некоторых случаях. Если у меня есть класс Customer со свойством Orders, и я хочу назначить его переменной, я просто сделаю следующее:
var orders = cust.Orders;
Меня не волнует, является ли Customer.Orders IEnumerable<Order>, ObservableCollection<Order> или BindingList<Order> - все, что я хочу, - это сохранить этот список в памяти, чтобы перебирать его или получать его счетчик или что-то в этом роде позже.
Сравните вышеприведенное заявление с:
ObservableCollection<Order> orders = cust.Orders;
Для меня название типа - просто шум. И если я вернусь и решу изменить тип Customer.Orders в дальнейшем (скажем, с ObservableCollection<Order> на IList<Order>), тогда мне нужно будет изменить и это объявление - чего бы мне не пришлось делать, если бы я использовал var в первое место.
Мне нравится иметь перед собой явный тип, когда я читаю код. Как мне узнать, что здесь "cust.Orders" без типа? Да, я могу навести указатель мыши, чтобы узнать, но зачем мне это нужно? :)
Но дело в том, что в целом это не имеет значения. При условии, что cust.Orders - это то, что вы можете перечислить (например, foreach over), тогда не имеет значения, какой это тип. Дополнительный код просто мешает прочтению намерения.
Да, я часто меняю дженерики, когда делаю какие-то наброски.
Но если вам нужно только, чтобы cust.Orders было «чем-то, что вы можете перечислить», то не делает ли это требование явным и понятным объявление его как IEnumerable <Order>? Объявление его как var означает, что вы фактически теряете это требование.
Думаю, это немного упрощает вопрос. Верно, что если все, что вы хотите сделать, это перебрать список, тогда это не имеет значения ... но в вашем примере, если это BindingList <Order>, тогда он немедленно сообщает вам, что он будет поддерживать привязку к пользовательскому интерфейсу управление без проблем - что немаловажно инфо имо.
Если вы действительно находитесь в ситуации, когда перечисление того, какой интерфейс вы получаете, «просто шум», то вам, вероятно, не нужно получать этот интерфейс. Но вы должны использовать объект в коде позже, поэтому очевидно, что интерфейс не имеет значения. (Странно, если я так думаю?)
Хотя это личное решение, я не согласен с тем, что имя типа - это просто шум, для меня все дело в ремонтопригодности, еще долго после того, как вы уйдете, меньшим смертным придется читать ваш код, используя var, где вы МОЖЕТЕ использовать строгое имя типа на мой взгляд неправильно. Раньше я не верил в это, но через некоторое время, используя стиль, который вы использовали выше, я убедился.
@jon, а как IEnumerbal orders = cust.Orders foreach (порядок переменных в заказах) будет иметь значение? единственное, что говорит IEnumerable, это то, что вы можете поместить его в foreach, но вы уже знали это из строки ниже
«Единственное, что говорит IEnumerable, это то, что вы можете поместить его в foreach» - он также выражает намерение, что Только, что вы можете сделать, это перечислить. Использование var дает доступ и intellisense для публичных членов конкретного типа коллекции.
@Joe - И если вы хотите использовать какие-либо из этих общедоступных членов, которые не являются частью IEnumerable, то читателю очень поможет явное объявление переменной с использованием этого конкретного типа.
Я только что понял, что var изменил способ написания кода. Я начал писать быстрее, в хорошем смысле.
@erlando, из любопытства, зачем вам знать тип переменной, глядя на исходный код?
В своей практике я обнаружил, что тип переменной важен для меня только тогда, когда я использую его в коде.
Если я пытаюсь выполнить некорректную операцию над someVar, компилятор с радостью выдает мне ошибку \ предупреждение.
Мне действительно все равно, какой тип у someVar, если я понимаю, что Почему используется в данном контексте.
Я широко использую var. Была критика, что это снижает читабельность кода, но не было аргументов в поддержку этого утверждения.
По общему признанию, это может означать, что непонятно, с каким типом мы имеем дело. Ну и что? На самом деле в этом суть несвязанного дизайна. Когда вы имеете дело с интерфейсами, нет особенно интересует тип переменной. var идет намного дальше, правда, но я думаю, что аргумент остается тем же самым с точки зрения удобочитаемости: программиста на самом деле должен интересовать не тип переменной, а скорее то, что такое переменная делает. Вот почему Microsoft также называет вывод типа «утиной типизацией».
Итак, что делает переменная, когда я объявляю ее с помощью var? Легко, он делает то, что мне говорит IntelliSense. Любые рассуждения о C#, игнорирующие IDE, не соответствуют действительности. На практике каждый код C# программируется в среде IDE, которая поддерживает IntelliSense.
Если я использую объявленную переменную var и не понимаю, для чего эта переменная, значит, с моим кодом что-то в корне не так. var не является причиной, он только делает видимыми симптомы. Не вините посланника.
Теперь команда C# выпустила руководство по кодированию, в котором говорится, что var должен использовать Только для захвата результата оператора LINQ, который создает анонимный тип (потому что здесь у нас нет реальной альтернативы var). Ну, к черту. Пока команда C# не дает мне веских аргументов в пользу этого правила, я буду игнорировать его, потому что, по моему профессиональному и личному мнению, это чистая чепуха. (Извините, у меня нет ссылки на данное руководство.)
На самом деле, есть некоторые (поверхностные) хорошие объяснения о том, почему вам не следует использовать var, но я все еще считаю, что они в основном ошибаются. Возьмем пример «поиска»: автор утверждает, что var затрудняет поиск мест, где используется MyType. Правильно. Так что интерфейсы. Собственно, зачем мне знать, где используется класс? Мне может быть больше интересно, где он создается, и это все равно будет доступно для поиска, потому что где-то должен быть вызван его конструктор (даже если это делается косвенно, имя типа должно быть где-то упомянуто).
В любой достойной среде IDE вы не используете текстовый поиск для получения информации об использовании класса, вы заставляете среду IDE делать это на основе дерева синтаксического анализа или, в противном случае, она определяет типы объектов. Поскольку мы говорим о статической типизации, он найдет все, кроме анонимных типов.
Я согласен с Конрадом. Я использовал var в других местах, кроме операторов LINQ, и считаю его весьма полезным.
Я согласен. var упрощает обслуживание моего кода. Я бы понял аргументы против, если бы он не был строго типизирован. Но это. Также, используя визуальную студию, почему мне нужно знать, какой класс находится в объявлении. Я могу навести курсор мыши или просто использовать IntelliSense, и это также значительно упрощает создание прототипов и рефакторинг. Для меня меньше кода и меньше беспорядка означает меньше ошибок.
Я бы не хотел наследовать 100 тыс. Строк исходного кода без документации и свободного использования var. Особенно, если вы комбинируете var с менее полезными именами переменных. Я мог видеть, что это полезно при иллюстрации точки (или работе с анонимными типами), но в производственном коде?
Arnshea: ну, вы уже указали на настоящую проблему: бесполезный имена переменных и отсутствующий документация. Я действительно не понимаю, что вносит var в путаницу. Конечно, могут быть случаи, когда важно подчеркнуть тип / размер переменной (например, битовые операции низкого уровня). Ничего страшного: никто никогда не утверждал, что нужно использовать исключительно var. Правило простое: если он действительно вызывает путаницу, не используйте его.
Каждый пример, противоположный var, который я видел, предполагает, что программист будет использовать бессмысленные имена переменных. Но, возможно, поэтому var является лучше, чем явное указание типа: это заставляет программиста придумывать хорошие имена переменных.
Microsoft также называет вывод типа «утиной типизацией». - правда ли? Я был бы в шоке ...
@Anton: извините, я не могу дать вам источник для этого утверждения (хотя поиск в библиотеке MSDN должен что-то дать), но да, Microsoft чрезмерно использовала это в своих превью нового ключевого слова var. Возможно, это было испорчено маркетингом, но в данном случае я в этом сомневаюсь.
Возможно, указание, на которое вы ссылаетесь (о котором я тоже помню), было отправлено в дыру в памяти. Я помню, как это случилось, когда Microsoft опубликовала действительно ужасную статью, якобы о TDD, которая на самом деле описывала противоположность TDD.
«... трудно найти места, где используется MyType» - а иногда много Полегче, чтобы найти места, где изначально создан или вызываются его статические методы, потому что другие использования (например, назначение из метода или вызов некоторого свойства) отфильтровываются. После этого я могу продолжить поиск использования конкретного свойства или метода, если мне нужно.
Я считаю, что утиная печать - признанная концепция. Я, конечно, слышал, что он используется для описания систем набора текста в других фреймворках.
@ElRonnoco Мы знаем это. Проблема в том, что утиная печать - это что-то разные, и Microsoft неправильно использовала этот термин.
@KonradRudolph Ах, извините, я неправильно понял.
@aku: Один из примеров - ревью кода. Другой пример - сценарии рефакторинга.
По сути, я не хочу заниматься поиском типов с помощью мыши. Это может быть недоступно.
Интересно, что вы так говорите, потому что var может упростить рефакторинг. Если вы использовали var, вам не нужно. Теперь вы всегда можете положиться на инструменты рефакторинга IDE, но вы знаете, что вы всегда можете положиться и на IDE для типа :)
Я не понимаю, в чем дело ...
var something = someMethod(); // Type of 'something' not clear <-- not to the compiler!
У вас все еще есть полный интеллект "что-то", и на любой неоднозначный случай у вас есть свои модульные тесты, верно? ( ты? )
Это не varchar, он не тусклый и, конечно же, не динамическая или слабая типизация. Это останавливает безумие вроде этого:
List<somethinglongtypename> v = new List<somethinglongtypename>();
и уменьшив этот общий беспорядок до:
var v = new List<somethinglongtypename>();
Красиво, не совсем так, как:
v = List<somethinglongtypename>();
Но тогда для этого и нужен Бу.
тип 'something' очень понятен компилятору, внутри 'var' устанавливается тип возвращаемого значения 'someMethod', это понятно компилятору, но может быть непонятно разработчикам, работающим над проектом. и Бу быстро растет на мне.
Нет, v = List<somethinglongtypename>(); даже не красивее. Важно различать введение новой переменной и присвоение существующей переменной.
Что ж, если вы ранее назначили 'v' в текущей области, тогда это назначение существующей. В противном случае это присвоение новой переменной 'v'. Легко.
@erlando,
Говоря о рефакторинге, кажется, намного проще изменить тип переменной, присвоив экземпляр нового типа одной переменной, а не изменяя его в нескольких местах, не так ли?
Что касается обзора кода, я не вижу больших проблем с ключевым словом вар. Во время проверки кода я предпочитаю проверять логику кода, а не типы переменных. Конечно, могут быть сценарии, в которых разработчик может использовать неподходящий тип, но я думаю, что количество таких случаев настолько мало, что не будет причиной для отказа от использования ключевого слова вар.
Поэтому я повторяю свой вопрос. Почему имеет значение для вас тип переменной?
Дело вкуса. Вся эта возня с тип переменной исчезает, когда вы привыкаете к языкам с динамической типизацией. То есть если вы когда-нибудь начнете любить их (не уверен, что все могут, но я люблю).
var в C# довольно крутой тем, что он выглядит похож на динамическую типизацию, но на самом деле это типизация статический - компилятор обеспечивает правильное использование.
Тип вашей переменной на самом деле не так важен (об этом уже говорилось ранее). Он должен быть относительно понятен из контекста (его взаимодействия с другими переменными и методами) и его имени - не ожидайте, что customerList будет содержать int ...
Я все еще жду, чтобы узнать, что мой босс думает по этому поводу - у меня есть повод использовать любые новые конструкции в 3.5, но что мы будем делать с техобслуживанием?
При сравнении IEnumerable<int> и IEnumerable<double> вам не о чем беспокоиться - если вы передадите неправильный тип, ваш код все равно не будет компилироваться.
Не стоит беспокоиться о безопасности типов, поскольку var является динамическим нет. Это просто магия компилятора, и любые небезопасные вызовы, которые вы делаете, будут пойманы.
Var абсолютно необходим для 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
};
Теперь посмотрите на anonEnumeration в intellisense, и он будет выглядеть примерно как 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
}
Компилятор C# довольно умен - отдельные типы, сгенерированные отдельно, будут иметь один и тот же сгенерированный тип, если их свойства совпадают.
В остальном, если у вас есть intellisense, имеет смысл использовать var везде, где контекст понятен.
//less typing, this is good
var myList = new List<UnreasonablyLongClassName>();
//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;
Удалите IQueriable<T> перед повторением: anonEnumeration.ToList();
@DavidDiez не могли бы вы перефразировать? Ваше заявление не имеет смысла. Ни один из моих фрагментов кода не ссылается на IQueryable или .ToList().
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 }; не возвращает IQueriable<T>?
@DavidDiez, это зависит от того, что возвращает AllPosts() - спрашивающий ссылается на List<T>, поэтому я предположил, что это. В этом случае результат таков, что anonEnumeration будет иметь тип IEnumerable<'a>. Теперь, если AllPosts() возвращает IQueryable<T>, тогда anonEnumeration станет IQueryable<'a> (обратите внимание на отсутствие i в Queryable) - однако в этом случае мой код Все еще работает, потому что IQueryable<T> реализует IEnumerable<T>. Здесь есть множество лучших вопросов и ответов о различиях между ними - здесь мой случай состоит в том, что 'a является анонимным, а var позволяет вам назначить его статически типизированной переменной.
Ох, понятно, спасибо за объяснение :) Мой комментарий был потому, что повторение IQueryable<T> не является хорошей практикой, потому что на каждой итерации вы делаете оператор чтения в БД. Убедитесь, что *.ToList()IQueryable<T> перед их повторением
Я разбил var повсюду, единственные сомнительные места для меня - это внутренние короткие типы, например Я предпочитаю int i = 3;, а не var i = 3;
@Keith -
In your comparison between IEnumerable<int> and IEnumerable<double> you don't need to worry - if you pass the wrong type your code won't compile anyway.
Это не совсем так - если метод перегружен как для IEnumerable <int>, так и для IEnumerable <double>, он может молча передать неожиданный предполагаемый тип (из-за некоторых других изменений в программе) в неправильную перегрузку, что приведет к неправильному поведению .
Я полагаю, вопрос в том, насколько вероятно возникновение такой ситуации!
Я предполагаю, что часть проблемы заключается в том, сколько путаницы добавляет var к заданному объявлению - если неясно, что это за тип (несмотря на то, что он строго типизирован и компилятор полностью понимает, какой это тип), кто-то может скрыть ошибку безопасности типа или по крайней мере, потребуется больше времени, чтобы понять фрагмент кода.
Я использую var в следующих ситуациях:
Когда тип находится в той же строке, что и код, например
var emp = новый сотрудник ();
Очевидно, что нам нужен Employee (потому что мы создаем новый объект Employee), так как же
Employee emp = new Employee() any more obvious?
Я НЕ использую var, если тип нельзя вывести, например
var emp = GetEmployee();
Потому что тип возвращаемого значения не сразу очевиден (есть у Employee, IEmployee, что-то, что вообще не имеет ничего общего с объектом Employee и т. д.?).
Так говорят все, кто выступает против var. Но Почему, вам нужно знать, кто это: Сотрудник или IEmployee? Какая практическая разница в том, что вы делаете?
«Я НЕ использую var, если тип не может быть выведен» - Гм, вы НЕ МОЖЕТЕ использовать var, когда тип не может быть выведен, поскольку var зависит от вывода типа. В вашем примере тип МОЖЕТ быть выведен.
@Joel Mueller Я имел в виду выведенный человеком, а не анализатором. Я думал, что это ясно из следующего предложения.
Что ж, если тип возвращаемого значения не имеет никакого отношения к объекту служащего, то вызов метода GetEmployee, вероятно, был плохим решением. На мой взгляд, обстоятельства, при которых человеку необходимо узнать, является ли это Employee или IEmployee, за меньшее время, чем требуется, чтобы навести курсор мыши на переменную, довольно ограничены. Я думаю, что человек может с довольно высокой степенью уверенности сделать вывод о том, что ему нужно знать, даже если он использует var. Не то чтобы вы, конечно, должны со мной соглашаться, я просто не думаю, что это хороший аргумент против использования var.
Вы правы насчет IEmployee vs Employee. Однако мое личное мнение таково, что отсутствие фактического типа прямо на экране противоречит духу строго типизированного языка, такого как C# (просто интуитивное ощущение ... ничего поддающегося количественной оценке). Я нервничаю, когда кто-то делает var e = GetEmployee ()? Нисколько. На самом деле, я, наверное, и сам делал это много раз.
После простого перехода на фреймворки 3.0 и 3.5 я узнал об этом ключевом слове и решил попробовать. Перед тем, как коммитить какой-либо код, я осознал, что это кажется обратным, как при возврате к синтаксису ASP. Поэтому я решил потрогать руководство, чтобы узнать, что они думают.
Они сказали, давай, так что я его использую.
С учетом сказанного, я избегаю использовать его там, где тип требует некоторого исследования, например:
var a = company.GetRecords ();
Теперь это может быть просто личная вещь, но я сразу не могу посмотреть на это и определить, является ли это коллекцией объектов Record или строковым массивом, представляющим имя записей. В любом случае, я считаю, что явное объявление полезно в таком случае.
Вы возражаете против var на основании неправильных имен переменных и методов. Было бы var все еще так плохо, если бы в вашем примере использовались имена переменных и методов хороший?
Не обязательно. Пока я просматриваю код, я сразу знаю, какого типа переменная, без необходимости проверять присваивающий ее метод, я за это.
Я должен согласиться с Мэтт Гамильтон.
Var может сделать ваш код более читаемым и понятным, если использовать его с хорошими именами переменных. Но var также может сделать ваш код таким же невозможным для чтения и понимания, как Perl при неправильном использовании.
Список хороших и плохих вариантов использования var тоже не поможет. Это случай здравого смысла. Более крупный вопрос - это удобочитаемость и возможность записи. Многим разработчикам все равно, читается ли их код. Они просто не хотят так много печатать. Лично я умею читать> писать.
кроноз - в таком случае (перегрузки для обоих) имело бы значение? Если у вас есть две перегрузки, которые принимают разные типы, вы, по сути, говорите, что любую из них можно передать и сделать то же самое.
У вас не должно быть двух перегрузок, которые выполняют совершенно разные действия в зависимости от переданных типов.
Хотя вы можете запутаться в этом случае, он все равно будет полностью безопасным по типу, у вас просто будет кто-то, вызывающий неправильный метод.
Я не понимаю, почему люди начинают такие дебаты. На самом деле это не служит никакой цели, чем начинать огненные войны, в конце которых ничего не получается. Теперь, если команда C# пыталась постепенно отказаться от одного стиля в пользу другого, я вижу причину спорить о достоинствах каждого стиля. Но поскольку оба они останутся в языке, почему бы не использовать тот, который предпочитает ты, и позволить всем делать то же самое. Это похоже на использование всеми любимого тернарного оператора: кому-то он нравится, а кому-то нет. В конце концов, для компилятора это не имеет значения.
Это похоже на споры с братьями и сестрами о том, кто ваш любимый родитель: это не имеет значения, если они не разводятся!
Статическая типизация касается контрактов, а не исходного кода. Идея заключается в необходимости иметь статическую информацию в одной строке того, что «должно» быть небольшим методом. Общие рекомендации редко рекомендуют использовать более 25 строк на метод.
Если метод достаточно велик, что вы не можете отслеживать одну переменную в этом методе, вы делаете что-то еще не так, что сделало бы любую критику var бледной по сравнению с ним.
Фактически, одним из замечательных аргументов в пользу var является то, что он может упростить рефакторинг, потому что вам больше не нужно беспокоиться о том, что вы сделали свое объявление чрезмерно ограничивающим (т.е. вы использовали List <>, когда вам следовало использовать IList <> или IEnumerable <> ). Вы все еще хотите подумать о сигнатуре новых методов, но, по крайней мере, вам не придется возвращаться и изменять свои объявления в соответствии с ними.
Я считаю, что использование ключевого слова var на самом деле делает код более читаемым, потому что вы просто привыкаете пропускать ключевое слово var. Вам не нужно постоянно прокручивать вправо, чтобы выяснить, что делает код, когда вам действительно все равно, что это за конкретный тип. Если мне действительно нужно знать, какой тип «элемент» находится ниже, я просто наведу на него указатель мыши, и Visual Studio сообщит мне. Другими словами, я бы предпочел прочитать
foreach( var item in list ) { DoWork( item ); }
снова и снова, чем
foreach( KeyValuePair<string, double> entry in list ) { DoWork( Item ); }
когда пытаюсь переварить код. Я думаю, что в какой-то степени это связано с личными предпочтениями. Я бы полагался на здравый смысл в этом вопросе - сохраните стандарты для важных вещей (безопасность, использование базы данных, ведение журнала и т. д.)
-Алан.
Мы приняли идеал «Код для людей, а не для машин», исходя из предположения, что в режиме обслуживания вы проводите в несколько раз больше времени, чем при новой разработке.
Для меня это исключает аргумент о том, что компилятор «знает», какого типа переменная - конечно, вы не можете написать недопустимый код в первый раз, потому что компилятор останавливает компиляцию вашего кода, но когда следующий разработчик читает код через 6 месяцев им необходимо определить, что переменная делает правильно или неправильно, и быстро определить причину проблем.
Таким образом,
var something = SomeMethod();
запрещено нашими стандартами кодирования, но наша команда приветствует следующее, поскольку это повышает удобочитаемость:
var list = new List<KeyValuePair<string, double>>();
FillList( list );
foreach( var item in list ) {
DoWork( item );
}
Я обнаружил, что («Код для людей, а не для машин») является отличным руководством - следование ему может привести к улучшению кода и поможет избежать преждевременной оптимизации.
Я не получаю var list = new KeyValuePair <string, double>? Для меня в списке может быть больше, чем просто предмет.
«Код для людей, а не для машин» - аминь.
От Эрика Липперта, старшего инженера-разработчика программного обеспечения в команде C#:
Почему было введено ключевое слово var?
There are two reasons, one which exists today, one which will crop up in 3.0.
The first reason is that this code is incredibly ugly because of all the redundancy:
Dictionary<string, List<int>> mylists = new Dictionary<string, List<int>>();And that's a simple example – I've written worse. Any time you're forced to type exactly the same thing twice, that's a redundancy that we can remove. Much nicer to write
var mylists = new Dictionary<string,List<int>>();and let the compiler figure out what the type is based on the assignment.
Second, C# 3.0 introduces anonymous types. Since anonymous types by definition have no names, you need to be able to infer the type of the variable from the initializing expression if its type is anonymous.
Акцент мой. Вся статья, C# 3.0 по-прежнему статически типизирован, честно!, и последующий серии довольно хороши.
Для этого и предназначен var. Другие варианты использования, вероятно, не будут работать так хорошо. Любое сравнение с JScript, VBScript или динамической типизацией - полная чушь. Заметим еще раз, var - это требуется, чтобы некоторые другие функции работали в .NET.
Я считаю аргумент Липперта странным. Никто не вводит имя второго класса, они позволяют Intellisense написать его за них, но затем он оборачивается и заявляет, что var лучше, потому что компилятор / Intellisense работает с этим. Вы не можете получить и то, и другое!
Команда C# не контролирует intellisense, они контролируют компилятор. В любом случае это не главная проблема. Я не думаю, что var смог бы заработать 100 очков только на том, чтобы сэкономить на вводе текста.
@Dustman: var вообще не экономит ввод. Это заставляет писать больше!
На мой взгляд, антипатия к var иллюстрирует важность двуязычия в .NET. Для тех программистов на C#, которые также работали с VB .NET, преимущества var интуитивно очевидны. Стандартное объявление C#:
List<string> whatever = new List<string>();
является эквивалентом в VB .NET такой команды:
Dim whatever As List(Of String) = New List(Of String)
Однако никто не делает этого в VB .NET. Было бы глупо, потому что с первой версии .NET вы могли это делать ...
Dim whatever As New List(Of String)
... который создает переменную и инициализирует ее в одной достаточно компактной строке. Ах, но что, если вам нужен IList<string>, а не List<string>? Что ж, в VB .NET это означает, что вам нужно сделать это:
Dim whatever As IList(Of String) = New List(Of String)
Точно так же, как вы должны были бы сделать в C# и, очевидно, не могли бы использовать var для:
IList<string> whatever = new List<string>();
Если вы необходимость тип будет чем-то другим, это может быть. Но одним из основных принципов хорошего программирования является уменьшение избыточности, и это именно то, что делает var.
Забавно, что вы упоминаете двуязычие как нечто, способствующее использованию var. Мой антагонизм по отношению к ключевому слову var проистекает непосредственно из моего свободного владения javascript! :)
var в C# никак не связан с var в JavaScript. Переменная, объявленная var в C#, строго типизирована.
Используйте его для анонимных типов - вот для чего он нужен. Все остальное - слишком далеко. Как и многие люди, выросшие на C, я привык смотреть слева от объявления для определения типа. Я не смотрю на правую сторону, если мне не нужно. Использование var для любого старого объявления заставляет меня делать это все время, что мне лично неудобно.
Те, кто говорит: «Неважно, используйте то, что вам нравится», не видят всей картины. Каждый в тот или иной момент подхватит чужой код и должен будет иметь дело с теми решениями, которые они приняли во время написания. Достаточно плохо иметь дело с радикально отличающимися соглашениями об именах или - классическими стилями жесткости - без добавления целого «var или нет» в смесь. В худшем случае один программист не использовал var, а затем приходит сопровождающий, которому он нравится, и расширяет код, используя его. Итак, теперь у вас ужасный беспорядок.
Стандарты - это хорошо именно потому, что они означают, что у вас гораздо больше шансов выбрать случайный код и быстро его проанализировать. Чем больше различий, тем сложнее становится. А переход к стилю «var везде» имеет значение большой.
Я не против динамического набора текста и не против неявного набора текста - на языках, которые предназначены для них. Мне очень нравится Python. Но C# был разработан как язык с явной статической типизацией, и таким он и должен оставаться. Нарушение правил для анонимных типов было уже достаточно плохо; Позволить людям пойти еще дальше и еще больше разрушить идиомы языка - это то, что меня не устраивает. Теперь, когда джинн из бутылки, он больше никогда не вернется. C# превратится в лагеря. Фигово.
Вау. Игнорирование всех аргументов, приведенных в этой ветке, и переустройство всего обсуждения - настоящее достижение.
Это 100% описывает, как я отношусь к var, особенно с точки зрения подбора чужого кода. Использование var радикально меняет текущую задачу, если она полностью замусорена. +1
Я думаю, что люди не понимают ключевое слово var. Они путают его с ключевым словом Visual Basic / JavaScript, который вместе взятый - совсем другой зверь.
Многие думают, что ключевое слово var подразумевает слабая типизация (или динамическая типизация), тогда как на самом деле C# является и остается строго типизированным.
Если учесть это в javascript:
var something = 5;
вам разрешено:
something = "hello";
В случае C# компилятор определит тип из первого оператора, вызывая что-то типа "int", поэтому второй оператор приведет к в исключении.
Людям просто нужно понимать, что использование ключевого слова var не подразумевает динамическая типизация, а затем решить, насколько далеко они хотят зайти с помощью ключевого слова var, зная, что у него не будет абсолютно никакой разницы в том, что будет скомпилировано.
Конечно, ключевое слово var было введено для поддержки анонимных типов, но если вы посмотрите на это:
LedDeviceController controller = new LedDeviceController("172.17.0.1");
Это очень, очень многословно, и я уверен, что это так же легко читается, если не больше:
var controller = new LedDeviceController("172.17.0.1");
Результат точно такой же, поэтому да, я использую его во всем своем коде
ОБНОВИТЬ:
Может быть, просто может ... им следовало использовать другое ключевое слово, тогда у нас не было бы этого обсуждения ... возможно, ключевое слово "infred" вместо "var"
var необходим для анонимных типов (как указано в одном из предыдущих ответов на этот вопрос).
Все остальные обсуждения ее плюсов и минусов я бы назвал «религиозной войной». Под этим я подразумеваю, что сравнение и обсуждение относительных достоинств ...
var i = 5;
int j = 5;
SomeType someType = new SomeType();
var someType = new SomeType();
... полностью субъективно.
Неявная типизация означает, что нет никаких штрафов во время выполнения для любой переменной, объявленной с использованием ключевого слова var, поэтому это сводится к спору о том, что делает разработчиков счастливыми.
Похищено с сообщение по этой проблеме на CodingHorror:
К сожалению, вы и все остальные в значительной степени ошиблись. Хотя я согласен с вами, что избыточность - это нехорошо, лучший способ решить эту проблему - это сделать что-то вроде следующего:
MyObject m = новый ();
Или если вы передаете параметры:
Человек p = new («Имя», «Фамилия»);
Если при создании нового объекта компилятор определяет тип с левой стороны, а не с правой. У этого есть и другие преимущества перед var, в том, что он также может использоваться в объявлениях полей (есть и другие области, в которых он также может быть полезен, но я не буду здесь вдаваться в подробности).
В конце концов, это просто не предназначалось для уменьшения избыточности. Не поймите меня неправильно, "var" ОЧЕНЬ важен в C# для анонимных типов / проекций, но его использование здесь просто ВАЖНО (и я говорил это уже давно), поскольку вы запутываете тип, который используется. Слишком часто приходится набирать его дважды, но объявлять ноль - слишком мало.
Николас Палдино. .NET / C# MVP, 20 июня 2008 г., 8:00
Думаю, если ваша главная забота - печатать меньше, то нет никаких аргументов, которые заставят вас отказаться от этого.
Если вы собираетесь только Когда-либо быть человеком, который смотрит на ваш код, то кого это волнует? В противном случае в таком случае:
var people = Managers.People
это нормально, но в таком случае:
var fc = Factory.Run();
он замыкает любые непосредственные типовые выводы, которые мой мозг мог начать формировать из «английского» кода.
В противном случае просто используйте здравый смысл и программируйте «вежливость» по отношению к другим людям, которым, возможно, придется работать над вашим проектом.
Приведенные выше примеры не являются аргументом в пользу отказа от использования var; они являются аргументом в пользу использования хороших описательных имен переменных. Если бы вместо [var fc = Factory.Run ();] у вас был [bool fc = Factory.Run ();], код не стал бы более понятным.
По возможности использую var.
Фактический тип локальной переменной не должно иметь значения, если ваш код хорошо написан (например, хорошие имена переменных, комментарии, четкая структура и т. д.)
Я не использую var, поскольку он противоречит корням C# - C / C++ / Java. Несмотря на то, что это уловка компилятора, язык кажется менее типизированным. Может быть, 20 с лишним лет C укоренили все это в наших (противников варваров) головах, что у нас должен быть тип как слева, так и справа от равных.
Сказав, что я вижу его достоинства для длинных общих определений коллекций и длинных имен классов, таких как пример codinghorror.com, но в других местах, таких как string / int / bool, я действительно не вижу смысла. Особенно
foreach (var s in stringArray)
{
}
экономия 3 символа!
Меня больше всего раздражает то, что я не могу видеть тип, который представляет var для вызовов методов, если только вы не наведете курсор на метод или не нажмете клавишу F12.
Хех. Если C++ / Java / etc. вы представляете, каким должен быть строго / статически типизированный язык, то вы никогда не использовали язык с реальной системой статических типов, многие из которых имеют гораздо больше выводов типов, чем C# и, гораздо более сильные гарантии типов, чем языки, которые вы упомянуть. Эта реакция на var - простое и чистое программирование культа карго.
@ C.A.McCann, ты говоришь, что типы - это программирование культа карго? Я запутался. var был введен в C# в версии 3.0 вместе с LINQ, который, возможно, был его основной целью. Я (и другие нытики вроде меня) обошелся без него в течение пяти лет разработки C#.
Статические типы - это здорово, писать типы для каждого объявления в большинстве случаев бесполезно. Вывод типов существует дольше, чем сам C#, в языках, в которых есть настоящие статические типы, а не искалеченный мусор, который вы получаете в языках стиля C.
VS2008 w / resharper 4.1 имеет правильный ввод во всплывающей подсказке, когда вы наводите курсор на «var», поэтому я думаю, что он сможет найти это, когда вы будете искать все использования класса.
Хотя еще не проверял, что он это делает.
Приходите немного поздно к этому обсуждению, но я просто хотел бы добавить мысль.
А как насчет лямбда-выражений всем тем, кто выступает против вывода типов (потому что именно об этом мы здесь говорим)? Если вы настаиваете на том, чтобы типы всегда объявлялись явно (за исключением анонимных типов), что вы делаете с лямбдами? Как аргумент «Не заставлять меня использовать наведение указателя мыши» применим к var, но не к лямбдам?
ОБНОВИТЬ
Я только что подумал об одном аргументе против 'var', который, я думаю, никто еще не упоминал, а именно то, что он «нарушает» «Найти все ссылки», что может означать (например), что если вы проверяли использование класса до рефакторинга, вы пропустите все места, где этот класс использовался через var.
Интересно, сколько людей, поддерживающих варвар, были «загрязнены» F#? :)
Это правда. Мне часто хочется, чтобы вывод типа C# был таким же хорошим, как вывод в F#.
В зависимости от того, как-то это заставляет код выглядеть «чище», но согласитесь, что это делает его более нечитаемым для ...
Думаю, это зависит от вашей точки зрения. У меня лично никогда не было проблем с пониманием фрагмента кода из-за «неправильного использования» var, и мы с моими коллегами постоянно его применяем. (Я согласен с тем, что Intellisense очень помогает в этом отношении.) Я приветствую его как способ избавиться от повторяющегося мусора.
В конце концов, если такие утверждения, как
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
были действительно настолько невозможны, что никто не стал бы использовать языки с динамической типизацией.
Предположительно, в .Net 4, где динамические типы являются обычным явлением, это станет более важным?
Напротив, если вы сейчас сбиты с толку словом «var», я ожидаю, что вас еще больше сбивает с толку слово «dynamic». Не дай Бог кому-либо объявить динамику, а затем сделать ссылку на нее с помощью "var" :)
Я имел в виду что-то вроде динамического d = 52; var x = d; что должно быть хорошо.
Это может сделать код проще и короче, особенно со сложными универсальными типами и делегатами.
Кроме того, это упрощает изменение типов переменных.
Учитывая, насколько мощным сейчас является Intellisense, я не уверен, что var читать труднее, чем иметь переменные-члены в классе или локальные переменные в методе, которые определены за пределами видимой области экрана.
Если у вас есть строка кода, например
IDictionary<BigClassName, SomeOtherBigClassName> nameDictionary = new Dictionary<BigClassName, SomeOtherBigClassName>();
Его читать намного легче или труднее, чем:
var nameDictionary = new Dictionary<BigClassName, SomeOtherBigClassName>();
Я на самом деле не рассматривал это, поскольку из другого вопроса кажется, что это довольно сильная сторона для еще одного раза, чтобы использовать его.
По сути, это была единственная причина, по которой они его реализовали (помимо возможности объявлять анонимные типы, но они могли сделать «var» специальным ключевым словом, предназначенным только для анонимных типов).
var отлично подходит, когда вы не хотите повторяться. Например, вчера мне понадобилась структура данных, похожая на эту. Какое представление вы предпочитаете?
Dictionary<string, Dictionary<string, List<MyNewType>>> collection = new Dictionary<string, Dictionary<string, List<MyNewType>>>();
или же
var collection = new Dictionary<string, Dictionary<string, List<MyNewType>>>();
Обратите внимание, что использование var в этом примере вносит небольшую двусмысленность. Однако бывают случаи, когда это было бы не такой уж хорошей идеей. Например, если я использовал var, как показано ниже,
var value= 5;
когда я мог просто написать настоящий тип и устранить любую двусмысленность в том, как должен быть представлен 5.
double value = 5;
Обратите внимание, первое значение не имеет двусмысленности, все числовые типы имеют собственный буквальный синтаксис. 5 для int, 5LU для беззнакового long, 5m для десятичного, ...
@Richard: Никакой двусмысленности компилятора - но не очень хорошо для обслуживания.
@Jeff: просто расширил свой ответ по этой теме. Изучение F# действительно изменило мое мнение ...
Использование double вместо var в вашем примере не «устраняет двусмысленность»; он меняет код. [var value = 5;] делает значение int, а не double. Но вы также можете сделать [var value = 5.0;], чтобы сделать его двойным.
@Kyralessa: да, по сути, это так. Однако, несмотря на это, мысль, о которой я говорил, все еще актуальна.
Фактически, вы указываете, в чем ошибка использования здесь var. Вы теряете намерение и, возможно, это может привести к проблемам (например, получить int вместо double).
Это, безусловно, может упростить задачу, исходя из кода, который я написал вчера:
var content = new Queue<Pair<Regex, Func<string, bool>>>();
...
foreach (var entry in content) { ... }
Без var это было бы очень многословно.
Приложение: немного времени, потраченное на язык с выводом типа настоящий (например, F#), покажет, насколько хороши компиляторы для правильного определения типа выражений. Это определенно означало, что я стараюсь использовать var как можно чаще, а использование явного типа теперь указывает на то, что переменная не относится к типу инициализирующего выражения.
Ага, компиляторы умнее нас, перестаньте!
Много раз во время тестирования я обнаруживал, что имею такой код:
var something = myObject.SomeProperty.SomeOtherThing.CallMethod();
Console.WriteLine(something);
Иногда я хочу посмотреть, что содержит сам SomeOtherThing, SomeOtherThing - это не тот тип, который возвращает CallMethod (). Поскольку я использую var, я просто меняю это:
var something = myObject.SomeProperty.SomeOtherThing.CallMethod();
к этому:
var something = myObject.SomeProperty.SomeOtherThing;
Без var мне пришлось бы также менять объявленный тип с левой стороны. Я знаю, что это мелочь, но очень удобно.
Я не думаю, что var per say - ужасная языковая функция, поскольку я использую ее ежедневно с кодом, подобным тому, что описал Джефф Йейтс. На самом деле, почти каждый раз я использую var потому, что обобщения могут сделать код очень многословным. Я живу подробным кодом, но дженерики заходят слишком далеко.
Тем не менее, я (очевидно ...) думаю, что var созрел для злоупотреблений. Если код достигает 20+ строк в методе с заваленными варами, вы быстро превратите обслуживание в кошмар. Кроме того, использование var в учебнике невероятно противоречит интуиции и, как правило, не используется в моих книгах.
С другой стороны, var - это «простая» функция, которую новые программисты собираются ухватить и полюбить. Затем, в течение нескольких минут / часов / дней, они столкнутся с огромным препятствием, когда они начнут достигать пределов. «Почему я не могу вернуть var из функций?» Такой вопрос. Кроме того, добавление псевдодинамического типа к строго типизированному языку может легко сбить с толку нового разработчика. Я думаю, что в конечном итоге ключевое слово var действительно затруднит изучение C# для начинающих программистов.
Тем не менее, как опытный программист я использую var, в основном, при работе с дженериками (и, очевидно, с анонимными типами). Я придерживаюсь своей цитаты, я верю, что var будет одной из самых злоупотребляемых функций C#.
Фраза «сама по себе». Это по-латыни означает «сам по себе». Я согласен с тем, что var следует использовать с осторожностью, если вообще следует использовать в учебниках или примере кода, но только потому, что такой код обычно не читается в среде IDE.
В крайних случаях обязательно возникнут разногласия, но я могу сказать вам свои личные рекомендации.
Я смотрю на эти критерии, когда решаю использовать var:
И наоборот, эти ситуации заставили бы меня не использовать var:
Наконец, я бы никогда не использовал var для собственных типов значений или соответствующих типов nullable<> (int, decimal, string, decimal?, ...). Существует неявное предположение, что если вы используете var, должна быть «причина».
Это все рекомендации. Вам также следует подумать об опыте и навыках ваших коллег, сложности алгоритма, долговечности / масштабе переменной и т. д. И т. Д.
В большинстве случаев нет идеального правильного ответа. Или это не имеет значения.
[Обновлено: удален повторяющийся маркер]
От Essential LINQ:
Лучше не объявлять явно тип переменной диапазона без крайней необходимости. Например, следующий код компилируется чисто, но тип мог быть определен компилятором без формального объявления:
List<string> list = new List<string> { "LINQ", "query", "adventure" };
var query = from string word in list
where word.Contains("r")
orderby word ascending
select word;
Явное объявление типа переменной диапазона вызывает скрытый вызов оператора LINQ Cast. Этот вызов может иметь непредвиденные последствия и может снизить производительность. Если вы сталкиваетесь с проблемами производительности с запросом LINQ, приведение, подобное показанному здесь, является одним из возможных мест для начала поиска виновника. (Единственное исключение из этого правила - когда вы работаете с неуниверсальным Enumerable, и в этом случае вам следует использовать приведение.)
Нет, за исключением того, что вам не нужно писать имя типа дважды. http://msdn.microsoft.com/en-us/library/bb383973.aspx
Это чисто удобство. Компилятор определит тип (на основе типа выражения справа)
В большинстве случаев набрать его проще - представьте
var sb = new StringBuilder();
вместо:
StringBuilder sb = new StringBuilder();
Иногда требуется, например: анонимные типы, вроде.
var stuff = new { Name = "Me", Age = 20 };
Мне лично нравится его использовать, несмотря на то, что он делает код менее читабельным и удобным в обслуживании.
Вам не нужно записывать имя типа, и это не менее эффективно, поскольку тип разрешается во время компиляции.
Скорее всего, это понадобится для анонимных типов (где это требуется на 100%); но это также позволяет избежать повторения в тривиальных случаях, а IMO делает линию более ясной. Мне не нужно видеть тип дважды для простой инициализации.
Например:
Dictionary<string, List<SomeComplexType<int>>> data = new Dictionary<string, List<SomeComplexType<int>>>();
(пожалуйста, не редактируйте hscroll выше - это вроде как подтверждает точку зрения !!!)
против:
var data = new Dictionary<string, List<SomeComplexType<int>>>();
Однако бывают случаи, когда это вводит в заблуждение и потенциально может вызвать ошибки. Будьте осторожны при использовании var, если исходная переменная и инициализированный тип не идентичны. Например:
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);
(для информации вы можете получить аналогичные проблемы во всем, где это неявное преобразование типа)
Не согласитесь с той частью, которую вы не хотите видеть дважды в одной строке. Возможно, что в будущем вы не будете напрямую создавать переменную после объявления (например, в if под определением), чем напрямую может быть неясно, что это за тип. Большинство разработчиков привыкли видеть тип непосредственно в начале строки, особенно в сложном коде, который не должен усложнять чтение кода.
@TheVillageIdiot - Я откатил ваше редактирование, потому что в этом случае hscroll связан с точкой ;-p
@Gertjan - мой мозг ограничен; если это сложно, я не хочу увидеть это дважды и должен начать сравнение (интерфейс / конкретный / и т. д.). Я счастлив увидеть это однажды и подумать «напечатано как один из них».
Использование var вместо явного типа значительно упрощает рефакторинг (поэтому я должен противоречить предыдущим плакатам, которые имели в виду, что это не имеет значения или это просто «синтаксический сахар»).
Вы можете изменить тип возвращаемого значения ваших методов, не меняя каждый файл, в котором вызывается этот метод. Представлять себе
...
List<MyClass> SomeMethod() { ... }
...
который используется как
...
IList<MyClass> list = obj.SomeMethod();
foreach (MyClass c in list)
System.Console.WriteLine(c.ToString());
...
Если вы хотите провести рефакторинг SomeMethod() для возврата IEnumerable<MySecondClass>, вам придется изменить объявление переменной (также внутри foreach) в каждом месте, где вы использовали метод.
Если вы напишете
...
var list = obj.SomeMethod();
foreach (var element in list)
System.Console.WriteLine(element.ToString());
...
вместо этого вам не нужно его менять.
согласился - удивляясь, почему этот приятный побочный эффект не рекламируется так часто, как некоторые другие, более субъективные плюсы, в более популярных ответах.
Это случилось со мной сегодня. У меня есть фабричный класс, который возвращает istance класса MainMenu. Сегодня я создал MainMenu2 с тем же интерфейсом, что и MainMenu. После изменения код моего приложения остался нетронутым!
Вы можете позволить компилятору (и тому, кто обслуживает код следующим) вывести тип из правой части присвоения инициализатора. Если такой вывод возможен, компилятор может это сделать, чтобы сэкономить на вводе текста с вашей стороны.
Если этому бедолаге легко сделать вывод, значит, вы ничего не обидели. Если вывод сложен, значит, вы усложнили поддержку кода, и поэтому, как правило, Я бы не стал этого делать.
Наконец, если вы предполагали, что типом будет что-то конкретное, а ваше выражение инициализатора на самом деле имеет другой тип, использование var означает, что вам будет сложнее найти вызванную ошибку. Явно сообщая компилятору, каким должен быть тип, когда тип не тот, вы получите немедленную диагностику. Задействуя объявление типа и используя «var», вы не получите ошибки при инициализации; вместо этого вы получите ошибку типа в некотором выражении, которое использует идентификатор, присвоенный выражением var, и будет труднее понять, почему.
Итак, мораль такова: используйте var экономно; как правило, вы не делаете много хорошего ни себе, ни другому сопровождающему. И надеюсь, что он рассуждает так же, чтобы вы не застряли в догадках о его намерениях, потому что он думал, что использовать var было легко. Оптимизация того, сколько вы печатаете, является ошибкой при кодировании системы с долгим сроком службы.
Иногда компилятор также может сделать вывод о том, что требуется, «лучше», чем разработчик - по крайней мере, разработчик, который не понимает, что требуется для используемого API.
Например - при использовании linq:
Пример 1
Func<Person, bool> predicate = (i) => i.Id < 10;
IEnumerable<Person> result = table.Where(predicate);
Пример 2
var predicate = (Person i) => i.Id < 10;
var result = table.Where(predicate);
В приведенном выше коде - при условии, что вы используете Linq to Nhibernate или Linq to SQL, пример 1 будет вернуть весь набор результатов для объектов Person, а затем выполнить фильтрацию на стороне клиента. Однако в примере 2 запрос будет выполняться на сервере (например, на сервере Sql с SQL), поскольку компилятор достаточно умен, чтобы определить, что функция Where должна принимать Expression>, а не Func.
Результат в Примере 1 также не будет запрашиваться на сервере в дальнейшем, поскольку возвращается IEnumerable, тогда как в Примере 2 компилятор может решить, если результатом будет IQueryable вместо IEnumerable.
Раньше я думал, что ключевое слово var было отличным изобретением, но я поставил на него ограничение:
Я понял, что это не дало мне никакой пользы, и удалил все ключевые слова var из моего кода (если они не были специально необходимы), а сейчас я думаю, что они делают код менее читаемым, особенно для других, читающих ваш код.
Он скрывает намерение и, по крайней мере, в одном случае приводит к ошибке времени выполнения в некотором коде из-за предположения о типе.
Из обсуждения этой темы, как представляется, результат:
Хорошо: var customers = new List<Customer>();
Спорный: var customers = dataAccess.GetCustomers();
Игнорируя ошибочное мнение о том, что «var» волшебным образом помогает в рефакторинге, самая большая проблема для меня - это настойчивое утверждение людей, что им все равно, какой будет возвращаемый тип, «пока они могут перечислить коллекцию».
Учитывать:
IList<Customer> customers = dataAccess.GetCustomers();
var dummyCustomer = new Customer();
customers.Add(dummyCustomer);
Теперь рассмотрим:
var customers = dataAccess.GetCustomers();
var dummyCustomer = new Customer();
customers.Add(dummyCustomer);
Теперь идите и реорганизуйте класс доступа к данным, чтобы GetCustomers вернул IEnumerable<Customer>, и посмотрите, что произойдет ...
Проблема здесь в том, что в первом примере вы явно выражаете свои ожидания от метода GetCustomers - вы говорите, что ожидаете, что он вернет что-то, что ведет себя как список. Во втором примере это ожидание неявно и не очевидно из кода.
Мне интересно (для меня), что многие аргументы pro-var говорят: «Мне все равно, какой тип он возвращает», но продолжают говорить: «Мне просто нужно перебрать его ...». (поэтому необходимо реализовать интерфейс IEnumerable, подразумевая значение типа делает).
Для фанатов, которые думают, что var экономит время, для ввода требуется меньше нажатий клавиш:
StringBuilder sb = new StringBuilder();
чем
var sb = new StringBuilder();
Считай их, если ты мне не веришь ...
19 против 21
Я объясню, если мне нужно, но просто попробуйте ... (в зависимости от текущего состояния вашего intellisense вам может потребоваться ввести еще пару для каждого)
И это верно для любого типа, о котором вы только можете подумать !!
Лично я считаю, что var никогда не следует использовать, кроме случаев, когда тип неизвестен, потому что это снижает читаемость распознавания в коде. Мозгу требуется больше времени, чтобы распознать тип, чем целую строку. Старожилы, разбирающиеся в машинном коде и битах, точно знают, о чем я говорю. Мозг обрабатывает параллельно, и когда вы используете var, вы заставляете его сериализовать ввод. Зачем кому-то заставлять свой мозг работать усерднее? Вот для чего нужны компьютеры.
Я считаю повторение stringBuilder sb = new StringBuilder () беспорядочным и более длинным, чтобы его можно было четко распознать. Это лишний шум. Проблема в том, что определение того, что представляет собой, а что не составляет дополнительных интеллектуальных усилий для понимания некоторого кода, довольно субъективно!
«var никогда не следует использовать, кроме случаев, когда тип неизвестен ...» - Вы ВСЕГДА можете знать тип, как и компилятор. Это не динамическая типизация, она просто позволяет компилятору определять тип за вас. Но тип никогда не бывает неизвестным.
Поразил, что до сих пор это не было замечено, но разумно использовать var для переменных цикла foreach.
Если вместо этого вы укажете конкретный тип, вы рискуете, что приведение во время выполнения будет автоматически вставлено в вашу программу компилятором!
foreach (Derived d in listOfBase)
{
Вышеупомянутое будет компилироваться. Но компилятор вставляет понижающее преобразование от Base к Derived. Таким образом, если что-либо в списке не является Derived во время выполнения, имеется недопустимое исключение приведения типов. Типовая безопасность поставлена под угрозу. Невидимые слепки ужасны.
Единственный способ исключить это - использовать var, поэтому компилятор определяет тип переменной цикла из статического типа списка.
Вар совсем не похож на вариант. Переменная по-прежнему строго типизирована, просто вы не нажимаете клавиши, чтобы получить ее таким образом. Вы можете навести на него курсор в Visual Studio, чтобы увидеть тип. Если вы читаете печатный код, возможно, вам придется немного подумать, чтобы понять, что это за тип. Но есть только одна строка, которая объявляет это, и много строк, которые его используют, поэтому присвоение вещам достойных имен по-прежнему является лучшим способом упростить отслеживание вашего кода.
Ленивое использование Intellisense? В нем меньше набора текста, чем в полном названии. Или есть вещи, которые требуют меньше работы, но не заслуживают критики? Я думаю, что есть, и var - один из них.
+1, единственное, кто должен заметить, что var не имеет ничего общего с Variant.
Удален из соображений избыточности.
vars по-прежнему инициализируется как правильный тип переменной - компилятор просто определяет его из контекста. Как вы упомянули, var позволяет нам хранить ссылки на экземпляры анонимных классов, но также упрощает изменение вашего кода. Например:
// If you change ItemLibrary to use int, you need to update this call
byte totalItemCount = ItemLibrary.GetItemCount();
// If GetItemCount changes, I don't have to update this statement.
var totalItemCount = ItemLibrary.GetItemCount();
Да, если трудно определить тип переменной по ее имени и использованию, во что бы то ни стало явным образом объявите ее тип.
Это неплохо, это скорее стилистическая вещь, которая имеет тенденцию быть субъективной. Это может добавить несоответствия, когда вы используете var, а когда нет.
Другой беспокоящий случай: в следующем вызове вы не можете определить, просто взглянув на код, тип, возвращаемый CallMe:
var variable = CallMe();
Это моя основная претензия к var.
Я использую var, когда объявляю анонимные делегаты в методах, почему-то var выглядит чище, чем если бы я использовал Func. Рассмотрим этот код:
var callback = new Func<IntPtr, bool>(delegate(IntPtr hWnd) {
...
});
РЕДАКТИРОВАТЬ: обновлен последний пример кода на основе ввода Джулиана
Но действительно ли вам нужно знать тип прямо в этой строке? Вы знаете, что CallMe что-то возвращает; разве недостаточно знать, что создается локальная переменная с именем variable? Если вы не расширите свой пример, это не очень веская жалоба, ИМО.
знание типа позволяет лучше понять любой код ниже инициализации, вы автоматически узнаете, что «этот код может вызывать то или иное», и, имея красивое имя для переменной, вы упрощаете смысл кода
Но вам не нужно знать тип, чтобы прочитать код. Если вы видите, например, variable.MyMethod(), вы знаете, что код вызывает метод MyMethod для любого типа variable. Вам не нужно знать, что делает MyMethod в этот момент, потому что вас беспокоит только то, что код вызывает это. Предположим, вы читаете код в первый раз (tm). Даже если вы знали тип variable при объявлении, скорее всего, вы не знаете, что это за тип или что он делает. В любом случае вы должны найти это, так зачем говорить об этом многословно?
Дело не в том, чтобы не быть многословным, а в том, чтобы не позволять компилятору делать синтаксический сахар за вас. Рассмотрим это: var getter ..., теперь это Func <объект> получатель ..., со вторым, когда вы знаете, что вам не нужно предоставлять какие-либо параметры и то, что он возвращает. Вы с самого начала знаете, что делать, и можете быстрее принимать решения при проектировании или рефакторинге. Иметь под рукой всю информацию важнее, чем несколько персонажей. Это можно понять, только когда вы работаете с большим количеством кода.
Поскольку в любом случае мы все говорим о визуальной студии, что такого особенного в том, чтобы навести указатель мыши на переменную на секунду и просто посмотреть, что это за тип? В любом случае, это намного лучше, чем бежать к декларации.
Согласитесь и не надо, это субъективно ... :)
Напротив, я все время работаю с большим количеством кода и всегда предпочитаю var. В вашем примере Func<object> вы можете сказать из контекста кода (на основании того факта, что он вызывается позже с использованием getter()), что это вызываемый элемент, либо Func, либо delegate. Дело в том, что вы можете сказать это из контекста, поэтому нет необходимости заранее объявлять это. Планирование рефакторинга - другое дело; да, вам нужна вся информация, когда вы планируете что-то подобное. Но вы можете получить его другими способами, в частности, с помощью intellisense, поэтому вы не можете записывать его прямо здесь необходимость.
Стандартные имена переменных и функций (variable, CallMe) - плохие примеры. Однако, если бы CallMe() был функцией какого-то «телефонного приложения», то var call = CallMe(); .... call.HangUp(); имел бы гораздо больший смысл.
@Randolpho: "Что особенного в том, чтобы навести указатель мыши на переменную на секунду и просто посмотреть, что это за тип?" Это добавляет время к накладным расходам на обслуживание ... плюс одна секунда - это только время наведения, а не подсчет клавиатуры для переключения контекста мыши. Не знаю, как вы, но работаю в срок. Каждый раз, когда мне приходится наводить курсор на переменную, чтобы узнать, что это за тип, это время, которое я мог бы лучше потратить на устранение проблемы.
@Р. Бемроуз: Если вы читаете код в первый раз (tm), у вас будет намного лучше работать с Right-Click->Go To Definition (F12, так как вы, очевидно, клавишный жокей, как я), чем наведение курсора мыши; вам все равно понадобится, если это пользовательский тип, потому что в конечном итоге вам нужно будет проанализировать тип. Но вам не нужно объявление типа для метода, который вы анализируете, поскольку в этот момент вас больше интересует как используется тип, чем то, чем он является на самом деле. И в 99,9% случаев, когда тип является основным типом фреймворка, вы можете выяснить, что это за тип к, как он используется.
Я с @Danko - если вы называете переменные variable, у вас больше проблем с удобочитаемостью, чем то, подходит ли ключевое слово var. Когда используется подходящее имя переменной, вам редко нужно знать фактический тип, чтобы понять, что делает код.
Ваш пример обратного вызова недействителен C#.
@Julian, спасибо, написал на скорую руку, обновил. Но вы могли видеть смысл, как это было
Ни то, ни другое не является абсолютной правдой; var может иметь как положительное, так и отрицательное влияние на читаемость. На мой взгляд, var следует использовать, когда выполняется одно из следующих условий:
var foo = new TypeWithAReallyLongNameTheresNoSenseRepeating())var не влияет на производительность, так как это синтаксический сахар; компилятор определяет тип и определяет его после компиляции в IL; в нем нет ничего динамического фактически.
согласны с обоими, хотя у меня есть длинные ограничения по второму случаю, если тип такой длинный, это обычно универсальный тип с множеством вложенных универсальных аргументов, в этом случае строго типизированный «ShortType, эквивалентный TypeWithAReallyLongNameTheresNoSenseRepeating» имеет больше смысла
У меня нет желания начинать религиозную войну, но я лично склонен не соглашаться с Ионом. Я бы предпочел очень длинное, но очень точное имя типа (например, дядя Боб Мартин), чем сокращенное и, возможно, двусмысленное более короткое имя типа. Я добавлю оговорку, что я НЕ согласен с искусственным завышением длины имени. Если 5 символов создают краткое имя, ясно показывающее намерение, используйте 5, а не 25.
@ Стив: Я должен с тобой согласиться; создание «короткого типа» (который, я полагаю, вы имеете в виду как наследование от определенного универсального типа исключительно с целью сокращения имени) не является хорошей практикой; это потребует от вас дублирования и прохождения любых конструкторов из универсального типа, а также предотвращения передачи типа разные, который наследуется от универсального типа в функцию. Вы используете наследование, как typedef, когда это не так.
@Steve: Думаю, вы имеете в виду что-то вроде: List<KeyValuePair<string, Dictionary<MyClassName, AnotherComplexType>>> list = new List<KeyValuePair<string, Dictionary<MyClassName, AnotherComplexType>>>();. В этом случае я бы использовал var и обернул ужасный беспорядок тегов в класс, который действительно имеет для меня смысл. var list = new ListOfComplexStuff(); Я согласен с ответом, что вам следует воздерживаться от использования var, если он не улучшает читаемость. Читаемость> Меньше нажатия клавиш.
Использовать var, когда тип очевиден? Может быть, но настоящий выигрыш - это когда тип не имеет значения.. Если вы делаете что-то вроде var customers = whatever; var query = from c in customers select stuff, не имеет значения, какой именно тип «клиентов». Понятно, как это можно использовать, и этого достаточно. И если фактический тип является громоздким, его стоит исключить.
@Kristoffer: Я понимаю желание избавиться от беспорядка тегов, но перенос их в класс не является (ИМО) приемлемой альтернативой, поскольку затем вы исключаете возможность того, что любой другой (законный) дочерний класс этого универсального типа будет допустимый параметр. Я бы предпочел использовать директиву using ShortType = LongGenericType<A,B,C> в верхней части файла, поскольку это дает такую же удобочитаемость, не требует повторного создания конструкторов и не исключает дочерние классы из кандидатов.
@Joren: Истинный выигрыш - это когда это более читабельно. Если тип действительно не имеет значения, то, вероятно, он более удобочитаемый. Если тип имеет значение, но очевиден из источника вывода, то он, вероятно, более читабелен.
@Steve Brouillard, Стив, на самом деле это моя причина, но я предпочитаю более короткое имя и тип, дополняющий имя переменной, например var iPhoneApplication = ... по сравнению с приложением IPhoneApplication = ....
@Joren - Совершенно верно. Я не должно волновать какого типа является переменная customer. Имя достаточно наглядное, чтобы понять, что с ним можно примерно сделать.
@ Адам Робинсон: Вы правы, читаемость - это конечная цель. А когда тип очевиден, var действительно может улучшить ситуацию. Моя точка зрения не должна сводиться к исключению вашей - я определенно согласен со всем вашим ответом - я просто использовал ваш как зацепку для добавления третьего пункта. «Настоящая выгода» была преувеличением.
Я думаю, что большинство из нас, комментирующих здесь, находятся на одной странице.
На мой взгляд, в использовании var нет проблем. Это не отдельный тип (вы все еще используете статическую типизацию). Вместо этого это просто экономия времени, позволяющая компилятору решить, что делать.
Как и любое другое средство экономии времени (например, автоматические свойства), является - хорошая идея, чтобы понять, что это такое и как работает, прежде чем использовать его повсюду.
Я думаю, вы, май, неправильно понимаете использование var в C#. Это является по-прежнему строгая типизация, в отличие от типа VB varient, поэтому его использование или отсутствие не влияет на производительность.
Поскольку это не влияет на окончательный скомпилированный код, это действительно выбор стилиста. Лично я не использую его, поскольку считаю, что код легче читать с определенными полными типами, но я могу представить, что через пару лет объявление полного типа будет рассматриваться так же, как сейчас венгерская нотация - лишний набор текста без реальной выгоды по сравнению с информацией, которую intellisense предоставляет нам по умолчанию.
На мой взгляд, Var в C# - это хорошая вещьtm. Любая типизированная таким образом переменная по-прежнему строго типизирована, но получает свой тип из правой части присваивания, в котором она определена. Поскольку информация о типе доступна с правой стороны, в большинстве случаев необязательно и слишком многословно вводить ее с левой стороны. Я думаю, что это значительно увеличивает читаемость без снижения безопасности типов.
С моей точки зрения, использование хороших соглашений об именах для переменных и методов более важно с точки зрения удобочитаемости, чем явная информация о типах. Если мне нужна информация о типе, я всегда могу навести курсор на переменную (в VS) и получить ее. Однако, как правило, читателю не требуется явная информация о типе. Для разработчика в VS вы по-прежнему получаете Intellisense, независимо от того, как объявлена переменная. Сказав все это, все же могут быть случаи, когда имеет смысл явно объявить тип - возможно, у вас есть метод, который возвращает List<T>, но вы хотите рассматривать его как IEnumerable<T> в своем методе. Чтобы гарантировать, что вы используете интерфейс, объявление переменной типа интерфейса может сделать это явным. Или, возможно, вы хотите объявить переменную без начального значения - потому что она сразу получает значение, основанное на каком-то условии. В этом случае вам нужен тип. Если информация о типе полезна или необходима, используйте ее. Однако я чувствую, что обычно в этом нет необходимости, и в большинстве случаев код легче читать без него.
Я согласен в целом. Я считаю, что ключевым моментом здесь является ясность намерений. Если большинству разработчиков в команде это непонятно, то это вредно, а не полезно. Тем не менее, я лично ОГРОМНЫЙ поклонник этого, но мне пришлось немного сдерживать себя, когда другие разработчики в моей команде не могли определить мои намерения. Иди разберись.
Эх, мне легче читать, когда шрифт слева. Используя ReSharper, мне все равно не нужно повторно набирать текст справа, поэтому меня это не беспокоит.
@BlueRaja - Я считаю, что использование хороших имен переменных обычно избавляет от необходимости беспокоиться о фактическом типе для понимания. Intellisense по-прежнему доступен для переменных, определенных "var", поэтому мне не нужно знать тип, чтобы выбрать для него метод / свойство при кодировании.
Дело не столько в том, когда вы пишете код, сколько в том, когда вам нужно прочитать код.
@BlueRaja - вот где важно использовать правильные имена переменных. Вам не нужно знать тип, если переменная названа соответствующим образом. Если по какой-то причине мне нужно знать тип, все, что мне нужно сделать, это навести указатель мыши на имя переменной, чтобы получить его.
Я не согласен с этим: «Поскольку в большинстве случаев информация о типе доступна с правой стороны», я бы поставил под сомнение, действительно ли это правда. Просматривая коды моих команд, мы не пытаемся гарантировать, что тип возвращаемого значения дословно указан в именах методов. Использование явного типа более читабельно и более устойчиво к ошибкам времени выполнения.
@Anthony - 1) Я никогда не говорил, что вы не можете использовать его в тех случаях, когда информация о типе важна и недоступна. 2) Хорошее именование, как с именами переменных, так и с именами методов, в любом случае (с точки зрения чтения / понимания) более важно, чем информация о типе. Если вам регулярно нужен тип в дополнение к именам переменных / методов, чтобы разобраться в коде, у вас, вероятно, есть более серьезные проблемы, чем использование или неиспользование var.
Тогда я, должно быть, просто придерживаюсь толстой стороны, мне нужно иметь хорошие имена методов и переменных и, чтобы понимать, с какими типами работают, чтобы правильно понимать код, который я читаю. Думаю, вы правы, хотя это симптом более серьезных проблем. Одно доверие. Чтобы быть уверенным, что код делает то, что кажется, вам нужно иметь Конечно используемых типов.
var неплохой. Запомни это. var неплохой. Повтори это. var неплохой. Запомни это. var неплохой. Повтори это.
Если компилятор достаточно умен, чтобы определить тип из контекста, то и вы тоже. Вам не обязательно записывать это прямо при декларировании. А intellisense делает это еще менее необходимым.
var неплохой. Запомни это. var неплохой. Повтори это. var неплохой. Запомни это. var неплохой. Повтори это.
Итак, вы говорите, что var - это неплохо? ;-)
@WaggingSiberian: Я говорю, что var неплох. Запомни это. var неплохой. Повтори это.
@Randolpho: Думаю, я понял. Вар неплохой! Я научусь любить вар! Я могу это сделать.
@WaggingSiberian: Да, можно! :)
«Он одержал победу над собой. Он любил var». (простите за неверное цитирование.)
Ой, меня только что ограбили. Три голоса против за столько же минут. Я думаю, некоторые люди действительно встают из-за вар. Должно быть, бывшие разработчики Java ....
Если кто-то использует ключевое слово var, потому что не хочет «выяснять тип», это определенно неправильная причина. Ключевое слово var не создает переменную с динамическим типом, компилятор все равно должен знать этот тип. Поскольку переменная всегда имеет определенный тип, тип также должен быть очевиден в коде, если это возможно.
Например, веские причины использовать ключевое слово var:
Запись типа данных часто упрощает выполнение кода. Он показывает, какие типы данных вы используете, поэтому вам не нужно выяснять тип данных, сначала выясняя, что делает код.
Первый.
var - это не тип и не какая-то особенность (например, C# 4.0 dynamic). Это просто синтаксический сахар. Вы просите компилятор определить тип по выражению в правой части. Единственное необходимое место - анонимные типы.
Не думаю, что использование var - это ни добро, ни зло, это стиль программирования. Лично я им не пользуюсь, но не против использования другими членами команды.
@Randolpho - Какого черта? Я вообще не читаю Slashdot, поэтому ваша аналогия мне непонятна. но я точно знаю, что SO - это не Литературный клуб, и голосование против, потому что вам не нравится мой стиль письма, не очень умно.
@Randolpho - первое имя абзаца. Я хотел написать вторую, но забыл об этом.
Это был язвительный голос против, сделанный для пинки. Я случайным образом проголосую за один из ваших постов, просто чтобы компенсировать потерю репутации. Иметь дело?
Думаю, вы указали на основную проблему с var в своем вопросе: «Мне не нужно определять тип». Как отмечали другие, есть место для var, но если вы не знаете тип, с которым имеете дело, есть довольно хороший шанс, что у вас возникнут проблемы в будущем - не во всех случаях, но запаха там достаточно, так что вы должны быть подозрительными.
Что ж, этот в значительной степени будет самоуверенным на всем протяжении, но я постараюсь высказать свое мнение по этому поводу - хотя я думаю, что мое мнение настолько смешано, что вы, вероятно, в любом случае не получите от него многого.
Прежде всего - есть анонимные типы, для которых вам нужно использовать ключевое слово «var», чтобы назначить объект с анонимным типом в качестве его класса - здесь не много обсуждения, «var» требуется.
Однако для более простых типов, целых, длинных, строковых и т. д. Я обычно использую правильные типы. В основном потому, что это своего рода «инструмент для ленивого человека», и я не вижу здесь большого выигрыша, очень мало нажатий клавиш и возможная путаница, которую он может вызвать позже, просто не стоит того. В частности, меня смущают различные типы чисел с плавающей запятой (float, double, decimal), поскольку я не уверен в постфиксе в литералах - мне нравится видеть этот тип в исходном коде.
С учетом сказанного, я предпочитаю использовать var alot, если тип более сложный и / или он явно повторяется в правой части присваивания. Это может быть List<string> или т. д., Например:
var list = new List<string>();
В таком случае я не вижу смысла повторять тип дважды - особенно когда вы начинаете изменять свой код и меняются типы - общие типы могут становиться все более и более сложными, и поэтому необходимость их дважды менять - просто боль. Однако, конечно, если вы хотите кодировать против IList<string>, вам нужно явно указать тип.
Вкратце я делаю следующее:
Конечно, int - это просто, но когда переменная имеет тип IEnumerable<MyStupidLongNamedGenericClass<int, string>>, var упрощает задачу.
+1 за это. int против var - повод для споров, но несколько вложенных универсальных типов делают var находкой. Именно здесь многократное использование имени типа действительно ухудшает читаемость кода.
Это совершенно неправильная причина для его использования. Если в вашем коде используется вложенный универсальный тип, вы должны создать для него определенный именованный класс. Например: class IntStringEnumerator : IEnumerable<MyStupidLongNamedGenericClass<int, string>>, а затем используйте новое имя. Это очищает код и лучше описывает тип.
Хорошо, но мой пример был просто преувеличением. IntStringEnumerator i = new IntStringEnumerator() по-прежнему слишком много печатает.
Я использую var только тогда, когда ясно, какой тип используется.
Например, в этом случае я бы использовал var, потому что сразу видно, что x будет иметь тип MyClass:
var x = new MyClass();
Я бы НЕ использовал var в таких случаях, потому что вам нужно перетащить указатель мыши на код и посмотреть во всплывающей подсказке, какой тип возвращает MyFunction:
var x = MyClass.MyFunction();
В частности, я никогда использую var в тех случаях, когда правая часть даже не метод, а только значение:
var x = 5;
(потому что компилятор не может знать, хочу ли я байт, короткий, int или что-то еще)
Если правая сторона недостаточно ясна, чтобы оправдать использование var, тогда проблема не в var: проблема в правой стороне. Это не описательный довольно. Customer c = GetContext() неясен Все еще и не лучше, чем использование var.
Помимо проблем с удобочитаемостью, есть одна реальная проблема с использованием var. При использовании для определения переменных, которые назначаются позже в коде, это может привести к нарушению кода, если тип выражения, используемого для инициализации переменной, изменится на более узкий тип. Обычно было бы безопасно провести рефакторинг метода, чтобы он возвращал более узкий тип, чем раньше: например, чтобы заменить возвращаемый тип «Object» некоторым классом «Foo». Но если существует переменная, тип которой определяется на основе метода, то изменение возвращаемого типа будет означать, что этой переменной больше можно назначить не-Foo объект:
var x = getFoo(); // Originally declared to return Object
x = getNonFoo();
Итак, в этом примере изменение типа возвращаемого значения getFoo сделало бы присвоение из getNonFoo незаконным.
Это не такая уж большая проблема, если getFoo и все его использования находятся в одном проекте, но если getFoo находится в библиотеке для использования внешними проектами, вы больше не можете быть уверены, что сужение возвращаемого типа не нарушит код некоторых пользователей, если они используют var вот так.
Именно по этой причине, когда мы добавили аналогичную функцию вывода типов в язык программирования Curl (называемую def в Curl), мы предотвратили присвоение переменных, определенных с использованием этого синтаксиса.
Ответ Эрика здесь ...
Псевдонимы с областью имен для универсальных типов в C#
относится.
Отчасти проблема заключается в том, что в C# нет строго типизированного псевдонима. Многие разработчики используют вар как частичный суррогат.
Не используйте это, это сделает ваш код нечитаемым.
ВСЕГДА используйте как можно более строгий набор текста, костыли только превращают вашу жизнь в ад.
varявляется строгая типизация. Это ни в коем случае не костыль. И это не делает код нечитаемым.
в некоторых случаях он действительно улучшает читаемость: using (var con = new SqlConnection()) проще для глаз, чем необходимость набирать текст дважды
В этом нет ничего плохого, но это может быть неуместно. Примеры см. Во всех других ответах.
var x = 5; (Плохо)
var x = новый SuperDooperClass (); (хороший)
var x = from t in db.Something select new {Property1 = t.Field12}; (лучше)
«Единственное, что вы действительно можете сказать о моем вкусе, это то, что он старомодный, и со временем ваш будет тоже». -Толкин.
var - это заполнитель, представленный для anonymous types в C# 3.0 и LINQ.
Таким образом, он позволяет писать запросы LINQ для меньшего количества столбцов в пределах, скажем, коллекции. Нет необходимости дублировать информацию в памяти, загружайте только то, что необходимо для выполнения того, что вам нужно сделать.
Использование var совсем неплохо, поскольку на самом деле это не тип, а, как упоминалось в другом месте, заполнитель для типа, который должен быть определен в правой части уравнения. Затем компилятор заменит ключевое слово самим типом.
Это особенно полезно, когда даже с IntelliSense имя типа длинное для ввода. Просто напишите var и создайте его экземпляр. Другие программисты, которые после прочтут ваш код, легко поймут, что вы делаете.
Это похоже на использование
public object SomeObject { get; set; }
вместо:
public object SomeObject {
get {
return _someObject;
}
set {
_someObject = value;
}
}
private object _someObject;
Все знают, что делает свойство, так же как все знают, что делает ключевое слово var, и оба примера, как правило, упрощают читаемость, делая его легче, и делают более приятным для программиста написание эффективного кода.
var хорош тем, что следует классическому правилу СУХОЙ, и особенно элегантен, когда вы указываете тип в той же строке, что и объявление переменной. (например, var city = new City())
Если вы знаете тип, используйте его. Если вы не знаете тип, почему бы и нет? Если вы не можете узнать тип, ничего страшного - вы нашли единственно верное применение.
И мне очень жаль, но если лучшее, что вы можете сделать, это «выровнять весь код», это не лучший ответ. Найдите другой способ форматирования вашего кода.
Один хороший аргумент, почему переменные не следует использовать просто как «ярлык для набора», а вместо этого следует использовать в сценариях, для которых они изначально были разработаны: Resharper (по крайней мере, v4.5) не может найти использования типа, если он представлен как var. Это может стать настоящей проблемой при рефакторинге или анализе исходного кода.
Если вы ленивы и используете var для чего-либо, кроме анонимных типов, вам необходимо использовать венгерскую нотацию при именовании таких переменных.
var iCounter = 0;
жизни!
Мальчик, я скучаю по VB.
-1: Выкопать старый вопрос, просто чтобы противостоять вмешательству типов, без причины - даже не по субъективной или, возможно, глупой причине, просто без причины. Тот факт, что вы называете эту мерзость венгерской нотацией (меня не волнует, что некоторые ее так называют, в моей книге венгерская нотация по-прежнему означает включение цели переменной в имя, а не ее точный тип) только делает ее более подходящей.
Извините, что вы так думаете. По моему опыту, венгерская нотация всегда означала, что тип переменной является префиксом; часть имени после префикса типа описывает назначение переменной. Вы думаете, что венгерская нотация означает, что вы добавляете префикс и суффикс имени с его целью? Теперь есть некоторая избыточность, о которой говорилось в этом потоке! В венгерской системе обозначений всегда использовались префиксы, чтобы дать читателю кода представление о типе переменной. И это то, что нужно делать тем, кто использует var! Использование var для неанонных типов действительно является «помехой».
Типа вывод, что, конечно, глупая опечатка. Но вы по-прежнему не называете ничего похожего на причину, по которой интерференция типов - это плохо ™. Относительно венгерского языка: спросите в Википедии. У него где-то есть хороший пример, префикс i: вы бы использовали его как «целое число», в то время как «венгерская нотация приложений», как его называют вики, использует его как «индекс» - последний содержит гораздо больше семантической информации и на самом деле сообщает вам то, что система типов не может сказать вам, в то время как первая избыточна с наполовину приличной IDE.
Хорошая точка зрения. Я должен был использовать var intCounter = 0; в моем примере (извините, я давно не использовал VB). Но тип венгерского языка, о котором я имел в виду, должен был быть очевиден из контекста VB. Возможно, я использовал сарказм, чтобы объяснить мою точку зрения о том, почему использование var для чего-либо другого, кроме анонимных типов, не транслируется хорошо (хотя «ленивый», безусловно, явная причина). И если вы не понимаете, почему я считаю чистой ленью использовать var для чего-либо, кроме анонимных типов, ну, просто прочтите некоторые другие ответы в этой ветке. И помните, не все используют (или имеют) IDE.
что большинство игнорирует:
var something = new StringBuilder();
обычно не набирается так быстро, как
StringBuilder something = KEY'TAB'();
Да, но вы дублируете StringBuilder. Дважды вы получите больше кода. Мне нравится var, потому что он делает код короче, меньше информации, легче читать.
... и больше похоже на Javascript. var был предназначен для LINQ, злоупотребление им должно караться удалением intellisense из вашей Visual Studio на неделю.
С LINQ еще одна очень веская причина для использования var заключается в том, что компилятор может гораздо больше оптимизировать запрос.
Если вы используете статический список для хранения результата, он будет выполняться там, где вы назначаете его списку, но с var он потенциально может объединить исходный запрос с более поздними запросами в коде, чтобы сделать более оптимизированные запросы к базе данных.
У меня был пример, когда я вытащил некоторые данные в первом запросе, а затем зациклился и запросил дополнительные данные для печати таблицы.
LINQ объединяет их, так что первый извлекает только идентификатор.
Затем в цикле было добавлено дополнительное соединение, которое я не делал, чтобы получить данные, которые я включил в оригинал.
При тестировании это оказалось намного более эффективным.
Если бы мы не использовали var, он делал бы запросы точно так же, как мы их написали.
Я новичок в мире C# после десяти лет работы профессионалом в области Java. Моя первоначальная мысль была примерно такой: «О, нет! Безопасность типов уходит в канализацию». Однако чем больше я читаю о var, тем больше он мне нравится.
1) Var является таким же типобезопасным, как и явно объявленный тип. Все дело в синтаксическом сахаре времени компиляции.
2) Следует принципу СУХОЙ (не повторяйтесь). DRY направлен на избежание дублирования, и обозначение типа с обеих сторон, безусловно, излишне. Чтобы избежать избыточности, нужно упростить изменение кода.
3) Что касается знания точного типа ... ну ... я бы сказал, что у вас всегда есть общее представление о том, что у вас есть целое число, сокет, какой-то элемент управления пользовательского интерфейса или что-то еще. Intellisense поможет вам отсюда. Знание точного типа часто не имеет значения. Например. Я бы сказал, что в 99% случаев вам все равно, является ли данная переменная long или int, float или double. В последнем 1% случаев, когда это действительно важно, просто наведите указатель мыши на ключевое слово var.
4) Я видел нелепый аргумент, что теперь нам нужно вернуться к венгерским бородавкам в стиле 1980 года, чтобы различать типы переменных. В конце концов, это был единственный способ определить типы переменных во времена, когда Тимоти Далтон играл Джеймса Бонда. Но это 2010 год. Мы научились называть наши переменные в зависимости от их использования и содержимого, и позволили IDE указывать нам их тип. Просто продолжайте делать это, и var вам не повредит.
Подводя итог, можно сказать, что var - это не большая вещь, но это действительно хорошая вещь, которую Java лучше скопирует в ближайшее время. Все аргументы против, похоже, основаны на заблуждениях до IDE. Я бы без колебаний использовал его, и я рад, что R # помогает мне в этом.
var - это способ работать с анонимными типами, будь то из операторов LINQ или нет. Любое другое использование во многом зависит от того, кто будет читать ваш код и какие правила существуют.
Если вы - единственная аудитория или ваша аудитория привыкла к использованию var или хорошо знакома с вашим кодом, я думаю, это не имеет значения. Если вы используете его как: var s = новый SqlConnection (), то это в значительной степени не имеет значения и, вероятно, улучшает читаемость кода. Если люди не слишком разборчивы и для них можно немного поработать, чтобы узнать тип, когда он не очевиден (что в большинстве случаев не требуется, то, как вы его используете в следующих утверждениях, обычно все объясняет), тогда все в порядке. .
Но если у вас есть придирчивые, недалекие товарищи по команде, которые любят ныть, или если руководящие принципы вашей компании специально запрещают использование var, когда тип неочевиден, вы, скорее всего, встретите серьезное сопротивление.
Если использование var делает ваш код безумно трудным для чтения, вы, вероятно, получите удар, используя var, даже если виноват, вероятно, дизайн вашего приложения.
Если var вводит двусмысленность (вроде вашего примера IEnumerable / IEnumerable), просто не используйте его и говорите явно. Но у var есть свои удобства, а в некоторых случаях, IMHO, даже улучшается читабельность за счет уменьшения беспорядка.
var похож на точечные пробелы в детских книгах, которыми дети должны его заполнить. За исключением этого случая, компилятор заполнит его правильным типом, который обычно пишется после знака =.
Ого, правда? и нет, вы понимаете, о чем я говорю.
Хорошо, вы проф. а я всего лишь студент. так что я не буду спорить. Но если хотите, можете попросить MS удалить ключевое слово var, если оно вас сильно беспокоит. Как всегда говоришь дорогой Андрей: «вар должен умереть».
Я говорю совсем не об этом.
Какая-то неприятная реакция на тебя, не так ли?
Не совсем Эндрю. Моему представителю было 172 года или около того ... К вашему сведению, ваш отрицательный голос был довольно несправедливым ...
давайте продолжить обсуждение в чате
для протокола, я проверял ваши ответы и, честно говоря, вы много знаете. Но вы высокомерный .. итак формула: (знание + высокомерие) = 0;)
Спасибо, что поболтали со мной и все обсудили!
Локальным переменным может быть задан предполагаемый "тип" var вместо явного типа. Ключевое слово var указывает компилятору вывести тип переменной из выражения в правой части оператора инициализации.
// z компилируется как int
var z = 100;
// s компилируется как строка ниже
var s = "Hello";
// a компилируется как int []
var a = new[] { 0, 1, 2 };
// expr компилируется как IEnumerable // или, возможно, IQueryable
var expr =
from c in customers
where c.City == "London"
select c;
// аноним компилируется как анонимный тип
var anon = new { Name = "Terry", Age = 34 };
// список составляется как List
var list = new List<int>();
var can only be used when a local variable is declared and initialized in the same statement; the variable cannot be initialized to null, or to a method group or an anonymous function.
var нельзя использовать в полях в области класса.
Переменные, объявленные с помощью var, нельзя использовать в выражении инициализации. Другими словами, это выражение допустимо: int i = (i = 20); но это выражение вызывает ошибку времени компиляции: var i = (i = 20);
Несколько неявно типизированных переменных не могут быть инициализированы в одном операторе.
Если тип с именем var находится в области видимости, то ключевое слово var будет преобразовано в это имя типа и не будет рассматриваться как часть объявления неявно типизированной локальной переменной.
В LINQ необходимо использовать var, потому что вы не всегда можете знать, что вы получите в результате запроса.