#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); Вы видите, что на самом деле присвоения свойствам нету, а есть просто вызов конструктора. Поэтому в дальнейшем запись в эти же свойства невозможна.
Комментариев нет:
Отправить комментарий