Вложенные анонимные типы?

315
25 декабря 2016, 18:40

Всем привет, имеется вот такой пример:

class Program
{
    static void Main()
    {
        // Анонимные типы в анонимных типах.
        var instance = new { Name = "Alex", Age = 27, Id = new { Number = 123 } };
        Console.WriteLine("Name = {0}, Age = {1}, Id = {2}", instance.Name, instance.Age, instance.Id.Number);

        // Delay.
        Console.ReadKey();
    }
}

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

Также как я понял, когда я создаю анонимный тип, Visual Studio создает новый класс и новый класс создается когда компилятор встречает новый анонимный тип. Новизна определяется путем сравнения имен свойств, их порядка и типов. И получается, что когда я создаю новый анонимный тип, то Visual Studio порождает (примерно) следующий класс:

[DebuggerDisplay("{ x = {x}, y = {y} }", Type = "<Anonymous Type>")]
public sealed class Anonymous<TX, TY>
{
    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() { /* тут имплементация */ }
}

Но если у меня один анонимный тип вложен в другой, то эти порожденные классы будут Nested классами ли нет?

Answer 1

Практика — критерий истины! Попробуем и посмотрим, что получилось.

class Program
{
    static void Main(string[] args)
    {
        var instance = new { Name = "Alex", Age = 27, Id = new { Number = 123 } };
        var allTypes = Assembly.GetExecutingAssembly().GetTypes();
        foreach (var t in allTypes)
        {
            var nestedTypes = t.GetNestedTypes(BindingFlags.Public | BindingFlags.NonPublic);
            Console.WriteLine($"Name: {t.FullName}, nested types: {nestedTypes.Length}");
        }
    }
}

Результат:

Name: <>f__AnonymousType0`3, nested types: 0
Name: <>f__AnonymousType1`1, nested types: 0
Name: NestedAnonymous.Program, nested types: 0

Таким образом, для компилятора второй анонимный тип ничем не отличается от первого, вложенных типов в программе нету. Этого и стоило ожидать: ведь когда мы пишем var instance = new { List = new List<int>() };, мы же не ожидаем, что List<int> окажется вложенным типом анонимного типа?

Для сравнения, положим ещё один вложенный тип:

class Program
{
    class Nested { }
    static void Main(string[] args)
    {
        var instance = new { Name = "Alex", Age = 27, Id = new { Number = 123 } };
        var allTypes = Assembly.GetExecutingAssembly().GetTypes();
        foreach (var t in allTypes)
        {
            var nestedTypes = t.GetNestedTypes(BindingFlags.Public | BindingFlags.NonPublic);
            Console.WriteLine($"Name: {t.FullName}, nested types: {nestedTypes.Length}");
        }
    }
}

Получаем такой вывод:

Name: <>f__AnonymousType0`3, nested types: 0
Name: <>f__AnonymousType1`1, nested types: 0
Name: NestedAnonymous.Program, nested types: 1
Name: NestedAnonymous.Program+Nested, nested types: 0

Мы видим, что у Program появился вложенный тип, и что имя вложенного типа содержит имя объемлющего типа, отделённое плюсиком. (Это, разумеется, внутренняя подробность имплементации анонимных типов компилятором в поставке MSVC 2015, другие компиляторы могут делать это по-другому.)

READ ALSO
xPath selectSingleNode не могу выбрать элемент

xPath selectSingleNode не могу выбрать элемент

Добрый деньесть XML файл

493
Генерация и движение объектов(врагов) [требует правки]

Генерация и движение объектов(врагов) [требует правки]

Хотел бы узнать, как в консоле реализовать генерацию, движение и стрельбу противников

284
Убрать полосы прокрутки Console C#

Убрать полосы прокрутки Console C#

Пишу мини-игру на Console C#Для более красивого отображения хочется убрать полосы прокрутки снизу и сбоку консоли

653