前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
社区首页 >专栏 >.NET/C# 判断某个类是否是泛型类型或泛型接口的子类型

.NET/C# 判断某个类是否是泛型类型或泛型接口的子类型

作者头像
walterlv
发布于 2018-09-18 03:29:55
发布于 2018-09-18 03:29:55
4.3K00
代码可运行
举报
运行总次数:0
代码可运行

.NET/C# 判断某个类是否是泛型类型或泛型接口的子类型

2018-09-01 08:28

.NET 中提供了很多判断某个类型或实例是某个类的子类或某个接口的实现类的方法,然而这事情一旦牵扯到泛型就没那么省心了。

本文将提供判断泛型接口实现或泛型类型子类的方法。


.NET 中没有自带的方法

对于实例,.NET 中提供了这些方法来判断:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
if (instance is Foo || instance is IFoo)
{
}

对于类型,.NET 中提供了这些方法来判断:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
if (typeof(Foo).IsAssignableFrom(type) || typeof(IFoo).IsAssignableFrom(type))
{
}

或者,如果不用判断接口,只判断类型的话:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
if (type.IsSubClassOf(typeof(Foo)))
{
}

对于 typeof 关键字,不止可以写 typeof(Foo),还可以写 typeof(Foo<>)。这可以得到泛型版本的 Foo<T> 的类型。

不过,如果你试图拿这个泛型版本的 typeof(Foo<>) 执行上述所有判断,你会发现所有的 if 条件都会是 false

我们需要自己编写方法

typeof(Foo<>)typeof(Foo<SomeClass>) 之间的关系就是 GetGenericTypeDefinition 函数带来的关系。

所以我们可以充分利用这一点完成泛型类型的判断。

比如,我们要判断接口:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
public static bool HasImplementedRawGeneric(this Type type, Type generic)
{
    // 遍历类型实现的所有接口,判断是否存在某个接口是泛型,且是参数中指定的原始泛型的实例。
    return type.GetInterfaces().Any(x => generic == (x.IsGenericType ? x.GetGenericTypeDefinition() : x));
}

而如果需要判断类型,那么就需要遍历此类的基类了:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
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);
}

于是,我们可以把这两个方法合成一个,用于实现类似 IsAssignableFrom 的效果,不过这回将支持原始接口(也就是 typeof(Foo<>))。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
/// <summary>
/// 判断指定的类型 <paramref name="type"/> 是否是指定泛型类型的子类型,或实现了指定泛型接口。
/// </summary>
/// <param name="type">需要测试的类型。</param>
/// <param name="generic">泛型接口类型,传入 typeof(IXxx&lt;&gt;)</param>
/// <returns>如果是泛型接口的子类型,则返回 true,否则返回 false。</returns>
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));

    // 测试接口。
    var isTheRawGenericType = type.GetInterfaces().Any(IsTheRawGenericType);
    if (isTheRawGenericType) return true;

    // 测试类型。
    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);
}

本文会经常更新,请阅读原文: https://walterlv.com/post/is-subclass-of-raw-generic-or-implemented-raw-generic.html ,以避免陈旧错误知识的误导,同时有更好的阅读体验。

