В C # как выведенные переменные, использующие var, ведут себя в отношении памяти и жизненного цикла? - PullRequest
3 голосов
/ 14 июля 2010

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

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

int i = 5;  // puts this on the stack
var i = 5;  // does this also go on the stack?

Имеет ли объявленная переменная постоянный тип после инициализации или ее также можно настроить?Я спрашиваю об этом, потому что не могу найти в документации, где это указано, и я просто прочитал что-то в этом ТАКОМ вопросе @ Eric Lippert :

переменная - это место хранения, содержимое которого изменяется

Протестировав следующий код, я вижу исключение неявного преобразования даже на уровне IDE.На данный момент у меня нет опыта работы с LINQ для запуска аналогичного теста в отношении анонимных типов.Они следуют этому же поведению?Признает ли среда IDE несоответствие типов во время разработки или такой код получит исключение во время выполнения?

var i = 5;    // Initializes as int, value is 5
i = "Steve";  // Type casting error

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

РЕДАКТИРОВАТЬ: я понимаю, что есть много статей, говорящих на эту тему, но я не нашел ни одного, который отвечал бы на эти вопросы определенно (хотя некоторые подсказки так или иначе).Я был бы рад прочитать любой документ, который, по вашему мнению, имеет отношение к этим темам, просто отправьте ссылку.

Ответы [ 5 ]

17 голосов
/ 14 июля 2010

var - это 100% синтаксический сахар в компиляторе C #.Когда фактический IL генерируется, тип определен явно.var -объявленные переменные не ведут себя иначе, чем их явно определенные аналоги.Недостаток информации, которую вы видите, связан с тем, что var проще, чем вы предполагаете.Буквально нет никакой разницы между этими двумя строками:

var i = 10;
int j = 10;

(Конечно, кроме того, что вы видите слова var и int; они функционально полностью идентичны).*

9 голосов
/ 14 июля 2010

переменные var выводятся компилятором, они на самом деле просто синтаксический сахар, между ними нет никакой разницы:

var i =0;

и

int i = 0;

в скомпилированном коде.

Они были добавлены с целью разрешения анонимных типов, например

var MyVar = new { prop1="A string", prop2=5};

Да, var varables распознают несоответствие типов во время компиляции, компилятор динамически создает класс для них при компиляции. например ниже не будет компилироваться:

var MyVar = new { prop1="A string", prop2=5};
MyVar = "Fred";
4 голосов
/ 14 июля 2010

Как уже говорили другие, var не влияет на поведение переменных с точки зрения памяти - это просто означает, что вы не указываете имя. Для анонимных типов вы не могли указать имя, во-первых, потому что вы не знаете его во время компиляции, а во-вторых, потому что имена преднамеренно «невыразимы» - они недопустимы в C #. (Как правило, они содержат <>, например.)

IL, сгенерированный для кода, использующего var, и код, использующий явное имя, равны точно . Так же, как обычная переменная не может изменить тип, так же как и переменная, объявленная с использованием var ..., так и в вашем примере, где вы пытаетесь присвоить значение «Стив» переменной, которая имеет неявный тип int, вы получите ошибку во время компиляции точно так же, как если бы вы явно объявили, что она имеет тип int.

Что касается того, когда использовать var, а когда нет, у меня есть несколько практических правил:

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

По сути, все дело в удобочитаемости: если код легче читать с помощью var, сделайте это. Если нет, не надо. Обратите внимание, что это не - это то же самое, что сохранение печатания ... код обычно читается больше, чем написано, так что подумайте о своем читателе. Эрик Липперт написал отличную заметку при рассмотрении технической статьи о первом издании C # in Depth, которое стоит прочитать.

3 голосов
/ 14 июля 2010

Простой ответ: точно так же, как обычные переменные.

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

1 голос
/ 14 июля 2010

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

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

var number = 1;

Изменится на:

System.Int32 number = 1;

... компилятором.И как таковые места памяти для хранения этих типов ничем не отличаются.вар по сути синтаксический сахар.Таким образом, локальные объявления методов типов значений сохраняются в стеке, а ссылочные указатели сохраняются в стеке вместе со ссылочными объектами в куче.

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

var i = 5;
i = "Steve"; 

... недопустим, потому что он уже был объявлен как Int32.

Анонимные типыследуйте аналогичному поведению, когда тип создается компилятором во время компиляции.

"Наконец, когда-нибудь возникает ситуация, когда вы можете подумать, где вы можете знать тип во время разработки, но было бы разумнов любом случае использовать var? "

Лично я следую простому шаблону:

Для примитивов я всегда ставлю тип:

int i = 5;
string name = "Matt";

Для сложных типов я в основном делаюthis:

var instance = new MyComplexTypeInstance();

Для результатов LINQ я придерживаюсь var:

var result = from i in something select i;

Для методов, если метод описывает возвращаемый тип, я буду использовать var.

var instance = GetInstance();

Принимая во внимание, что более сложные имена методов я бы назвал реальным типом:

Result result = DoSomethingWeirdAndWonderful(); 

Каждый разработчик найдет то, что ему удобно, выбор за вами.Поскольку var - это действительно только вещь времени разработки, ее синтаксический сахар.

...