C# 类型检查:typeof、GetType或is?
我见过很多人使用以下代码:C# 类型检查:typeof、GetType或is?,c#,types,typeof,gettype,C#,Types,Typeof,Gettype,我见过很多人使用以下代码: Type t = typeof(obj1); if (t == typeof(int)) // Some code here 但我知道你也可以这样做: if (obj1.GetType() == typeof(int)) // Some code here 或者这个: if (obj1 is int) // Some code here 就我个人而言,我觉得最后一个是最干净的,但我有什么遗漏吗?哪一个是最好的选择,还是个人偏好?我相信最后
Type t = typeof(obj1);
if (t == typeof(int))
// Some code here
但我知道你也可以这样做:
if (obj1.GetType() == typeof(int))
// Some code here
或者这个:
if (obj1 is int)
// Some code here
就我个人而言,我觉得最后一个是最干净的,但我有什么遗漏吗?哪一个是最好的选择,还是个人偏好?我相信最后一个选择也会考虑遗传(例如,Dog is Animal==true),这在大多数情况下更好。这取决于我在做什么。如果我需要一个bool值(比如,确定是否转换为int),我将使用
is
。如果我确实因为某种原因需要该类型(比如,传递给其他方法),我将使用GetType()
当您想要在编译时获取该类型时,使用typeof
。要在执行时获取类型,请使用GetType
。很少有任何情况可以使用is
,因为它执行强制转换,而且在大多数情况下,您最终还是强制转换了变量
还有第四个选项您没有考虑(特别是如果您要将对象强制转换为您找到的类型);即使用作为
Foo foo = obj as Foo;
if (foo != null)
// your code here
此方法仅使用一个cast,而此方法:
if (obj is Foo)
Foo foo = (Foo)obj;
需要两个
更新(2020年1月):
- ,您现在可以内联转换,因此“is”方法现在也可以在一次转换中完成
if(obj是Foo newLocalFoo)
{
//例如,您现在可以在此本地范围中引用“newLocalFoo”
Console.WriteLine(newLocalFoo);
}
我更喜欢的是
也就是说,如果您使用的是is,那么您可能没有正确地使用继承
假设那个人是实体,那个动物是实体。Feed是实体中的虚拟方法(使Neil高兴)
班级人员
{
//一个人应该能够养活自己
//另一个实体,但他们知道他供养的方式
//每一个都是不同的
公共覆盖无效提要(实体e)
{
如果(e是人)
{
//喂我
}
否则,如果(e是动物)
{
//皱褶
}
}
}
相当于
班级人员
{
公共覆盖无效提要(人员p)
{
//喂人
}
公共饲料(动物a)
{
//喂动物
}
}
所有这些都是不同的
采用类型名称(在编译时指定)typeof
获取实例的运行时类型GetType
如果实例位于继承树中,则返回trueis
(T)的类型如何?它是否也在编译时解析 对。T始终是表达式的类型。记住,泛型方法基本上是一系列具有适当类型的方法。例如:
string Foo<T>(T parameter) { return typeof(T).Name; }
Animal probably_a_dog = new Dog();
Dog definitely_a_dog = new Dog();
Foo(probably_a_dog); // this calls Foo<Animal> and returns "Animal"
Foo<Animal>(probably_a_dog); // this is exactly the same as above
Foo<Dog>(probably_a_dog); // !!! This will not compile. The parameter expects a Dog, you cannot pass in an Animal.
Foo(definitely_a_dog); // this calls Foo<Dog> and returns "Dog"
Foo<Dog>(definitely_a_dog); // this is exactly the same as above.
Foo<Animal>(definitely_a_dog); // this calls Foo<Animal> and returns "Animal".
Foo((Animal)definitely_a_dog); // this does the same as above, returns "Animal"
stringfoo(T参数){returntypeof(T).Name;}
动物可能是新狗;
狗肯定是新狗;
福(可能是狗);//这将调用Foo并返回“Animal”
福(可能是狗);//这与上面完全相同
福(可能是狗);/!!!这将无法编译。参数需要狗,不能传入动物。
Foo(绝对是狗);//这将调用Foo并返回“Dog”
Foo(绝对是狗);//这与上面完全相同。
Foo(绝对是狗);//这将调用Foo并返回“Animal”。
Foo((动物)绝对是狗);//这与上面的操作相同,返回“Animal”
最后一个更清晰、更明显,并且还检查子类型。其他人不检查多态性。1。
Type t = typeof(obj1);
if (t == typeof(int))
if (obj1.GetType() == typeof(int))
if (obj1 is int)
这是非法的,因为typeof
只对类型有效,对变量无效。我假设obj1是一个变量。因此,通过这种方式,typeof
是静态的,它在编译时而不是运行时工作
2.
Type t = typeof(obj1);
if (t == typeof(int))
if (obj1.GetType() == typeof(int))
if (obj1 is int)
如果obj1
的类型正好是int
,则这是true
。如果obj1
源自int
,则If条件将为false
3.
Type t = typeof(obj1);
if (t == typeof(int))
if (obj1.GetType() == typeof(int))
if (obj1 is int)
如果obj1
是一个int
,或者它派生自一个名为int
的类,或者它实现了一个名为int
的接口,则这是true
Type t = typeof(obj1);
if (t == typeof(int))
// Some code here
这是一个错误。C#中的typeof运算符只能接受类型名,不能接受对象
if (obj1.GetType() == typeof(int))
// Some code here
这会起作用,但可能不像你预期的那样。对于值类型,正如您在这里所展示的,它是可以接受的,但是对于引用类型,只有当类型是完全相同的类型时,它才会返回true,而不是继承层次结构中的其他类型。例如:
class Animal{}
class Dog : Animal{}
static void Foo(){
object o = new Dog();
if(o.GetType() == typeof(Animal))
Console.WriteLine("o is an animal");
Console.WriteLine("o is something else");
}
这将打印“o是其他东西”
,因为o
的类型是Dog
,而不是Animal
。但是,如果使用Type
类的IsAssignableFrom
方法,则可以实现这一点
if(typeof(Animal).IsAssignableFrom(o.GetType())) // note use of tested type
Console.WriteLine("o is an animal");
不过,这项技术仍然存在一个主要问题。如果变量为null,则对GetType()
的调用将引发NullReferenceException。因此,要使其正常工作,您需要:
if(o != null && typeof(Animal).IsAssignableFrom(o.GetType()))
Console.WriteLine("o is an animal");
这样,您就有了is
关键字的等效行为。因此,如果这是您想要的行为,您应该使用is
关键字,它更具可读性和效率
if(o is Animal)
Console.WriteLine("o is an animal");
然而,在大多数情况下,is
关键字仍然不是您真正想要的,因为仅仅知道对象是某种类型通常是不够的。通常,您希望实际使用该对象作为该类型的实例,这也需要强制转换它。因此,您可能会发现自己在编写这样的代码:
if(o is Animal)
((Animal)o).Speak();
(o as Animal).Speak();
但这会使CLR最多检查两次对象的类型。它将对其进行一次检查,以满足is
操作员的要求,如果o
确实是动物
,我们将再次对其进行检查以验证投射
这样做更有效:
Animal a = o as Animal;
if(a != null)
a.Speak();
as
运算符是一个强制转换,如果失败,它不会抛出异常,而是返回null
。这样,CLR将检查对象的类型
00:00:02.3799048
00:00:07.1797128
System.Type type = typeof(int);
Example:
public class ExampleClass
{
public int sampleMember;
public void SampleMethod() {}
static void Main()
{
Type t = typeof(ExampleClass);
// Alternatively, you could use
// ExampleClass obj = new ExampleClass();
// Type t = obj.GetType();
Console.WriteLine("Methods:");
System.Reflection.MethodInfo[] methodInfo = t.GetMethods();
foreach (System.Reflection.MethodInfo mInfo in methodInfo)
Console.WriteLine(mInfo.ToString());
Console.WriteLine("Members:");
System.Reflection.MemberInfo[] memberInfo = t.GetMembers();
foreach (System.Reflection.MemberInfo mInfo in memberInfo)
Console.WriteLine(mInfo.ToString());
}
}
/*
Output:
Methods:
Void SampleMethod()
System.String ToString()
Boolean Equals(System.Object)
Int32 GetHashCode()
System.Type GetType()
Members:
Void SampleMethod()
System.String ToString()
Boolean Equals(System.Object)
Int32 GetHashCode()
System.Type GetType()
Void .ctor()
Int32 sampleMember
*/
class GetTypeTest
{
static void Main()
{
int radius = 3;
Console.WriteLine("Area = {0}", radius * radius * Math.PI);
Console.WriteLine("The type is {0}",
(radius * radius * Math.PI).GetType()
);
}
}
/*
Output:
Area = 28.2743338823081
The type is System.Double
*/
if (c is UserControl) c.Enabled = enable;
if (obj1 is int integerValue)
{
integerValue++;
}
Button button = obj1 as Button;
if (button != null)
{
// do stuff...
return;
}
TextBox text = obj1 as TextBox;
if (text != null)
{
// do stuff...
return;
}
Label label = obj1 as Label;
if (label != null)
{
// do stuff...
return;
}
// ... and so on
switch (obj1)
{
case Button button:
// do stuff...
break;
case TextBox text:
// do stuff...
break;
case Label label:
// do stuff...
break;
// and so on...
}