Это деталь реализации, которую вы не понимаете.
Если вы используете анонимный тип, компилятор должен сгенерировать новый тип (с неописуемым именем, таким как <>f__AnonymousType0<<A>j__TPar>
), и он генерирует этот тип в сборке, которая его использует.
Он будет использовать этот же сгенерированный тип для всех случаев использования анонимных типов с одинаковой структурой в этой сборке. Тем не менее, каждая сборка будет иметь свои собственные определения анонимных типов: нет возможности поделиться ими между сборками. Конечно, как вы обнаружили, это можно обойти как object
.
. Это ограничение является одной из основных причин, по которой нет способа разоблачить анонимные типы: вы не можете их вернуть. из методов, имейте их как поля et c. Это могло бы вызвать всевозможные проблемы, если бы вы могли передавать их между сборками.
Вы можете видеть это на работе в SharpLab , где:
var x = new { A = 1 };
вызывает это тип, который будет сгенерирован в той же сборке:
internal sealed class <>f__AnonymousType0<<A>j__TPar>
{
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
private readonly <A>j__TPar <A>i__Field;
public <A>j__TPar A
{
get
{
return <A>i__Field;
}
}
[DebuggerHidden]
public <>f__AnonymousType0(<A>j__TPar A)
{
<A>i__Field = A;
}
[DebuggerHidden]
public override bool Equals(object value)
{
global::<>f__AnonymousType0<<A>j__TPar> anon = value as global::<>f__AnonymousType0<<A>j__TPar>;
if (anon != null)
{
return EqualityComparer<<A>j__TPar>.Default.Equals(<A>i__Field, anon.<A>i__Field);
}
return false;
}
[DebuggerHidden]
public override int GetHashCode()
{
return -1711670909 * -1521134295 + EqualityComparer<<A>j__TPar>.Default.GetHashCode(<A>i__Field);
}
[DebuggerHidden]
public override string ToString()
{
object[] obj = new object[1];
<A>j__TPar val = <A>i__Field;
obj[0] = ((val != null) ? val.ToString() : null);
return string.Format(null, "{{ A = {0} }}", obj);
}
}
ValueTuple
имел те же проблемы, связанные с желанием определять типы анонимно, но все же передавать их между сборками, и решал его другим способом: определяя ValueTuple<..>
в BCL и используя волшебный компилятор c, чтобы сделать вид, что их свойства имеют имена, отличные от Item1
, Item2
, et c.