当前位置: 首页 > news >正文

C# 获取Type对象的方式

总目录


前言

在 C# 中,获取 Type 对象的三种主要方式如下:


一、使用 typeof 运算符

typeof 是 C# 的内置运算符,用于在 编译时 获取指定类型的 Type 对象。它不需要对象实例,直接通过类型名即可获取。

1. 语法

Type type = typeof(类型名);

2. 特点

  • 编译时绑定:在编译时确定类型,类型名称必须是已知的(如 intstring、自定义类型等)。
  • 无法获取运行时类型:无法通过变量或对象实例获取动态类型。
  • 适用场景:已知类型名称且无需运行时多态性时使用。

3. 示例

public class User { }

public interface IWorker { }

internal class Program
{
    static void Main(string[] args)
    {
        // 获取内置类型的 Type 对象
        Type type1 = typeof(string);
        Console.WriteLine(type1.Name); // 输出:String

        type1 = typeof(Int32);
        Console.WriteLine(type1.Name); // 输出:Int32

        // 获取自定义类型的 Type 对象
        Type type = typeof(User);
        Console.WriteLine(type.Name); // 输出:User

        type = typeof(IWorker);
        Console.WriteLine(type.Name); // 输出:IWorker   
    }
}

4. 注意事项

  • 参数必须是类型名称:不能传入变量或对象实例。例如:
    int num = 42;
    Type type = typeof(num); // 错误!typeof 的参数必须是类型名,而非变量名
    
  • 泛型支持:可以直接获取泛型类型:
    Type listType = typeof(List<int>); // 获取 List<int> 的 Type 对象
    

二、对象的 GetType() 方法

GetType()System.Object 类的虚方法,所有对象都继承自它。它返回对象在 运行时 的实际类型。

1. 语法

Type type = 对象实例.GetType();

2. 特点

  • 运行时绑定:返回对象的实际类型,支持多态。例如,基类引用指向派生类实例时,GetType() 会返回派生类的 Type
  • 需要对象实例:必须通过对象实例调用。
  • 适用场景:需要动态获取对象的运行时类型时使用。

3. 示例

using System;

public class User { }

class Program
{
    static void Main()
    {
    	// 自定义类型 示例
        User user = new User();
        Type typeFromInstance = user.GetType();
        Console.WriteLine(typeFromInstance.Name); // 输出:User

		// 内置类型 示例
        string str = "hello";
        Type typeFromInstance2 = str.GetType();
        Console.WriteLine(typeFromInstance2.Name); // 输出:String

        int num = 32;
        Type typeFromInstance3 = num.GetType();
        Console.WriteLine(typeFromInstance3.Name); // 输出:Int32
    }
}

4. 注意事项

  • 多态性:返回对象的实际运行时类型,而非声明类型。
  • 空对象:如果对象为 null,调用 GetType() 会抛出 NullReferenceException

三、通过 Assembly.GetType()Type.GetType()

通过程序集(Assembly)的 GetType 方法或 Type.GetType 静态方法,根据 字符串类型的全名 动态获取 Type 对象。这种方式在运行时动态加载类型时非常有用。

1. 语法

// 通过程序集获取
Assembly assembly = Assembly.GetExecutingAssembly();
Type type = assembly.GetType("命名空间.类型名称");

// 通过 Type.GetType 静态方法
Type type = Type.GetType("命名空间.类型名称, 程序集名称");

2. 特点

  • 运行时动态获取:通过字符串名称查找类型,支持延迟绑定。
  • 需要全名:类型名称必须包含完整的命名空间和程序集信息(如 "System.String""MyNamespace.MyClass, MyAssembly")。
  • 适用场景:在插件系统、配置加载或反射序列化等场景中动态加载类型。

3. 示例

// 示例1:获取当前程序集中的类型
Assembly currentAssembly = Assembly.GetExecutingAssembly();
// 需要完全限定名(命名空间.类型名)
Type personType = currentAssembly.GetType("TestNamespace.Person"); 
// 示例2:使用 Type.GetType(需指定程序集名称)
Type stringType = Type.GetType("System.String"); // 成功
Type unknownType = Type.GetType("NonExistentType"); // 返回 null

4. 注意事项

  • 完全限定名:必须提供完整的命名空间和程序集名称(如 "MyClass, MyAssembly")。
  • 程序集加载:如果类型不在当前程序集中,需先加载对应的程序集。
  • 返回值为 null:如果类型不存在或名称不正确,返回 null,需处理空值。

