匿名类型C#

时间:2016-12-20 19:58:04

标签: c# anonymous-types

据我所知,匿名类型没有自己的预定义类型。编译器以编译类型为其分配类型,并且在编译时分配的类型的详细信息不能在代码级别知道;这些细节是CLR本身所知的。我听说CLR的这些匿名类型被视为仅仅是引用类型。所以我的问题是,在编译时是否创建了类似于类或结构的新类型,对应于匿名类型中定义的只读属性?

5 个答案:

答案 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之外的任何类型。尽管您的应用程序无法访问它,但编译器为每个匿名类型提供了一个名称。从公共语言运行时的角度来看,匿名类型与任何其他引用类型没有区别

来源:https://msdn.microsoft.com/en-us/library/bb397696.aspx

答案 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上没有等效功能。它们被简单地编译为普通类型,编译器选择了非常长且非常复杂的名称。请注意,规范保证具有相同结构的两个匿名类型(在同一个程序集中)实际上是相同的类型,因此编译器也需要考虑到这一点,并且只生成一个类型(并为两者生成相同的名称)用法网站)。