Вопрос

На днях я беседовал со своими коллегами и услышал, что их стандарт кодирования прямо запрещает им использовать var Ключевое слово в C#.Они понятия не имели, почему это так, а я всегда считал неявное объявление невероятно полезным при кодировании.У меня никогда не возникало проблем с определением типа переменной (просто наведите курсор на переменную в VS и таким образом получите тип).

Кто-нибудь знает, почему было бы плохой идеей использовать ключевое слово var в C#?

Это было полезно?

Решение

Авторы Рекомендации по проектированию .Net Framework (потрясающая книга), вышедшая в ноябре 2008 г., рекомендую рассмотреть возможность использования var когда Тип очевиден и однозначен.

С другой стороны, если использовать var приведет к неоднозначности при чтении кода, как заметил Антон Гоголев, то лучше его не использовать.

в книге (Приложение А) фактически приводят такой пример:

var names = new List<string>(); // good usage of var

string source = GetSource();
var tokens = source.Split(' '); // ok; most developers know String.Split

var id = GetId(); // Probably not good; it's not clear what the type of id is

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

В большинстве случаев использование var для простых типов на самом деле улучшается читаемость, и мы не должны забывать, что использование не снижает производительность. var.

Другие советы

var q = GetQValue();

это действительно плохо.Однако,

var persistenceManager = ServiceLocator.Resolve<IPersistenceManager>();

меня вполне устраивает.

Суть такова:используйте описательные имена идентификаторов, и все будет в порядке.

В качестве примечания:Интересно, как они справляются с анонимными типами, когда их не разрешено использовать? var ключевое слово.Или они ими вообще не пользуются?

В большинстве случаев при разумном использовании (т.простой инициализатор типа, где тип и значение совпадают), тогда все в порядке.

Бывают случаи, когда неясно, что вы что-то сломали, изменив его - в основном, когда инициализированный тип и (исходный) тип переменной не совпадают, потому что:

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

В этих случаях у вас могут возникнуть проблемы с любым разрешением типа — например:

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

В таких случаях вы меняете смысл кода и выполняете что-то другое.Тогда это плохо.

Примеры:

Неявное преобразование:

static void Main() {
    long x = 17;
    Foo(x);
    var y = 17;
    Foo(y); // boom
}
static void Foo(long value)
{ Console.WriteLine(value); }
static void Foo(int value) {
throw new NotImplementedException(); }

Скрытие метода:

static void Main() {
    Foo x = new Bar();
    x.Go();
    var y = new Bar();
    y.Go(); // boom
}
class Foo {
    public void Go() { Console.WriteLine("Hi"); }
}
class Bar : Foo {
    public new void Go() { throw new NotImplementedException(); }
}

и т. д.

Наверняка это ошибка.Это потому, что некоторые люди не понимают, что на самом деле это строго типизированная переменная, а не переменная в VB.

Не все корпоративные стандарты кодирования имеют смысл. Однажды я работал в компании, которая хотела добавлять к именам всех классов префикс названия компании.Когда компания сменила название, произошла масштабная переработка.

Во-первых, как правило, стандарты кодирования должны обсуждаться и согласовываться командой, а их обоснование должно быть записано, чтобы каждый мог знать, почему они существуют.Они не должны быть Святой Истиной от Одного Мастера.

Во-вторых, это правило, вероятно, оправдано, поскольку код читается больше раз, чем пишется. var ускоряет письмо, но может немного замедлить чтение.Очевидно, это не такое правило поведения кода, как «Всегда инициализировать переменные», потому что две альтернативы (написание var и написание типа) ведут себя точно так же.Так что это не критическое правило.я бы не запретил var, я бы просто использовал «Предпочитаю...»

Несколько месяцев назад я написал статью в блоге на эту тему.Что касается меня, я использую его везде, где это возможно, и специально разрабатываю свои API на основе вывода типов.Основные причины, по которым я использую вывод типа:

  1. Это не снижает типобезопасность
  2. Это фактически повысит безопасность типов в вашем коде, предупредив вас о неявном приведении типов.Лучший пример в операторе foreach
  3. Поддерживает принципы DRY в C#.Это специально для случая объявления, зачем повторять имя дважды?
  4. В некоторых случаях это просто необходимо.Примеры анонимных типов
  5. Меньше набора текста без потери функциональности.

