我见过很多人使用以下代码:
Type t = typeof(obj1);
if (t == typeof(int))
// Some code here
Run Code Online (Sandbox Code Playgroud)
但我知道你也可以这样做:
if (obj1.GetType() == typeof(int))
// Some code here
Run Code Online (Sandbox Code Playgroud)
或这个:
if (obj1 is int)
// Some code here
Run Code Online (Sandbox Code Playgroud)
就个人而言,我觉得最后一个是最干净的,但有什么我想念的吗?哪一个最好用,还是个人喜好?
Jim*_*mmy 1759
一切都不一样.
typeof
采用类型名称(您在编译时指定).GetType
获取实例的运行时类型.is
如果实例位于继承树中,则返回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);
Run Code Online (Sandbox Code Playgroud)
怎么样
typeof(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"
Run Code Online (Sandbox Code Playgroud)
And*_*are 182
使用typeof
时,你想获得的类型编译时间.使用GetType
时,你想要得到的类型执行时间.很少有任何情况可以使用,is
因为它是一个演员,在大多数情况下,你最终还是会转换变量.
你没有考虑过第四个选项(特别是如果你要将一个对象转换为你发现的类型); 那是用的as
.
Foo foo = obj as Foo;
if (foo != null)
// your code here
Run Code Online (Sandbox Code Playgroud)
这只使用一个演员而这种方法:
if (obj is Foo)
Foo foo = (Foo)obj;
Run Code Online (Sandbox Code Playgroud)
需要两个.
Sco*_*ham 69
1.
Type t = typeof(obj1);
if (t == typeof(int))
Run Code Online (Sandbox Code Playgroud)
这是非法的,因为typeof仅适用于类型,而不适用于变量.我假设obj1是一个变量.因此,以这种方式,typeof是静态的,并且它在编译时而不是运行时工作.
2.
if (obj1.GetType() == typeof(int))
Run Code Online (Sandbox Code Playgroud)
如果obj1完全是int类型,则为true.如果obj1派生自int,则if条件将为false.
3.
if (obj1 is int)
Run Code Online (Sandbox Code Playgroud)
如果obj1是一个int,或者它是从一个名为int的类派生,或者它实现了一个名为int的接口,那么这是真的.
P D*_*ddy 49
Type t = typeof(obj1);
if (t == typeof(int))
// Some code here
Run Code Online (Sandbox Code Playgroud)
这是一个错误.C#中的typeof运算符只能采用类型名称,而不是对象.
if (obj1.GetType() == typeof(int))
// Some code here
Run Code Online (Sandbox Code Playgroud)
这可行,但可能不如您所期望的那样.对于值类型,正如您在此处所示,它是可接受的,但对于引用类型,如果类型是完全相同的类型,它将仅返回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");
}
Run Code Online (Sandbox Code Playgroud)
这将打印"o is something else"
,因为类型o
是Dog
,没有Animal
.但是,如果使用类的IsAssignableFrom
方法,则可以使其工作Type
.
if(typeof(Animal).IsAssignableFrom(o.GetType())) // note use of tested type
Console.WriteLine("o is an animal");
Run Code Online (Sandbox Code Playgroud)
但是,这种技术仍然存在一个重大问题.如果您的变量为null,则调用GetType()
将抛出NullReferenceException.为了使其正常工作,您需要:
if(o != null && typeof(Animal).IsAssignableFrom(o.GetType()))
Console.WriteLine("o is an animal");
Run Code Online (Sandbox Code Playgroud)
有了这个,你就有了与is
关键字相同的行为.因此,如果这是您想要的行为,您应该使用is
更具可读性和更高效的关键字.
if(o is Animal)
Console.WriteLine("o is an animal");
Run Code Online (Sandbox Code Playgroud)
但在大多数情况下,is
关键字仍然不是您真正想要的,因为通常只知道对象属于某种类型是不够的.通常情况下,要真正地使用该对象作为类型,这需要铸造太的一个实例.所以你可能会发现自己编写这样的代码:
if(o is Animal)
((Animal)o).Speak();
Run Code Online (Sandbox Code Playgroud)
但这使得CLR最多检查对象的类型两次.它将检查一次以满足is
操作员,如果o
确实是Animal
,我们再次检查以验证演员.
这样做效率更高:
Animal a = o as Animal;
if(a != null)
a.Speak();
Run Code Online (Sandbox Code Playgroud)
该as
操作是,如果它失败了,而不是返回,不会抛出异常铸造null
.这样,CLR只检查对象的类型一次,之后,我们只需要进行空检查,这样效率更高.
但要注意:很多人陷入陷阱as
.因为它不会抛出异常,所以有些人会认为它是一个"安全"的演员,并且他们只使用它,避开常规演员.这会导致如下错误:
(o as Animal).Speak();
Run Code Online (Sandbox Code Playgroud)
在这种情况下,开发商显然是假设o
将永远是一个Animal
,只要他们的假设是正确的,一切工作正常.但如果他们错了,那么他们最终会得到的是一个NullReferenceException
.通过定期演员,他们会得到一个InvalidCastException
代替,这将更正确地识别问题.
有时候,这个bug很难找到:
class Foo{
readonly Animal animal;
public Foo(object o){
animal = o as Animal;
}
public void Interact(){
animal.Speak();
}
}
Run Code Online (Sandbox Code Playgroud)
这是开发商显然是期待另一种情况o
是一个Animal
每一次,但是这不是明显在构造函数中,其中as
用于铸造.直到你得到这个Interact
方法animal
才明确指定该字段.在这种情况下,不仅会导致误导性异常,而且在发生实际错误之前可能要晚得多.
综上所述:
如果您只需要知道对象是否属于某种类型,请使用is
.
如果您需要将对象视为某种类型的实例,但您不确定该对象是否属于该类型,请使用as
并检查null
.
如果您需要将对象视为特定类型的实例,并且该对象应该是该类型的对象,请使用常规强制转换.
Yah*_*ous 13
我有一个Type
属性来比较和不能使用is
(像my_type is _BaseTypetoLookFor
),但我可以使用这些:
base_type.IsInstanceOfType(derived_object);
base_type.IsAssignableFrom(derived_type);
derived_type.IsSubClassOf(base_type);
Run Code Online (Sandbox Code Playgroud)
请注意,IsInstanceOfType
并IsAssignableFrom
返回true
比较相同类型时,其中IsSubClassOf将返回false
.并且IsSubclassOf
不适用于其他两个接口的接口.(另见这个问题和答案.)
public class Animal {}
public interface ITrainable {}
public class Dog : Animal, ITrainable{}
Animal dog = new Dog();
typeof(Animal).IsInstanceOfType(dog); // true
typeof(Dog).IsInstanceOfType(dog); // true
typeof(ITrainable).IsInstanceOfType(dog); // true
typeof(Animal).IsAssignableFrom(dog.GetType()); // true
typeof(Dog).IsAssignableFrom(dog.GetType()); // true
typeof(ITrainable).IsAssignableFrom(dog.GetType()); // true
dog.GetType().IsSubclassOf(typeof(Animal)); // true
dog.GetType().IsSubclassOf(typeof(Dog)); // false
dog.GetType().IsSubclassOf(typeof(ITrainable)); // false
Run Code Online (Sandbox Code Playgroud)
Joe*_*elC 13
如果你正在使用C#7,那么现在是时候更新Andrew Hare的好答案了.模式匹配引入了一个很好的快捷方式,它在if语句的上下文中提供了一个类型变量,而不需要单独的声明/强制转换和检查:
if (obj1 is int integerValue)
{
integerValue++;
}
Run Code Online (Sandbox Code Playgroud)
对于像这样的单人演员来说,这看起来相当平庸,但是当你有很多可能的类型进入你的日常生活时,真的很闪耀.以下是避免施放两次的旧方法:
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
Run Code Online (Sandbox Code Playgroud)
尽可能地缩小这些代码,以及避免重复使用同一个对象,这一直困扰着我.上面的模式匹配很好地压缩到以下:
switch (obj1)
{
case Button button:
// do stuff...
break;
case TextBox text:
// do stuff...
break;
case Label label:
// do stuff...
break;
// and so on...
}
Run Code Online (Sandbox Code Playgroud)
编辑:根据Palec的评论更新了使用开关的更长的新方法.
我更喜欢的是
也就是说,如果您使用的是,那么您可能无法正确使用继承.
假设Person:Entity和那个Animal:Entity.Feed是实体中的虚拟方法(让Neil高兴)
class Person
{
// A Person should be able to Feed
// another Entity, but they way he feeds
// each is different
public override void Feed( Entity e )
{
if( e is Person )
{
// feed me
}
else if( e is Animal )
{
// ruff
}
}
}
Run Code Online (Sandbox Code Playgroud)
宁
class Person
{
public override void Feed( Person p )
{
// feed the person
}
public override void Feed( Animal a )
{
// feed the animal
}
}
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
928290 次 |
最近记录: |