5. Type.GetTypeAssemblyQualifiedName

  • AssemblyQualifiedName 是类型的程序集限定名,适用于通过反射加载类型。

  • 通过使用Type.GetType 获取指定名称的类型对象的时候,需要传入 AssemblyQualifiedName 完成类型的加载。

  • 关于Type.GetTypeAssemblyQualifiedName 配合使用的规则如下:

    • 名称A:类型的程序集限定名=类型的完全限定名+程序集的名称
      • 如:MyNamespace.MyClass, MyLibrary, Version=1.0.0.0, Culture=neutral, PublicKeyToken=abcdef1234567890
    • 名称B:类型的程序集限定名=类型的完全限定名+程序集的名称
      • 如:MyNamespace.MyClass, MyLibrary
    • 名称C:类型的完全限定名
      • 如:MyNamespace.MyClass
加载类型时
是否要求
程序集强名称
使用 名称A
是否位于
同一程序集内
使用 名称B/C
使用 名称B

注:是否位于同一程序集,表示的是:需要动态加载的类型 与 当前负责加载的对象 是否位于同一程序集的时候,如程序集A 中有类型AClass,程序集B中需要动态加载程序集A中的AClass,这种情况属于不在同一程序集内。

四、 三种方式的对比总结

方法是否需要实例运行时/编译时多态性支持适用场景
typeof编译时已知类型且无需动态类型
GetType()运行时需要对象实际运行时类型
Assembly.GetType()

Type.GetType()
运行时动态加载类型(如插件系统)

五、实际应用示例

场景1:类型检查

object obj = "Hello";
if (obj.GetType() == typeof(string)) // 结合 GetType() 和 typeof()
{
    Console.WriteLine("对象是字符串类型");
}

场景2:动态创建对象

string typeName = "System.String";
Type type = Type.GetType(typeName);
if (type != null)
{
    object instance = Activator.CreateInstance(type); // 创建字符串实例
}

场景3:反射调用方法

Type type = typeof(string);
MethodInfo method = type.GetMethod("Substring", new Type[] { typeof(int) });
string result = (string)method.Invoke("Hello", new object[] { 2 }); // 输出 "llo"

注意事项

  1. 性能:反射操作(如 GetType()Assembly.GetType)在频繁使用时可能影响性能,建议缓存 Type 对象。
  2. 安全性:动态获取类型时需验证输入,防止注入攻击(如 Type.GetType 的参数可能被恶意构造)。
  3. 命名空间与程序集:使用 Assembly.GetTypeType.GetType 时,确保类型名称的完全限定名正确。

通过合理选择这三种方式,可以灵活应对 C# 中类型反射的各类需求。


结语

回到目录页:C#/.NET 知识汇总
希望以上内容可以帮助到大家,如文中有不对之处,还请批评指正。

相关文章:

  • 本周安全速报(2025.3.11~3.17)
  • 依赖倒置 DIP、依赖注入 DI、控制反转 IoC 和工厂模式
  • 算法备案全景洞察趋势解码:技术迭代、行业裂变与生态重构
  • IP关联对跨境电商的影响及如何防范措施?
  • Arduino开发ESP8266环境搭建
  • LeetCode[19]删除链表的倒数第N个节点
  • 【Go语言圣经3.1】
  • 《Python深度学习》第一讲:深度学习基础
  • uniapp APP权限弹框
  • 高级java每日一道面试题-2025年3月04日-微服务篇[Eureka篇]-Eureka是什么?
  • 卷积神经网络 - 基本概念
  • 【玩转正则表达式】Python、Go、Java正则表达式解释器的差异解析(附示例)
  • 【Mac 从 0 到 1 保姆级配置教程 08】08. 快速配置 Neovim、LazyVim 以及常用开发环境,如果之前有人这么写就好了
  • 算法刷题记录——LeetCode篇(10) [第901~1000题](持续更新)
  • MySQL:Ubuntu下安装MySQL 8.0记录
  • Maya的操作基础教学
  • Redis--渐进式遍历
  • 应急响应靶场练习-Web1
  • tensorflow与torch并行读取数据机制
  • C盘清理终极方案——基于Windows软连接的目录迁移实战
  • 5月起,这些新规将施行
  • 金砖国家外长会晤落幕,外交部:发出了反对单边霸凌行径的“金砖声音”
  • 来伊份一季度净利减少近八成,今年集中精力帮助加盟商成功
  • 人到中年为何腰围变粗?科学家发现腹部脂肪增加的细胞元凶
  • 君亭酒店:2024年营业收入约6.76亿元, “酒店行业传统增长模式面临巨大挑战”
  • 深圳宝安区一宗涉宅用地中止出让,起始总价86.27亿元