本作品采用 知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议 进行许可。欢迎转载、使用、重新发布,但务必保留文章署名 吕毅 (包含链接: https://walterlv.com ),不得用于商业目的,基于本文修改后的作品务必以相同的许可发布。如有任何疑问,请 与我联系 (walter.lv@qq.com)

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2018-09-01 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
浅谈泛型
我们在写一些通用库的时候,经常需要写一个算法,比如交换,搜索,比较,排序,转换等算法,但是需要支持int,string等多种类型。通常我们可能会把代码复制多遍分别处理不同类型的数据。有没有一种办法,让我们只写一遍算法的实现,就可以支持所有类型的数据?泛型(generic)是C#提供的一种机制,它可以提供这种形式的代码重用,即“算法重用”。简单来说,开发人员在定义算法的时候并不设定算法操作的数据类型,而是在使用这个算法的时候再指定具体的数据类型。大多数算法都封装在一个类型中,CLR允许创建泛型引用类型和泛型值类型,以及泛型接口和泛型委托。所以CLR允许在类或接口中定义泛型方法。来看一个简单例子,Framework类库定义了一个泛型列表算法,它知道如何管理对象集合。泛型算法没有设定数据的类型。要在使用这个泛型列表算法时指定具体的数据类型。封装了泛型列表算法的FCL类称为List<T>。这个类是System.Collections.Generic命名空间中定义的。下面展示了类的定义:
小蜜蜂
2019/07/14
1.1K0
java泛型总结
泛型类型用于类的定义中,被称为泛型类。通过泛型可以完成对一组类的操作对外开放相同的接口。最典型的就是各种容器类,如:List、Set、Map。
earthchen
2020/09/24
3240
CA1010:集合应实现泛型接口
类型实现 System.Collections.IEnumerable 接口,但不能实现 System.Collections.Generic.IEnumerable<T> 接口和包含程序集的目标 .NET。 此规则会忽略能够实现 System.Collections.IDictionary 的类型。
用户4268038
2022/01/10
6120
C#泛型
泛型(Generic) 是C# 2.0中的新增元素。这种机制允许将类名作为参数传递给泛型类型,并生成相应的对象。将泛型(包括类、接口、方法等)看作模板可能更好理解,模板中的变体部分将被作为参数传进来的类名称所代替,从而得到一个新的类型定义。   通过泛型可以定义类型安全类,而不会损害类型安全、性能或工作效率。您只须一次性地将服务器实现为一般服务器,同时可以用任何类型来声明和使用它。为此,需要使用 <和 > 括号,以便将一般类型参数括起来。 List<string> list = new List<strin
拾点阳光
2018/05/10
1.7K0
C#反射与特性(九):全网最全-解析反射
C# 中的访问修饰符:public、private、protected、internal、protected internal。
痴者工良
2021/04/26
2K0
From Java To Kotlin 2:Kotlin 类型系统与泛型终于懂了
上期主要分享了 From Java To Kotlin 1 :空安全、扩展、函数、Lambda。
Seachal
2023/06/06
4720
From Java To Kotlin 2:Kotlin 类型系统与泛型终于懂了
使用 C# 9 的records作为强类型ID - 路由和查询参数
但是在强类型id真正可用之前,还有一些问题需要解决,比如,ASP.NET Core并不知道如何在路由参数或查询字符串参数中正确的处理它们,在这篇文章中,我将展示如何解决这个问题。
全球技术精选
2021/01/21
1.9K0
使用 C# 9 的records作为强类型ID - 路由和查询参数
理解C#泛型运作原理
我们都知道泛型在C#的重要性,泛型是OOP语言中三大特征的多态的最重要的体现,几乎泛型撑起了整个.NET框架,在讲泛型之前,我们可以抛出一个问题,我们现在需要一个可扩容的数组类,且满足所有类型,不管是值类型还是引用类型,那么在没有用泛型方法实现,如何实现?
ryzenWzd
2021/03/07
7170
C#的泛型接口
在C#中,泛型接口是泛型编程的核心构建块之一。它们允许开发者定义与特定类型无关的操作方法,从而提高代码的重用性和灵活性。泛型接口在.NET框架中广泛应用,特别是在集合、委托和事件处理等方面。本文将深入探讨C#中的泛型接口,包括它们的基本概念、实现方式、高级用法和最佳实践。
Michel_Rolle
2024/10/08
2.5K0
C#反射与特性(二):探究反射
在上一章中,我们探究了 C# 引入程序集的各种方法,这一章节笔者将探究 C# 中使用反射的各种操作和代码实践。
痴者工良
2021/04/26
1.6K0
Java基础11:Java泛型详解
这是一位阿里 Java 工程师的技术小站,作者黄小斜,专注 Java 相关技术:SSM、SpringBoot、MySQL、分布式、中间件、集群、Linux、网络、多线程,偶尔讲点Docker、ELK,同时也分享技术干货和学习经验,致力于Java全栈开发!(关注公众号后回复”资料“即可领取 3T 免费技术学习资源以及我我原创的程序员校招指南、Java学习指南等资源)
程序员黄小斜
2019/04/07
4990
揭开Java 泛型类型擦除神秘面纱
大家可能会有疑问,我为什么叫做泛型是一个守门者。这其实是我个人的看法而已,我的意思是说泛型没有其看起来那么深不可测,它并不神秘与神奇。泛型是 Java 中一个很小巧的概念,但同时也是一个很容易让人迷惑的知识点,它让人迷惑的地方在于它的许多表现有点违反直觉。
java思维导图
2018/10/24
1.3K0
揭开Java 泛型类型擦除神秘面纱
C#反射与特性(三):反射类型的成员
本篇文章中,将使用 Type 去获取成员信息,通过打印出反射获取到的信息,为后续操作反射打好基础。
痴者工良
2021/04/26
1.1K0
.NET面试题系列[8] - 泛型
“可变性是以一种类型安全的方式,将一个对象作为另一个对象来使用。“ - Jon Skeet
s055523
2018/09/14
7300
[深入解析C#] 泛型
使用泛型(generic),可以编写在编译时类型安全的通用代码,无须事先知道要使用的具体类型,即可在不同位置表示相同类型。在引入之初,泛型主要用于集合。如今,泛型已经广泛应用于C#的各个领域,其中用得较多的有如下几项:
科控物联
2022/03/29
1.6K0
[深入解析C#] 泛型
小工具 --- 树形展示多属性复杂结构类
最近在做配置模块,然后整个配置的参数是非常多的,层级结构也很深。可能有几百个参数,三、四层的层级关系,想要捋顺所有的类和参数,太繁琐了,而且 Visual Studio 的类视图只能看到属性,却看不出层级关系来,所以花费些许精力,写一个控制台小程序,展示类结构。
Niuery Diary
2023/10/22
1660
小工具 --- 树形展示多属性复杂结构类
C# 中关于 T 泛型
C# 里面的泛型不仅可以使用泛型函数、泛型接口,也可以使用泛型类、泛型委托等等。在使用泛型的时候,它们会自行检测你传入参数的类型,因此它可以为我们省去大量的时间,不用一个个编写方法的重载。与此同时,使用泛型会提升程序的效率。
郑子铭
2023/08/30
3880
C# 中关于 T 泛型
Java进阶:【泛型】认识泛型,泛型方法,泛型类,泛型接口和通配符
例如关于这个元素如何保存,如何管理等是确定的,因此此时把元素的类型设计成一个参数,这个类型参数叫做泛型。
冷环渊
2021/11/29
3.5K0
Java进阶:【泛型】认识泛型,泛型方法,泛型类,泛型接口和通配符
泛型接口,泛型类和泛型通配符
泛型的使用位置,除了最常见的约束集合元素,还可以使用在接口,类,方法上面。最本质的原因就是为了在使用接口,类,方法的时候,可以将类型作为参数,进行类型的参数传递。这样可以使程序的编写更加的灵活,在创建对象,调用方法的时候动态的指定类型,所以泛型也可以理解为类型的参数化。
用户5745563
2019/07/04
2.4K0
泛型接口,泛型类和泛型通配符
C#基础篇——泛型
在开发编程中,我们经常会遇到功能非常相似的功能模块,只是他们的处理的数据不一样,所以我们会分别采用多个方法来处理不同的数据类型。但是这个时候,我们就会想一个问题,有没有办法实现利用同一个方法来传递不同种类型的参数呢?
zls365
2021/04/23
1.3K0
C#基础篇——泛型
相关推荐
浅谈泛型
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
查看详情【社区公告】 技术创作特训营有奖征文