Использование общих анонимных типов в одной сборке. Часть 1

В одной из моих заметок 2010-го года я сказал, что приведу в следующем году пример использования в сборке одного и того же анонимного типа. Я имел в виду 2011-й год, но вот, снова наступил «новый год», так почему бы не написать об этом сейчас.

Спецификация языка C# гарантирует, что использование «одного и того же» анонимного типа в двух местах в одной и той же сборке (*) приведет к использованию одного типа. Для того чтобы два анонимных типа были «одинаковыми», они должны иметь одинаковые имена полей одинаковых типов и в одинаковой последовательности. (**)

Вот простой пример, который можно написать:

var anon1 = new { X = 1 };
var anon2 = new { X = 2 };
anon2 = anon1;
Console.WriteLine(anon2.X); // 1

С помощью механизма отражения вы легко можете в этом убедиться:

class C
{
public static object Anon1() { return new { X = 1 }; }
}
class D
{
static void M()
{
// True:
Console.WriteLine(C.Anon1().GetType() == (new { X = 2 }).GetType());
}
}

Ну… и что? Такое использование отражения кажется невероятно неинтересным. Намного интереснее объединить два предыдущих примера вместе:

class C
{
public static object Anon1() { return new { X = 1 }; }
}
class D
{
static T CastByExample<T>(T example, object obj)
{
return (T)obj;
}
static void M()
{
var anon1 = CastByExample(new { X = 0 }, C.Anon1());
var anon2 = new { X = 2 };
anon2 = anon1;
Console.WriteLine(anon1.X); // 1
}
}

Как видите, если хотите, то вы можете совместно использовать экземпляры анонимных типов внутри одной сборки. Мы не рассчитываем, что многие будут этим пользоваться; если вам понадобится что-то подобное, то можно использовать кортежи (tuple) или обыкновенные типы. Но, все же, данное свойство было довольно просто реализовать, и оно может быть весьма полезным.


(*) Технически, это не совсем верно. Вы можете собрать сборку из разных подмодулей (netmodule), скомпилированных в разное время и не знающих ничего друг о друге; в таком случае, анонимные типы, определенные в разных подмодулях не обязательно будут использовать общие анонимные типы.

(**) В следующий раз я расскажу о необходимости последнего требования.

Оригинал статьи