我见过很多人使用以下代码:
Type t = obj1.GetType();
if (t == typeof(int))
// Some code here
但我知道你也可以这样做:
if (obj1.GetType() == typeof(int))
// Some code here
或者这个:
if (obj1 is int)
// Some code here
就我个人而言,我觉得最后一个是最干净的,但我有什么遗漏吗?哪一个最好用,还是个人喜好?
一切都不同。
typeof采用类型名(您在编译时指定)。GetType获取实例的运行时类型。如果实例在继承树中,则返回true。
实例
class Animal { }
class Dog : Animal { }
void PrintTypes(Animal a) {
Console.WriteLine(a.GetType() == typeof(Animal)); // false
Console.WriteLine(a is Animal); // true
Console.WriteLine(a.GetType() == typeof(Dog)); // true
Console.WriteLine(a is Dog); // true
}
Dog spot = new Dog();
PrintTypes(spot);
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"
当您想在编译时获取类型时,请使用typeof。如果要在执行时获取类型,请使用GetType。很少有任何情况可以使用,因为它进行了强制转换,而且在大多数情况下,最终还是会强制转换变量。
还有第四个选项你还没有考虑(特别是如果你要将一个对象转换为你找到的类型);即用作。
Foo foo = obj as Foo;
if (foo != null)
// your code here
这只使用一个强制转换,而此方法:
if (obj is Foo)
Foo foo = (Foo)obj;
需要两个。
更新(2020年1月):
从C#7+开始,您现在可以内联转换,因此“is”方法现在也可以在一次转换中完成。
例子:
if(obj is Foo newLocalFoo)
{
// For example, you can now reference 'newLocalFoo' in this local scope
Console.WriteLine(newLocalFoo);
}
用于获取类型的System.Type对象。表达式类型采用以下形式:
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
*/
此示例使用GetType方法确定用于包含数值计算结果的类型。这取决于生成的数字的存储要求。
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
*/
如果您使用的是C#7,那么是时候更新Andrew Hare的伟大答案了。模式匹配引入了一个很好的快捷方式,它在if语句的上下文中为我们提供了一个类型化变量,而不需要单独的声明/强制转换和检查:
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...
}
编辑:根据Palec的评论,更新了较长的新方法以使用开关。
一切都不同。
typeof采用类型名(您在编译时指定)。GetType获取实例的运行时类型。如果实例在继承树中,则返回true。
实例
class Animal { }
class Dog : Animal { }
void PrintTypes(Animal a) {
Console.WriteLine(a.GetType() == typeof(Animal)); // false
Console.WriteLine(a is Animal); // true
Console.WriteLine(a.GetType() == typeof(Dog)); // true
Console.WriteLine(a is Dog); // true
}
Dog spot = new Dog();
PrintTypes(spot);
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"