据我所知,匿名类型没有自己的预定义类型。编译器以编译类型为其分配类型,并且在编译时分配的类型的详细信息不能在代码级别知道;这些细节是CLR本身所知的。我听说CLR的这些匿名类型被视为仅仅是引用类型。所以我的问题是,在编译时是否创建了类似于类或结构的新类型,对应于匿名类型中定义的只读属性?
答案 0 :(得分:12)
据我所知,匿名类型没有自己的预定义类型。
正确。除了匿名类型共有的对象之外,没有其他基本类型。
编译器以编译类型为其分配类型,并且在编译时分配的类型的详细信息无法在代码级别知道
这是正确的。
CLR本身已知这些细节。
我不知道你所谈论的“细节”或“CLR所知”的含义。
我听说CLR的这些匿名类型被视为仅仅是引用类型。
你听错了。
所以我的问题是,在编译时是否创建了类似于类或结构的新类型,对应于匿名类型中定义的只读属性?
是。创建一个新类。
注意程序集中的如果有两个具有相同属性名称,相同属性类型的匿名类型,顺序相同,则只创建一个类型。这是由语言规范保证的。
练习:
// Code in Assembly B:
public class B { protected class P {} }
// Code in Assembly D (references assembly B)
class D1 : B {
public static object M() { return new { X = new B.P() }; }
}
class D2 : B {
public static object M() { return new { X = new B.P() }; }
}
您需要在程序集D中生成一个单个类声明,该声明具有类型为B.P的属性X,使D1.M().GetType()
等于D2.M().GetType()
。描述如何操作。
答案 1 :(得分:6)
匿名类型是类类型,它直接从对象派生,并且不能转换为除object之外的任何类型。尽管您的应用程序无法访问它,但编译器为每个匿名类型提供了一个名称。从公共语言运行时的角度来看,匿名类型与任何其他引用类型没有区别。
答案 2 :(得分:3)
除了没有程序员可访问的名称之外,匿名类型非常简单:编译器根据您所做的分配生成它们,并负责将相同匿名类型从同一方法正确合并到单个运行时类型中。
根据C#语言规范第7.6.10.6节,匿名类型始终是类,而不是struct
。表单
new { p1 = e1 , p2 = e2 , ... pn = en }
声明表单的匿名类型
class __Anonymous1 {
private readonly T1 f1 ;
private readonly T2 f2 ;
...
private readonly Tn fn ;
public __Anonymous1(T1 a1, T2 a2,…, Tn an) {
f1 = a1 ;
f2 = a2 ;
...
fn = an ;
}
public T1 p1 { get { return f1 ; } }
public T2 p2 { get { return f2 ; } }
...
public Tn pn { get { return fn ; } }
public override bool Equals(object __o) { … }
public override int GetHashCode() { … }
}
答案 3 :(得分:1)
这些匿名类直接来自对象。通常,它们用于选择LINQ查询,以将只读属性封装到单个对象中。
LINQ示例(FirstName和LastName作为FullName):
public class Person {
public int Id {get;set;}
public string FirstName {get;set;}
public string LastName {get;set;}
}
IEnumerable<int> personIds = persons
.Select(p => new { Id = p.Id, FullName = p.FirstName + " " + p.LastName})
.Where(a => a.FullName == "John Smith")
.Select(a => a.Id);
答案 4 :(得分:1)
匿名类型是C♯功能,在CLI上没有等效功能。它们被简单地编译为普通类型,编译器选择了非常长且非常复杂的名称。请注意,规范保证具有相同结构的两个匿名类型(在同一个程序集中)实际上是相同的类型,因此编译器也需要考虑到这一点,并且只生成一个类型(并为两者生成相同的名称)用法网站)。