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

<p>это вопрос, который я всегда задаю при программировании: что использовать, когда мы пишем код:</p><pre><code>var myfiles = directory.getfiles(fullpath); </code></pre><p>или же</p><pre><code>string[] myfiles = directory.getfiles(fullpath); </code></pre><p><strong><em> var </em></strong> является новым и является <em> неявно типизированными локальными переменными </em>, поэтому мы можем использовать только локально, и у него есть правила, такие как не может быть нулевым и т. д., но мне интересно, получим ли мы какое-либо преимущество, используя его "нормально".</p><p>в "нормальной" части говорится не в <strong>анонимные типы</strong>, <strong>инициализаторы объектов и коллекций</strong> и <strong>выражения запросов</strong> где это было намерением использовать var anonymous объект, так что я имею в виду ... так же, как в примере выше.</p><p>о чем ты думаешь?</p>

<p>помимо очевидного использования <code>var</code> с linq, я также использую его для сокращения объединенных объявлений переменных для удобства чтения, например:</p><pre><code>var d = new dictionary<string, dictionary<string, queue<someclass>>>(); </code></pre><p>в целом, я получаю некое утешение (из-за отсутствия лучшего слова) от статической типизации, что заставляет меня неохотно отказываться от нее. мне нравится ощущение, что я знаю, что делаю, когда объявляю переменную. объявление переменной не просто говорит компилятору, это говорит человеку, читающему ваш код.</p><p>позвольте привести пример. предположим, у меня есть метод, который возвращает <code>list<string></code>. этот код, безусловно, правильный, и я думаю, что 90% разработчиков c #, вероятно, написали бы его:</p><pre><code>list<string> list = mymethod(); </code></pre><p>очевидно, верно? на самом деле, вот место, где вы могли бы так же легко использовать <code>var</code>.</p><p>правда достаточно. но <em> эта </em> версия кода не просто объявляет переменную, она говорит мне, что намерен сделать человек, который ее написал:</p><pre><code>ienumerable<string> list = mymethod(); </code></pre><p>разработчик, который написал этот код, говорит мне: "я не собираюсь изменять этот список, и при этом я не собираюсь использовать индекс для доступа к его членам. все, что я собираюсь сделать, - это перебирать его". это много информации, которую нужно передать в одной строке кода. это то, от чего вы отказываетесь, если используете <code>var</code>.</p><p>конечно, вы не откажетесь от этого, если не использовали его в первую очередь. если вы разработчик, который написал бы эту строку кода, вы уже знаете, что не будете использовать <code>var</code> там.</p><p><strong>edit:</strong></p><p>я просто перечитал пост джона скита, и эта цитата эрика липперта выскочила на меня:</p><blockquote> <p>неявно типизированные местные жители - это всего лишь один маленький способ, которым вы можете уменьшить внимание как и тем самым подчеркнуть, что.</p> </blockquote><p>я думаю, что на самом деле во многих случаях использование неявной типизации оставляет то, что подразумевается. это нормально, чтобы не останавливаться на чем. например, я случайно напишу запрос linq, например:</p><pre><code>var rows = from datarow r in parentrow.getchildrows(myrelation) where r.field<bool>("flag") orderby r.field<int>("sortkey") select r; </code></pre><p>когда я читаю этот код, одна из вещей, которые я думаю, когда я читаю, это "<code>rows</code> - <code>ienumerable<datarow></code>". потому что я знаю, что запросы linq возвращают <code>ienumerable<t></code>, и я могу видеть тип объекта, который выбирается прямо здесь.</p><p>это тот случай, когда что <em> не было </em> сделано явным. это было оставлено для меня, чтобы сделать вывод.</p><p>теперь, примерно в 90% случаев, когда я использую linq, это не имеет значения. потому что 90% времени следующая строка кода:</p><pre><code>foreach (datarow r in rows) </code></pre><p>но нетрудно представить код, в котором было бы очень полезно объявить <code>rows</code> как <code>ienumerable<datarow></code> - код, в котором запрашивалось множество различных типов объектов, было невозможно разместить объявление запроса рядом с итерацией, и это было бы полезно иметь возможность проверять <code>rows</code> с intellisense. и это то, что, а не как.</p>

