這篇文章主要介紹.NET/C#怎么判斷某個(gè)類(lèi)是否是泛型類(lèi)型或泛型接口的子類(lèi)型,文中介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們一定要看完!
創(chuàng)新互聯(lián)專(zhuān)注于企業(yè)網(wǎng)絡(luò)營(yíng)銷(xiāo)推廣、網(wǎng)站重做改版、美蘭網(wǎng)站定制設(shè)計(jì)、自適應(yīng)品牌網(wǎng)站建設(shè)、H5建站、商城網(wǎng)站定制開(kāi)發(fā)、集團(tuán)公司官網(wǎng)建設(shè)、成都外貿(mào)網(wǎng)站制作、高端網(wǎng)站制作、響應(yīng)式網(wǎng)頁(yè)設(shè)計(jì)等建站業(yè)務(wù),價(jià)格優(yōu)惠性?xún)r(jià)比高,為美蘭等各大城市提供網(wǎng)站開(kāi)發(fā)制作服務(wù)。前言
泛型:通過(guò)參數(shù)化類(lèi)型來(lái)實(shí)現(xiàn)在同一份代碼上操作多種數(shù)據(jù)類(lèi)型。利用“參數(shù)化類(lèi)型”將類(lèi)型抽象化,從而實(shí)現(xiàn)靈活的復(fù)用。在.NET類(lèi)庫(kù)中處處都可以看到泛型的身影,尤其是數(shù)組和集合中,泛型的存在也大大提高了程序員的開(kāi)發(fā)效率。更重要的是,C#的泛型比C++的模板使用更加安全,并且通過(guò)避免裝箱和拆箱操作來(lái)達(dá)到性能提升的目的。因此,我們很有必要掌握并善用這個(gè)強(qiáng)大的語(yǔ)言特性。
C#泛型特點(diǎn):
1、如果實(shí)例化泛型類(lèi)型的參數(shù)相同,那么JIT編輯器會(huì)重復(fù)使用該類(lèi)型,因此C#的動(dòng)態(tài)泛型能力避免了C++靜態(tài)模板可能導(dǎo)致的代碼膨脹的問(wèn)題。
2、C#泛型類(lèi)型攜帶有豐富的元數(shù)據(jù),因此C#的泛型類(lèi)型可以應(yīng)用于強(qiáng)大的反射技術(shù)。
3、C#的泛型采用“基類(lèi)、接口、構(gòu)造器,值類(lèi)型/引用類(lèi)型”的約束方式來(lái)實(shí)現(xiàn)對(duì)類(lèi)型參數(shù)的“顯示約束”,提高了類(lèi)型安全的同時(shí),也喪失了C++模板基于“簽名”的隱式約束所具有的高靈活性
.NET 中提供了很多判斷某個(gè)類(lèi)型或?qū)嵗悄硞€(gè)類(lèi)的子類(lèi)或某個(gè)接口的實(shí)現(xiàn)類(lèi)的方法,然而這事情一旦牽扯到泛型就沒(méi)那么省心了。
本文將提供判斷泛型接口實(shí)現(xiàn)或泛型類(lèi)型子類(lèi)的方法。
.NET 中沒(méi)有自帶的方法
對(duì)于實(shí)例,.NET 中提供了這些方法來(lái)判斷:
if (instance is Foo || instance is IFoo) { }
對(duì)于類(lèi)型,.NET 中提供了這些方法來(lái)判斷:
if (typeof(Foo).IsAssignableFrom(type) || typeof(IFoo).IsAssignableFrom(type)) { }
或者,如果不用判斷接口,只判斷類(lèi)型的話:
if (type.IsSubClassOf(typeof(Foo))) { }
對(duì)于 typeof 關(guān)鍵字,不止可以寫(xiě)typeof(Foo)
,還可以寫(xiě)typeof(Foo<>)
。這可以得到泛型版本的 Foo
的類(lèi)型。
不過(guò),如果你試圖拿這個(gè)泛型版本的typeof(Foo<>)
執(zhí)行上述所有判斷,你會(huì)發(fā)現(xiàn)所有的 if 條件都會(huì)是 false 。
我們需要自己編寫(xiě)方法
typeof(Foo<>)
和typeof(Foo
之間的關(guān)系就是 GetGenericTypeDefinition 函數(shù)帶來(lái)的關(guān)系。
所以我們可以充分利用這一點(diǎn)完成泛型類(lèi)型的判斷。
比如,我們要判斷接口:
public static bool HasImplementedRawGeneric(this Type type, Type generic) { // 遍歷類(lèi)型實(shí)現(xiàn)的所有接口,判斷是否存在某個(gè)接口是泛型,且是參數(shù)中指定的原始泛型的實(shí)例。 return type.GetInterfaces().Any(x => generic == (x.IsGenericType ? x.GetGenericTypeDefinition() : x)); }
而如果需要判斷類(lèi)型,那么就需要遍歷此類(lèi)的基類(lèi)了:
public static bool IsSubClassOfRawGeneric([NotNull] this Type type, [NotNull] Type generic) { if (type == null) throw new ArgumentNullException(nameof(type)); if (generic == null) throw new ArgumentNullException(nameof(generic)); while (type != null && type != typeof(object)) { isTheRawGenericType = IsTheRawGenericType(type); if (isTheRawGenericType) return true; type = type.BaseType; } return false; bool IsTheRawGenericType(Type test) => generic == (test.IsGenericType ? test.GetGenericTypeDefinition() : test); }
于是,我們可以把這兩個(gè)方法合成一個(gè),用于實(shí)現(xiàn)類(lèi)似 IsAssignableFrom 的效果,不過(guò)這回將支持原始接口(也就是typeof(Foo<>)
)。
////// 判斷指定的類(lèi)型 /// 需要測(cè)試的類(lèi)型。 /// 泛型接口類(lèi)型,傳入 typeof(IXxx<>) ///是否是指定泛型類(lèi)型的子類(lèi)型,或?qū)崿F(xiàn)了指定泛型接口。 /// 如果是泛型接口的子類(lèi)型,則返回 true,否則返回 false。 public static bool HasImplementedRawGeneric([NotNull] this Type type, [NotNull] Type generic) { if (type == null) throw new ArgumentNullException(nameof(type)); if (generic == null) throw new ArgumentNullException(nameof(generic)); // 測(cè)試接口。 var isTheRawGenericType = type.GetInterfaces().Any(IsTheRawGenericType); if (isTheRawGenericType) return true; // 測(cè)試類(lèi)型。 while (type != null && type != typeof(object)) { isTheRawGenericType = IsTheRawGenericType(type); if (isTheRawGenericType) return true; type = type.BaseType; } // 沒(méi)有找到任何匹配的接口或類(lèi)型。 return false; // 測(cè)試某個(gè)類(lèi)型是否是指定的原始接口。 bool IsTheRawGenericType(Type test) => generic == (test.IsGenericType ? test.GetGenericTypeDefinition() : test); }
以上是“.NET/C#怎么判斷某個(gè)類(lèi)是否是泛型類(lèi)型或泛型接口的子類(lèi)型”這篇文章的所有內(nèi)容,感謝各位的閱讀!希望分享的內(nèi)容對(duì)大家有幫助,更多相關(guān)知識(shí),歡迎關(guān)注創(chuàng)新互聯(lián)行業(yè)資訊頻道!