总目录
前言
在 C# 中,获取 Type
对象的三种主要方式如下:
一、使用 typeof
运算符
typeof
是 C# 的内置运算符,用于在 编译时 获取指定类型的 Type
对象。它不需要对象实例,直接通过类型名即可获取。
1. 语法
Type type = typeof(类型名);
2. 特点
- 编译时绑定:在编译时确定类型,类型名称必须是已知的(如
int
、string
、自定义类型等)。 - 无法获取运行时类型:无法通过变量或对象实例获取动态类型。
- 适用场景:已知类型名称且无需运行时多态性时使用。
3. 示例
public class User { }public interface IWorker { }internal class Program
{static void Main(string[] args){// 获取内置类型的 Type 对象Type type1 = typeof(string);Console.WriteLine(type1.Name); // 输出:Stringtype1 = typeof(Int32);Console.WriteLine(type1.Name); // 输出:Int32// 获取自定义类型的 Type 对象Type type = typeof(User);Console.WriteLine(type.Name); // 输出:Usertype = 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); // 输出:Stringint 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.GetType
与 AssemblyQualifiedName
-
AssemblyQualifiedName
是类型的程序集限定名,适用于通过反射加载类型。 -
通过使用
Type.GetType
获取指定名称的类型对象的时候,需要传入AssemblyQualifiedName
完成类型的加载。 -
关于
Type.GetType
与AssemblyQualifiedName
配合使用的规则如下:- 名称A:类型的程序集限定名
=
类型的完全限定名+
程序集的强名称- 如:
MyNamespace.MyClass, MyLibrary, Version=1.0.0.0, Culture=neutral, PublicKeyToken=abcdef1234567890
- 如:
- 名称B:类型的程序集限定名
=
类型的完全限定名+
程序集的弱名称- 如:
MyNamespace.MyClass, MyLibrary
- 如:
- 名称C:类型的完全限定名
- 如:
MyNamespace.MyClass
- 如:
- 名称A:类型的程序集限定名
注:是否位于同一程序集,表示的是:需要动态加载的类型 与 当前负责加载的对象 是否位于同一程序集的时候,如程序集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"
注意事项
- 性能:反射操作(如
GetType()
或Assembly.GetType
)在频繁使用时可能影响性能,建议缓存Type
对象。 - 安全性:动态获取类型时需验证输入,防止注入攻击(如
Type.GetType
的参数可能被恶意构造)。 - 命名空间与程序集:使用
Assembly.GetType
或Type.GetType
时,确保类型名称的完全限定名正确。
通过合理选择这三种方式,可以灵活应对 C# 中类型反射的各类需求。
结语
回到目录页:C#/.NET 知识汇总
希望以上内容可以帮助到大家,如文中有不对之处,还请批评指正。