Страницы

Поиск по вопросам

суббота, 7 декабря 2019 г.

Анонимные типы в c# и их особенности?

#c_sharp #c_sharp_faq


Начал изучать анонимные типы в C#.
Автор приводит пример синтаксиса анонимного типа var instance = new { Name = "Alex",
Age = 27 }; и предлагает последовательно — шаг за шагом добавить на эту строку дополнительные
элементы синтаксиса, чтобы данная строк стала более узнаваемая "читаемая" для нас (напоминаю:
автор это делает т.к пример и весь курс — учебный) т.е. превратив выше приведенную строку в

var instance = new MyClass() { Name = "Alex", Age = 27 };


говоря, что мы добавили имя конструктора по умолчанию и круглые скобки для приема
аргументов конструктора, и тут же демонстрируеь, что добавляя это — студия предлагает
сгенерировать нам свойства для Age и для Name в классе MyClass(класс он создал сам
— опять же для примера, но сказал, что в анонимных типах при генерации свойств класс
также создаётся автоматически).
В классе сгенерировались автореализуемые свойства


Но автор сказал, что они должны быть только для чтения, т.е. в (ну в данном случае
посто нужно убрать set — ведь студия генерировала свойства как для обычных полей класса
когда мы дописала имя конструктора по умолчаню после ключевого слова new).
И это подводит меня к вопросу №3 (вопросы №1 и №2 представлены ниже). Если автогенерируемые,
автореализуемые свойства в также автоматически созданном классе (назовем его MyClass)
только для чтения, то каким образом в блоке инициализатора на строке var instance =
new { Name = "Alex", Age = 27 }; мы вообще можем присваивать этим полям значения?
Вот скриншот первого примера, в котором меня интересует комментарий, в котором у
меня и возникают все эти вопросы.


Вопрос №1: т.е. компилятор каждый раз создает новое имя для анонимного типа, который
в свою очередь является ссылочным типом?

Вопрос №2: т.е. приложение не может обращаться ссылке (т.к. тип ссылочный) к 
новому имени созданному компилятором.

Вопрос №3 представлен вначале. 
    


Ответы

Ответ 1



Да, так задумано. Компилятор создаёт имя наподобие <>f__AnonymousType0, которое невозможно использовать из C#. К нему невозможно получить доступ просто так, потому что такие имена нельзя использовать в C#. Но вы легко можете увидеть это имя при помощи рефлексии: class Program { public static void Main() { var o = new { x = 5, y = 8 }; foreach (var t in Assembly.GetExecutingAssembly().GetTypes()) Console.WriteLine(t.Name); } } выдаёт <>f__AnonymousType0`2 Program Settings (`2 означает, что класс на самом деле является generic-классом по причинам, указанным здесь) Программа вполне может обращаться по ссылке к значениям этого типа. Просто она не может получить имя типа, чтобы, например, объявить тип возвращаемого значения. Обращение на чтение работает: var o = new { x = 5, y = 8 }; // var необходим, т. к. мы не можем назвать имя Console.WriteLine(o.x); // обращение по ссылке Нет, присваивать свойствам анонимного типа нельзя. Они создаются вовсе без сеттера. На самом деле вот такой код: var o = new { x = 5, y = 8 }; порождает (примерно) следующий класс: [DebuggerDisplay("{ x = {x}, y = {y} }", Type = "")] public sealed class Anonymous { private readonly TX field_x; private readonly TY field_y; public TX x { get { return field_x; } } public TY y { get { return field_y; } } [DebuggerHidden] public Anonymous(PX x, PY y) { field_x = x; field_y = y; } public override bool Equals(object value) { /* тут имплементация */ } public override int GetHashCode() { /* тут имплементация */ } public override string ToString() { /* тут имплементация */ } } а ваш вызов превращается компилятором в следующее: Anomymous o = new Anonymous(5, 8); Вы видите, что на самом деле присвоения свойствам нету, а есть просто вызов конструктора. Поэтому в дальнейшем запись в эти же свойства невозможна.

Комментариев нет:

Отправить комментарий