http://blogs.msdn.com/jaredpar/archive/2008/09/09/when-to-use-type-inference.aspx

var это последняя дискуссия о том, «как расставить брекеты»/венгерская нотация/дебаты о верблюжьей оболочке.Правильного ответа нет, но есть люди, которые сидят на крайностях.

Вашему другу просто не повезло, что он работает под началом одного из экстремистов.

Полный запрет означает запрет на использование анонимных типов (которые становятся невероятно полезными по мере того, как вы чаще используете LINQ).

Это очевидная и простая глупость, если только кто-то не сможет формализовать вескую причину никогда не использовать анонимные типы.

Это может повредить читабельности, если использовать его неправильно.Однако полностью запрещать это немного странно, поскольку без него вашим коллегам будет сложно использовать анонимные типы.

Это действительно проблема читаемости вашего кода.

Лично я предпочитаю использовать «var» только для анонимных типов (действительно, если вы вообще хотите использовать анонимные типы, вам нужно будет использовать var), и они в основном поступают из запросов LINQ.В этих случаях у вас нет другого выбора, кроме как использовать var, если ваш запрос проецируется в новый (неявный и анонимный) тип.

Однако C# 3.0 с радостью позволит вам использовать var где угодно, за пределами LINQ и анонимных типов, например:

var myint = 0;
var mystring = "";

совершенно допустим, и myint и mystring будут строго типизированы на основе выведенных значений, используемых для их инициализации.(таким образом, myint — это System.Int32, а mystring — это System.String).Конечно, при взгляде на значения, используемые для инициализации переменных, довольно очевидно, к каким типам они будут неявно типизированы, однако я думаю, что для читаемости кода было бы даже лучше, если бы приведенное выше было записано как:

int myint = 0;
string mystring = "";

так как вы можете сразу увидеть, к какому типу относятся эти переменные.

Рассмотрим этот несколько запутанный сценарий:

var aaa = 0;
double bbb = 0;

Совершенно правильный код (хотя и немного нетрадиционный), но в приведенном выше примере я знаю, что bbb — это двойное число, несмотря на то, что инициализирующее значение выглядит как целое число, но aaa определенно будет не двойным, а скорее целым.

Вы можете считать мнение Microsoft актуальным, поскольку C# — это их язык:

«Однако использование вар имеет, по крайней мере, потенциал сделать ваш код более трудным для понимания другими разработчиками.По этой причине в документации C# обычно используется вар только тогда, когда это необходимо».

