Анонимный тип против динамического типа - PullRequest
38 голосов
/ 24 декабря 2008

Каковы реальные различия между анонимным типом (var) в c # 3.0 и динамическим типом (динамическим), который входит в c # 4.0?

Ответы [ 6 ]

91 голосов
/ 24 декабря 2008

Вы, кажется, смешиваете три совершенно разные, ортогональные вещи:

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

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

Статическая или динамическая типизация относится к , когда происходит проверка типа: динамическая типизация происходит в время выполнения , статическая типизация происходит до выполнения .

Манифест против неявной типизация указывает, являются ли типы манифестами в исходном коде или нет: манифест тип означает, что программист должен написать вводит в исходный код, неявная типизация означает, что система типов вычисляет их самостоятельно.

Именованные и анонимные типы относится к тому, есть ли у типов имена или нет.

Ключевое слово dynamic в C # 4.0 означает, что эта переменная, параметр, метод, поле, свойство ... независимо от того, динамически типизирован , то есть его тип будет проверяться во время выполнения. Все, что не типизировано как динамическое, статически типизировано. Является ли тип статическим или динамическим, не только определяет, когда происходит проверка типа, но и в C # 4.0 он также определяет, когда происходит отправка метода . В C # диспетчеризация метода выполняется перед выполнением на основе статического типа (за исключением, конечно, полиморфизма подтипа во время выполнения), тогда как для динамически типизированных объектов в C # 4.0 диспетчеризация метода выполняется во время выполнения на основе типа среды исполнения.

Ключевое слово var в C # 3.0 означает, что эта локальная переменная будет неявно типизирована , т. Е. Вместо того, чтобы программист явно записывал тип, система типов сама определит его. Это не имеет ничего общего с динамической типизацией, по крайней мере, в C # 3.0. Переменная будет строго типизирована так же, как если бы вы сами записали тип. Это просто удобство: например, зачем вам записывать все имена типов дважды в HashMap<int, string> foo = new HashMap<int, string>();, когда система типов может ясно выяснить, что foo HashMap<int, string>, поэтому вместо этого вы пишете var foo = new HashMap<int, string();. Обратите внимание, что в этом нет ничего динамичного или анонимного. Тип является статическим и имеет имя: HashMap<int, string>. Конечно, в C # 4.0, если система типов обнаруживает, что правая часть присваивания является динамической, то тип переменной в левой части будет динамическим.

анонимный тип в C # 3.0 означает, что этот тип не имеет имени. Ну, на самом деле, real анонимным типам потребовалось бы изменение, несовместимое с предыдущими версиями, в Common Type System, так что на самом деле происходит за кулисами, это то, что компилятор будет генерировать очень долго, очень случайное, уникальное и недопустимое имя для типа и поместите это имя везде, где появляется анонимный тип. Но с точки зрения программиста тип не имеет имени. Почему это полезно? Ну, иногда у вас есть промежуточные результаты, которые вам нужны только на короткое время, а затем выбрасывайте снова. Предоставление таким временным типам собственных имен повысит их до уровня важности, которого они просто не заслуживают. Но опять же, в этом нет ничего динамичного.

Итак, если тип не имеет имени, как программист может ссылаться на него? Ну, она не может! По крайней мере, не напрямую. Программист может сделать, описать тип: он имеет два свойства, одно из которых называется «имя» типа string, другое - «id» типа int. Это тот тип, который я хочу, но мне все равно, как он называется.

Вот где кусочки начинают собираться вместе. В C # вы должны объявлять типы локальных переменных, явно записывая имена типов. Но как вы можете записать имя типа, у которого нет имени? Вот тут и приходит var: поскольку начиная с C # 3.0, это на самом деле уже не так: вам больше не нужно записывать имена, вы также можете сказать компилятору выяснить это. Итак, хотя то, что я написал в первом абзаце выше, верно, что неявная типизация и анонимные типы не имеют ничего общего с другими, также верно, что анонимные типы были бы довольно бесполезны без неявной типизации.

