三、匿名類型的解析:
匿名類型的基礎是對象初始化器,匿名類型從對象初始化器(object initializer)自動推斷和生成的元組類型。下面我們來看看匿名類型到底怎麼生成的和我們原來的定義方式有什麼區別:
var noname = new { namea = "dd", age = 24 };//匿名類型
var qname = new { namea = "ff", age = 25 };
第一句,給noname賦了一個匿名類型,在編譯時,編譯器使用對象初始化器推斷的屬性來創建見一個新的匿名類型,該類型擁有aname啊和age的屬性,在運行時,會創建新類型的一個實例同時namea和age屬性將會被設置為對象初始化器中指定的值“dd”、24;和上面幾節裡描述的一樣這裡大家一定會想到,肯定又是在編譯器裡封裝了一些處理;確實是這樣,下面這段代碼描述編譯器針對匿名類型語句具體做了哪些工作:
class __Anonymous1
{
private string name;
private int age;
public string Name { get { return name; } set { name = value; } }
public int Age { get { return age; } set { age = value; } }
}
__Anonymous1 noname = new __Anonymous1();
noname.Name="dd";
noname.Age=24;
這段代碼就是我們非常熟悉的寫法,編譯器就是在後台依據匿名類型解析類型,創建新類,初始化對象;如果你創建了多個相似的匿名類型,C#編譯器會聰明的發現這一點,只生成一個類和它的多個實例;
上邊說到,這兩句中,noname和qname的類型相同,可以通過Visual Studio 2008的工具ILDasm來驗證。這個工具能對一個程序或者它的類庫執行反匯編處理,顯示由C#編譯器生成的CIL代碼,通過反匯編可以列出封裝在程序集中的類型信息。為此,先給出完整的類代碼:
public class EDClass
{
public string Name { get; private set; }
public EDClass()
{
Name = "QQ1";
}
public void setName()
{
Name = "QQ";
var noname = new { namea = "dd", age = 24 };//匿名類型
var qname = new { namea = "ff", age = 25 };
//var vara = new { hei = null, id = 5 };
if (qname == noname)
{
//!=,所以不能輸出
Console.WriteLine("qname == noname");
}
if (qname.Equals(noname))
{
//Equal,能夠輸出
Console.WriteLine("qname equal noname");
}
if (qname.GetHashCode() == noname.GetHashCode())
{
//能夠輸出
Console.WriteLine("same hashcode");
}
}
}