Видеть MSDN — неявно типизированные локальные переменные (Руководство по программированию на C#), последний абзац.


Вы также должны знать, что вар удаляет проверку типа данных во время компиляции при первоначальном назначении.

var x = "mistake";     // error not found by compiler
int x = "mistake";     // error found

Поскольку большинство переменных присваиваются только один раз, последовательное использование вар удаляет почти все проверки типов данных при назначении переменных.

Это делает ваш код уязвимым для случайных изменений, например.созданные с помощью инструментов слияния или уставших разработчиков.

Неявная типизация — это здорово, но люди, которые категорически запрещают ее, вредят производительности и создают хрупкий код.

Это почти как типизированная, проверенная компилятором утиная типизация, которая невероятно полезна при рефакторинге.Например, если у меня есть метод, который возвращает список, и я реорганизую его, чтобы вернуть IEnumerable, то любые вызывающие методы этого метода, которые использовали ключевое слово var и используют только методы IEnumerable, будут в порядке.Если я явно указал, например, List, то мне придется везде изменить его на IEnumerable.

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

Эрик Липперт хорошо подводит итог:

  • Используйте var, когда вам нужно;когда вы используете анонимные типы.
  • Используйте var, когда тип объявления очевиден из инициализатора, особенно если это создание объекта.Это исключает избыточность.
  • Рассмотрите возможность использования var, если в коде подчеркивается семантическая «деловая цель» переменной и преуменьшаются «механические» детали ее хранения.
  • Используйте явные типы, если это необходимо для правильного понимания и поддержки кода.
  • Используйте описательные имена переменных независимо от того, используете ли вы «var».Имена переменных должны отражать семантику переменной, а не детали ее хранения;«decimalRate» — это плохо;«interestRate» — это хорошо.

Мое собственное мнение:Мне сложнее читать и немного бессмысленно использовать такие типы, как int, string, bool или даже User.В конце концов, речь идет об удобочитаемости (за исключением случаев использования ее с LINQ), поэтому, когда вокруг разбросаны переменные, это может быть труднее читать и противоречить цели ключевого слова, для которой его задумали разработчики языка.

От Отдел резервирования деклараций (от Джеффа Кодирование ужасов):

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

Я сам так думаю является стоит взять на себя, но было бы полезно создать подробное руководство о том, когда использовать или нет. излишнее убийство.

У меня были случаи (когда я выполнял foreach через коллекцию Table.Rows), когда использование var приводило к тому, что тип принадлежал некоторому базовому классу, а не фактическому типу DataRow.Это единственный раз, когда у меня были проблемы с var.

'var' означает ясность

Основные споры о том, стоит ли использовать var Ключевое слово или нет зависит от того, насколько читабелен код для вас и других разработчиков.

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

Джейк поздоровался с Биллом.Он ему не понравился, поэтому он повернулся и пошел в другую сторону.

Кто пошел другим путем?Джейк или Билл?В данном случае «Джейк» и «Билл» аналогичны имени типа.А «Он» и «его» подобны ключевому слову var.В этом случае может быть полезно быть более конкретным.Следующий пример гораздо яснее.

Джейк поздоровался с Биллом.Джейку Билл не понравился, поэтому он повернулся и пошел в другую сторону.

В данном случае более конкретная формулировка сделала предложение более ясным.Но так будет не всегда.В некоторых случаях конкретность затрудняет чтение.

Билл любит книги, поэтому Билл пошел в библиотеку и взял книгу, которая Биллу всегда нравилась.

В этом случае было бы легче прочитать предложение, если бы мы использовали «он», а в некоторых случаях вообще опустили его имя. Это эквивалентно использованию слова «он». var ключевое слово.

Билл любит книги, поэтому он пошел в библиотеку и взял книгу, которая ему всегда нравилась.

Эти аналогии отражают суть, но не рассказывают всей истории.Видите ли, в этих примерах был только один способ обращения к человеку.Либо по имени, например Билл, либо в более общем смысле, например «он» и «он».Но мы работаем только с одним словом.

В случае кода у вас есть два «слова»: тип и имя переменной.

Person p = GetPerson();

Теперь возникает вопрос, достаточно ли там информации, чтобы вы могли легко определить, что именно p является?Знали бы вы еще, что представляют собой люди в этом сценарии:

var p = GetPerson();

Как насчет этого:

var p = Get();

Как насчет этого:

var person = Get();

Или этот:

var t = GetPerson();

Или этот:

var u = Person.Get();

Является ли ключевое слово var Работа в конкретном сценарии во многом зависит от контекста кода, например, от имен переменных, классов и методов, а также от сложности кода.

Лично мне нравится использовать var ключевое слово, оно более подробное мне.Но я также склонен называть свои переменные по типу, чтобы не потерять никакой информации.

Тем не менее, иногда я делаю исключения, такова природа всего сложного, а программное обеспечение — это нечто сложное.

Вот результаты теста, который я провел на эффективность var по сравнению с явной типизацией:

  private void btnVar_Click(object sender, EventArgs e)
    {
        Stopwatch obj = new Stopwatch();
        obj.Start();
        var test = "Test";
        test.GetType();
        obj.Stop();
        lblResults.Text = obj.Elapsed.ToString();
    }

    private void btnString_Click(object sender, EventArgs e)
    {
        Stopwatch obj = new Stopwatch();
        obj.Start();
        string test = "Test";
        obj.Stop();
        lblResults.Text = obj.Elapsed.ToString();

    }

Результат первой метки:00:00:00 000034

Результат второй метки:00:00:00 00008

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top