<p>вы получите огромное разнообразие мнений по этому вопросу - от "везде используйте var!" до "используйте var только с анонимными типами, где вам в основном это нужно". мне нравится <a href="http://csharpindepth.com/viewnote.aspx?noteid=61">эрик липперт возьмется за это</a> :</p><blockquote> <p>весь код - это абстракция. то, что код "действительно" делает, манипулирует данными? номера? биты? напряжения? электроны? да, но понимание кода на уровне электронов - плохая идея! искусство кодирования определяет, какой уровень абстракции подходит для аудитории.</p> <p>в языке высокого уровня всегда существует такое напряжение между тем, что код делает (семантически), и как код выполняет это. программисты по техническому обслуживанию должны понимать, что и как, если они собираются успешно вносить изменения.</p> <p>весь смысл linq заключается в том, что он в значительной степени уменьшает акцент на "как" и массивно подчеркивает "что". используя понимание запросов, программист говорит будущей аудитории: "я считаю, что вы не должны ни знать, ни интересоваться, как именно вычисляется этот набор результатов, но вы должны очень заботиться о том, какова семантика полученного набора". они делают код ближе к внедряемому бизнес-процессу и дальше от битов и электронов, которые его запускают.</p> <p>неявно типизированные местные жители - это всего лишь один маленький способ, которым вы можете уменьшить внимание как и тем самым подчеркнуть, что. правильно ли это делать в конкретном случае - это решение по делу. поэтому я говорю людям, что если знание типа является релевантным и его выбор имеет решающее значение для продолжения работы метода, не используйте неявную типизацию. явная типизация говорит: "я говорю вам, как это работает по какой-то причине, обратите внимание". неявная типизация гласит: "неважно, является ли эта вещь списком или клиентом [], важно то, что это набор клиентов".</p> </blockquote><p>лично я не склонен <em> </em> использовать его, если тип не является достаточно очевидным - где я включаю запросы linq как "достаточно очевидные". я бы не стал делать это, например, для <code>directory.getfiles</code>, поскольку не совсем очевидно, что он возвращает <code>string[]</code> вместо (скажем) <code>fileinfo[]</code> (или чего-то еще полностью) - и это имеет большое значение для того, что вы будете делать позже.</p><p>если в правой части оператора присваивания есть вызов конструктора, я с большей вероятностью пойду с <code>var</code>: совершенно очевидно, каким будет тип. это особенно удобно для сложных родовых типов, например, <code>dictionary<string,list<int>></code>.</p>

<p>лично я использую var только в двух местах:</p><ol> <li>с анонимными типами, т.е. linq-related (где в некоторых случаях требуется var)</li> <li>когда оператор объявляет и создает определенный тип в том же типе</li> </ol><p>то есть. это пример пункта 2:</p><pre><code>var names = new list<string>(); </code></pre><p><strong>отредактировано</strong>: это ответ на вопрос джона скита.</p><p>приведенный выше ответ был фактически упрощен. обычно я использую <em> var </em>, где тип:</p><ol> <li>не нужно знать (не так много мест, хотя)</li> <li>невозможно знать (linq, анонимные типы)</li> <li>в противном случае известно или ясно из кода</li> </ol><p>в случае фабричного метода, где все, что вам нужно знать в месте написания кода, это то, что возвращаемый вами объект является потомком некоторого типа и <em> некоторого типа </em> имеет статический метод фабрики, тогда я бы использовал <em> var </em>. как это:</p><pre><code>var connection = databaseconnection.createfromconnectionstring("..."); </code></pre><p>приведенный выше пример является реальным примером из моего кода. очевидно, по крайней мере для меня и людей, которые используют этот код, что <em> соединение </em> является потомком databaseconnection, но точный тип не нужен ни для того, ни для другого. понимание кода, ни его использование.</p>

<p>я попробовал стиль "везде использую var" ... и вот почему я не продолжал его использовать.</p><ol> <li>ухудшенная читаемость в разы</li> <li>пределы intellisense после =</li> <li>ввод "var" на самом деле не намного короче, чем "int", "string" и т.д., особенно с intellisense.</li> </ol><p>с учетом сказанного, я все еще использую его с linq.</p>

<p>я склонен использовать <code>var</code> везде, но мои коллеги сказали: "стоп, он нам менее читаем". поэтому я теперь использую <code>var</code> только для анонимных типов, запросов linq и где находится конструктор с правой стороны.</p>

<p>в этом <a href="http://community.bartdesmet.net/blogs/bart/archive/2008/08/23/appropriate-use-of-local-variable-type-inference.aspx">post</a> есть несколько хороших рекомендаций о том, когда использовать интерфейс типа var или типы объектов.</p>

<p>исходя из страны функционального программирования, где управление типами определяет день, я использую <code>var</code> для всех местных жителей, где это возможно.</p><p>в visual studio, если вы когда-нибудь задумывались о том, какой тип есть у любого локального пользователя, все, что вам нужно сделать, это навести на него курсор мыши.</p>

<p>я думаю, что интересно отметить, как это обычно обрабатывается в haskell. благодаря <a href="http://en.wikipedia.org/wiki/curry-howard\_correspondence">изоморфизму карри-ховарда</a> можно вывести (наиболее общий) тип любого выражения в haskell, и, таким образом, объявления типов практически нигде не требуются, за некоторыми исключениями; например, иногда вы намеренно хотите ограничить тип чем-то более конкретным, чем было бы выведено.</p><p>конечно, то, что требуется и что рекомендуется, - это не одно и то же; на практике, согласно соглашению, определения верхнего уровня всегда имеют объявления типов, в то время как в локализованных определениях объявления типов не учитываются. похоже, что это обеспечивает хороший баланс между четкостью для восприятия определения в целом, в отличие от краткости для удобства чтения локальных "вспомогательных" или "временных" определений. если я правильно понимаю, вы не можете использовать <code>var</code> для определения "верхнего уровня" (например, метод или глобальную функцию), поэтому я предполагаю, что это переводится как "использовать <code>var</code> везде, где вы можете" в мире c #. конечно, ввод "<code>int</code>" - это то же количество нажатий клавиш, что и "<code>var</code>", но большинство примеров будет длиннее.</p>