Разница между реализацией var в Javascript и С#
Я хотел бы задать теоретический вопрос. Если у меня есть, например, следующий код С# в Page_load:
cars = new carsModel.carsEntities();
var mftQuery = from mft in cars.Manufacturers
where mft.StockHeaders.Any(sh=> sh.StockCount>0)
orderby mft.CompanyName
select new {mft.CompanyID, mft.CompanyName};
// ...
Вопросы:
- В этом коде используется ключевое слово
var
. Какая польза от этой конструкции?
- В чем ключевое различие между реализацией
var
в Javascript и С#?
Ответы
Ответ 1
JavaScript - это динамически типизированный язык, а С# - (обычно) статически типизированный язык. В результате подобные сравнения всегда будут проблематичными. Но:
Ключевое слово JavaScript var
несколько похоже на ключевое слово С# dynamic
. Оба создают переменную, тип которой не будет известен до выполнения, и чье неправильное использование не будет обнаружено до выполнения. Это способ JavaScript всегда, но это поведение совершенно новое для С# 4.
dynamic foo = new DateTime();
foo.bar(); //compiles fine but blows up at runtime.
JavaScript не имеет ничего общего с С# var
, поскольку JavaScript является динамически типизированным языком, а С# var
, несмотря на распространенное заблуждение, создает переменную, тип которой известен во время компиляции. С# var
выполняет две задачи: объявлять переменные, тип которых является болью для записи, и создавать переменные, которые имеют анонимный тип, и поэтому не имеют типа, который может быть выписан разработчиком.
Пример первого:
var conn = new System.Data.SqlClient.SqlConnection("....");
Анонимные прогнозы типов из Linq-to-Sql или Entity Framework являются хорошим примером второго:
var results = context.People.Where(p => p.Name == "Adam")
.Select(p => new { p.Name, p.Address });
Здесь results
имеет тип IQueryable<SomeTypeTheCompilerCreatedOnTheFly>
. Независимо от того, сколько вы могли бы написать фактический тип результатов, а не просто писать var
, нет никакого способа, поскольку вы не знаете тип, который создает компилятор под обложками для вашего анонимного типа, следовательно терминология: этот тип анонимный
В обоих случаях тип известен в время компиляции, и в обоих случаях, впоследствии говоря, либо
conn = new DateTime();
или
results = new DateTime();
приведет к ошибке компилятора, поскольку вы устанавливаете conn
и results
для типа, который несовместим с тем, что они были объявлены как.
Ответ 2
a) С# var
позволяет избежать записи явного типа при объявлении переменной. Это делает ваш код более компактным, также иногда тип выражения в правой части объявления сложный и в то же время вас не интересует, что такое фактический тип.
b) Javascript var
похож на С# dynamic
. Он позволяет вам объявлять переменную, но вы можете изменить ее тип.
var i = 1;
i = "foo"; // legal in Javascript, illegal in C#
Ответ 3
Единственное, что у них общего, это то, что они используются для объявления локальных переменных.
С# эквивалент JS var
равен dynamic
. Но так как большинство пользователей С# предпочитают статическую типизацию, они обычно используются только в некоторых сценариях взаимодействия (с COM или динамически типизированным языком).
С# var
по-прежнему использует статическую типизацию, но с выведенным типом. Поскольку JS поддерживает только динамическое типирование, эквивалент не существует.
В этом контексте явное статическое типирование невозможно, так как new {mft.CompanyID, mft.CompanyName}
создает анонимный тип, поэтому неявное статическое типирование с var
используется.
Ответ 4
var в С# является динамическим во время разработки, но статически вводится во время компиляции. Вы увидите, что если:
var mftQuery = from mft in cars.Manufacturers
where mft.StockHeaders.Any(sh=> sh.StockCount>0)
orderby mft.CompanyName
select new {mft.CompanyID, mft.CompanyName};
а затем:
mftQuery = "Hello world!";
Он не будет компилировать и жаловаться на типы missmatching, даже если вы не указали какой-либо тип.
Это полезное повышение производительности, потому что вы можете легко изменить типы возвращаемых данных на аналогичные типы, не нарушая ничего, и его легче написать. Глупый пример:
foreach(var animal in GetCats()){
Console.WriteLine(animal.Owner);
}
можно изменить на:
foreach(var animal in GetDogs()){
Console.WriteLine(animal.Owner);
}
Ответ 5
И чтобы ответить на ваш вопрос 1, преимущество использования ключевого слова var
в представленном коде может быть трудным для получения результирующего типа для запроса LINQ и может быть легко затронуто путем изменения запроса. Фактически, его введение в С# совпадает с премьерой LINQ.
Повторяя, нужно упростить жизнь программиста, а также удалить избыточность Type t = new Type()
.