通過is運算符,能夠判斷對象類型是否為特定類型,如果兩種類型是相同類型,或者兩者之間存在引用,裝箱拆箱轉(zhuǎn)換,則表明兩種類型是兼容的。
class PRogram { static void Main(string[] args) { A a = new A(); B b = new B(); if (a is A) { Console.WriteLine("a is an A"); //這個打印,因為a 是 A 類型的對象 } if (b is A) { //這個打印,因為b是B類型的對象,而B類型派生于A類型,由于b對象可以轉(zhuǎn)換為A類型,因此b對象與A類型是兼容的,但是反過來就不成立,例如下面不打印 Console.WriteLine("b is an A because it is derived from"); } if (a is B) { //這個不打印 Console.WriteLine("This won't display , because a not derived from B"); } if (a is object) { //這個打印 Console.WriteLine("a is an object"); } Console.ReadKey(); } } class A { } class B : A { }
在運行期間執(zhí)行類型轉(zhuǎn)換,并且能夠使得類型轉(zhuǎn)換失敗不拋異常,而返回一個null值,其實as也可以看作一個is運算符的簡化備選方式(看例子)。
class Program { static void Main(string[] args) { A a = new A(); B b = new B(); if (a is B) { b = (B)a; //由于a變量不是B類型,因此這里將a變量轉(zhuǎn)換為B類型是無效的。 } else { b = null; } if (b ==null) { //這個打印 Console.WriteLine("The cast in b=(B)a is not allowed"); } //上面使用as運算符,能夠把兩部合二為一。 b = a as B; //as類型先檢查強制類型轉(zhuǎn)換的有效性,如果有效,則執(zhí)行強類型轉(zhuǎn)換過程。這些都在這一句完成。 if (b == null) { //這個打印 Console.WriteLine("The cast in b=(B)a is not allowed"); } Console.ReadKey(); } } class A { } class B : A { }
as ,is 能夠測試兩種類型的兼容性。但大多數(shù)情況下,還需要獲得某個類型的具體信息。這就用到了typeof,它可以返回與具體類型相關(guān)的System.Type對象,通過System.Type對象可以去頂此類型的特征。一旦獲得給定類型的Type對象,就可以通過使用該對象定義的各種屬性,字段,方法來獲取類型的具體信息。Type類包含了很多成員,在接下來的反射中再詳細討論。下面簡單的演示Type對象,調(diào)用它的三個屬性。
static void Main(string[] args) { Type t=typeof(StringBuilder); Console.WriteLine(t.FullName); //FullName屬性返回類型的全稱 if (t.IsClass) { Console.WriteLine("is a class"); //打印 } if (t.IsSealed) //是否為密封類 { Console.WriteLine("is Sealed"); //打印 } Console.ReadKey(); }
MemberInfo類中的只讀屬性 | |
屬性 | 描述 |
TypeDeclaringType | 獲取聲明該成員的類或接口的類型 |
MemberTypesMemberType | 獲取成員的類型,這個值用于指示該成員是字段、方法、屬性、事件、或構(gòu)造函數(shù) |
IntMetadataToken | 獲取與特定元數(shù)據(jù)相關(guān)的值 |
ModuleModule | 獲取一個代表反射類型所在模塊(可執(zhí)行文件)的Module對象 |
StringName | 成員的名稱 |
TypeReflectedType | 反射的對象類型 |
請注意
當(dāng)然除了MemberInfo類定義的方法和屬性外,Type類自己也添加了許多屬性和方法:如下表(只列出一些常用的,太多了,自己可以轉(zhuǎn)定義Type類看下)
Type類定義的方法 | |
方法 | 功能 |
ConstructorInfo[] GetConstructors() | 獲取指定類型的構(gòu)造函數(shù)列表 |
EventInfo[] GetEvents(); | 獲取指定類型的時間列 |
FieldInfo[] GetFields(); | 獲取指定類型的字段列 |
Type[] GetGenericArguments(); | 獲取與已構(gòu)造的泛型類型綁定的類型參數(shù)列表,如果指定類型的泛型類型定義,則獲得類型形參。對于正早構(gòu)造的類型,該列表就可能同時包含類型實參和類型形參 |
MemberInfo[] GetMembers(); | 獲取指定類型的成員列表 |
MethodInfo[] GetMethods(); | 獲取指定類型的方法列表 |
PropertyInfo[] GetProperties(); | 獲取指定類型的屬性列表 |
下面列出Type類定義的常用的只讀屬性
Type類定義的屬性 | |
屬性 | 功能 |
Assembly Assembly | 獲取指定類型的程序集 |
TypeAttributes Attributes | 獲取制定類型的特性 |
Type BaseType | 獲取指定類型的直接基類型 |
String FullName | 獲取指定類型的全名 |
bool IsAbstract | 如果指定類型是抽象類型,返回true |
bool IsClass | 如果指定類型是類,返回true |
string Namespace | 獲取指定類型的命名空間 |
上面的列術(shù)都是為了,這里的使用。
通過使用Type類定義的方法和屬性,我們能夠在運行時獲得類型的各種具體信息。這是一個非常強大的功能。我們一旦得到類型信息,就可以調(diào)用其構(gòu)造函數(shù),方法,和屬性。可見,反射是允許使用編譯時不可用的代碼的。
由于Reflection API非常多,這里不可能完整的介紹他們(這里如果完整的介紹,據(jù)說要一本書,厚書)。但是,Reflection API是按照一定邏輯設(shè)計的。因此,只要知道部分接口的使用方法,就可以舉一反三的使用剩余的接口。
這里我列出四種關(guān)鍵的反射技術(shù):
一旦有了Type對象就可以使用GetMethodInfo()方法獲取此類型支持的方法列表。該方法返回一個MethodInfo 對象數(shù)組,MethodInfo對象描述了主調(diào)類型所支持的方法,他位于System.Reflection命名空間中
MethodInfo類派生于Method
新聞熱點
疑難解答