Обратите внимание, однако, что обратное неверно: неявная типизация очень полезна без анонимных типов. var foo = HashMap<int, string> имеет смысл, и в поле зрения нет анонимного типа.

19 голосов
/ 24 декабря 2008

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

Насколько я понимаю, динамические типы связаны с поздним связыванием. Это означает, что CLR (или DLR) будет оценивать объект во время выполнения, а затем использовать утку, чтобы разрешить или запретить доступ членов к объекту.

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

18 голосов
/ 24 декабря 2008

Тип dynamic по существу object, но он разрешает все вызовы метода / свойства / оператора и т. Д. во время выполнения через DLR или другого поставщика (например, отражения).

Это делает его очень похожим на VB с Option Strict Off, и делает его очень универсальным для вызова в COM или в типы DLR.

Во время компиляции есть нет проверки типов с помощью dynamic; очевидно, что анонимные типы - это правильные статически типизированные звери, прошедшие проверку типа (их можно увидеть в отражателе, хотя они не очень красивые).

Кроме того, анонимные типы могут обрабатываться исключительно компилятором; dynamic требует обширной поддержки во время выполнения - поэтому анонимные типы являются функцией C #, но dynamic будет в основном реализовано в .NET 4.0 (с некоторой поддержкой C # 4.0).

8 голосов
/ 24 декабря 2008

Ознакомьтесь с презентацией Андерса здесь:

http://channel9.msdn.com/pdc2008/TL16/

HTM

6 голосов
/ 24 декабря 2008

Три раза, с тремя актерами - по одному на каждый раз.

  • Время разработки - программист
  • Время компиляции - компилятор c #
  • Время выполнения - .net время выполнения

Анонимные типы объявляются и именуются компилятором. Это объявление основано на спецификации программиста (как он использовал тип). Поскольку эти типы названы в честь того, как программист покинул процесс, они кажутся программисту безымянными и, следовательно, «анонимными».

  • Программист говорит: У некоторого типа есть Имя и Адрес
  • Компилятор говорит: есть тип с именем xyz со свойствами и полями Name и Address, обе строки.
  • среда выполнения говорит: я не могу отличить xyz от типа, который сделал программист.

динамическая типизация в c # позволяет вам вызывать методы, которые могут существовать или не существовать во время компиляции. Это полезно для вызова в python или javascript, которые не компилируются.

  • Программист говорит: относитесь к этому экземпляру автомобиля как к динамическому типу. Теперь шарлатан.
  • Компилятор говорит: динамическая типизация, а? должно быть в порядке. Я не буду жаловаться, потому что не могу это проверить.
  • Среда выполнения пытается создать экземпляр автомобиля, шарлатана.
1 голос
/ 24 февраля 2017

Ничего подобного небольшому коду, чтобы прояснить ситуацию:

// anonymous types
var anonType = new {Id = "123123123", Name = "Goku", Age = 30, DateAdded = new DateTime()};
// notice we have a strongly typed anonymous class we can access the properties with
Console.WriteLine($"Anonymous Type: {anonType.Id} {anonType.Name} {anonType.Age} {anonType.DateAdded}");
// compile time error
//anonType = 100;

// dynamic types
dynamic dynType = 100.01m;
Console.WriteLine($"Dynamic type: {dynType}");
// it's ok to change the type however you want
dynType = new List<DateTime>();
Console.WriteLine($"Dynamic type: {dynType}");

// mix dynamic and anonymous
dynamic dynamicAnonymousType = new {Id = 8000, FirstName = "Goku", Gender = "male", IsSuperSaiyan = true};
// Wasn't sure this would work but it does! However, you lose intellisense on the FirstName so you have to type it manually.
Console.WriteLine($"FirstName: {dynamicAnonymousType.FirstName}");
dynamicAnonymousType = 100;
Console.WriteLine(dynamicAnonymousType);
// runtime error
Console.WriteLine($"Id: {dynamicAnonymousType.FirstName}");
...