C# is vs typeof

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/184681/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-03 17:02:03  来源:igfitidea点击:

is vs typeof

c#rtti

提问by ilitirit

Which of these pieces of code is faster?

这些代码中哪一个更快?

if (obj is ClassA) {}

if (obj.GetType() == typeof(ClassA)) {}

Edit: I'm aware that they don't do the same thing.

编辑:我知道他们不做同样的事情。

采纳答案by MagicKat

This should answer that question, and then some.

这应该回答这个问题,然后是一些。

The second line, if (obj.GetType() == typeof(ClassA)) {}, is faster, for those that don't want to read the article.

第二行,if (obj.GetType() == typeof(ClassA)) {},对于那些不想阅读文章的人来说更快。

(Be aware that they don't do the same thing)

(请注意,他们不做同样的事情)

回答by tvanfosson

They don't do the same thing. The first one works if obj is of type ClassA or of some subclass of ClassA. The second one will only match objects of type ClassA. The second one will be faster since it doesn't have to check the class hierarchy.

他们不做同样的事情。如果 obj 是 ClassA 类型或 ClassA 的某个子类,则第一个有效。第二个将只匹配 ClassA 类型的对象。第二个会更快,因为它不必检查类层次结构。

For those who want to know the reason, but don't want to read the article referenced in is vs typeof.

对于那些想知道原因,但又不想阅读 中引用的文章的人 is vs typeof

回答by Jay Bazuzi

Does it matter which is faster, if they don't do the same thing? Comparing the performance of statements with different meaning seems like a bad idea.

如果他们不做同样的事情,哪个更快是否重要?比较具有不同含义的语句的性能似乎是一个坏主意。

istells you if the object implements ClassAanywhere in its type heirarchy. GetType()tells you about the most-derived type.

is告诉您对象是否ClassA在其类型层次结构中的任何位置实现。 GetType()告诉你最派生的类型。

Not the same thing.

不是一回事。

回答by nawfal

I did some benchmarking where they do the same - sealed types.

我做了一些基准测试,他们做同样的事情 - 密封类型。

var c1 = "";
var c2 = typeof(string);
object oc1 = c1;
object oc2 = c2;

var s1 = 0;
var s2 = '.';
object os1 = s1;
object os2 = s2;

bool b = false;

Stopwatch sw = Stopwatch.StartNew();
for (int i = 0; i < 10000000; i++)
{
    b = c1.GetType() == typeof(string); // ~60ms
    b = c1 is string; // ~60ms

    b = c2.GetType() == typeof(string); // ~60ms
    b = c2 is string; // ~50ms

    b = oc1.GetType() == typeof(string); // ~60ms
    b = oc1 is string; // ~68ms

    b = oc2.GetType() == typeof(string); // ~60ms
    b = oc2 is string; // ~64ms


    b = s1.GetType() == typeof(int); // ~130ms
    b = s1 is int; // ~50ms

    b = s2.GetType() == typeof(int); // ~140ms
    b = s2 is int; // ~50ms

    b = os1.GetType() == typeof(int); // ~60ms
    b = os1 is int; // ~74ms

    b = os2.GetType() == typeof(int); // ~60ms
    b = os2 is int; // ~68ms


    b = GetType1<string, string>(c1); // ~178ms
    b = GetType2<string, string>(c1); // ~94ms
    b = Is<string, string>(c1); // ~70ms

    b = GetType1<string, Type>(c2); // ~178ms
    b = GetType2<string, Type>(c2); // ~96ms
    b = Is<string, Type>(c2); // ~65ms

    b = GetType1<string, object>(oc1); // ~190ms
    b = Is<string, object>(oc1); // ~69ms

    b = GetType1<string, object>(oc2); // ~180ms
    b = Is<string, object>(oc2); // ~64ms


    b = GetType1<int, int>(s1); // ~230ms
    b = GetType2<int, int>(s1); // ~75ms
    b = Is<int, int>(s1); // ~136ms

    b = GetType1<int, char>(s2); // ~238ms
    b = GetType2<int, char>(s2); // ~69ms
    b = Is<int, char>(s2); // ~142ms

    b = GetType1<int, object>(os1); // ~178ms
    b = Is<int, object>(os1); // ~69ms

    b = GetType1<int, object>(os2); // ~178ms
    b = Is<int, object>(os2); // ~69ms
}

sw.Stop();
MessageBox.Show(sw.Elapsed.TotalMilliseconds.ToString());

The generic functions to test for generic types:

用于测试泛型类型的泛型函数:

static bool GetType1<S, T>(T t)
{
    return t.GetType() == typeof(S);
}
static bool GetType2<S, T>(T t)
{
    return typeof(T) == typeof(S);
}
static bool Is<S, T>(T t)
{
    return t is S;
}

I tried for custom types as well and the results were consistent:

我也尝试了自定义类型,结果是一致的:

var c1 = new Class1();
var c2 = new Class2();
object oc1 = c1;
object oc2 = c2;

var s1 = new Struct1();
var s2 = new Struct2();
object os1 = s1;
object os2 = s2;

bool b = false;

Stopwatch sw = Stopwatch.StartNew();
for (int i = 0; i < 10000000; i++)
{
    b = c1.GetType() == typeof(Class1); // ~60ms
    b = c1 is Class1; // ~60ms

    b = c2.GetType() == typeof(Class1); // ~60ms
    b = c2 is Class1; // ~55ms

    b = oc1.GetType() == typeof(Class1); // ~60ms
    b = oc1 is Class1; // ~68ms

    b = oc2.GetType() == typeof(Class1); // ~60ms
    b = oc2 is Class1; // ~68ms


    b = s1.GetType() == typeof(Struct1); // ~150ms
    b = s1 is Struct1; // ~50ms

    b = s2.GetType() == typeof(Struct1); // ~150ms
    b = s2 is Struct1; // ~50ms

    b = os1.GetType() == typeof(Struct1); // ~60ms
    b = os1 is Struct1; // ~64ms

    b = os2.GetType() == typeof(Struct1); // ~60ms
    b = os2 is Struct1; // ~64ms


    b = GetType1<Class1, Class1>(c1); // ~178ms
    b = GetType2<Class1, Class1>(c1); // ~98ms
    b = Is<Class1, Class1>(c1); // ~78ms

    b = GetType1<Class1, Class2>(c2); // ~178ms
    b = GetType2<Class1, Class2>(c2); // ~96ms
    b = Is<Class1, Class2>(c2); // ~69ms

    b = GetType1<Class1, object>(oc1); // ~178ms
    b = Is<Class1, object>(oc1); // ~69ms

    b = GetType1<Class1, object>(oc2); // ~178ms
    b = Is<Class1, object>(oc2); // ~69ms


    b = GetType1<Struct1, Struct1>(s1); // ~272ms
    b = GetType2<Struct1, Struct1>(s1); // ~140ms
    b = Is<Struct1, Struct1>(s1); // ~163ms

    b = GetType1<Struct1, Struct2>(s2); // ~272ms
    b = GetType2<Struct1, Struct2>(s2); // ~140ms
    b = Is<Struct1, Struct2>(s2); // ~163ms

    b = GetType1<Struct1, object>(os1); // ~178ms
    b = Is<Struct1, object>(os1); // ~64ms

    b = GetType1<Struct1, object>(os2); // ~178ms
    b = Is<Struct1, object>(os2); // ~64ms
}

sw.Stop();
MessageBox.Show(sw.Elapsed.TotalMilliseconds.ToString());

And the types:

和类型:

sealed class Class1 { }
sealed class Class2 { }
struct Struct1 { }
struct Struct2 { }

Inference:

推理:

  1. Calling GetTypeon structs is slower.GetTypeis defined on objectclass which can't be overridden in sub types and thus structs need to be boxed to be called GetType.

  2. On an object instance, GetTypeis faster, but very marginally.

  3. On generic type, if Tis class, then isis much faster. If Tis struct, then isis much faster than GetTypebut typeof(T)is much faster than both.In cases of Tbeing class, typeof(T)is not reliable since its different from actual underlying type t.GetType.

  1. 调用GetTypestructs是慢。GetType定义在object不能在子类型中覆盖的类上,因此structs 需要装箱才能被调用GetType

  2. 在对象实例上,GetType速度更快,但非常有限。

  3. 在泛型类型上,如果Tclass,那么is要快得多。如果Tstruct,则比两者is快得多,GetTypetypeof(T)比两者都快得多。在案件T之中classtypeof(T)是不是因为从实际的基本类型及其不同的可靠t.GetType

In short, if you have an objectinstance, use GetType. If you have a generic classtype, use is. If you have a generic structtype, use typeof(T). If you are unsure if generic type is reference type or value type, use is. If you want to be consistent with one style always (for sealed types), use is..

简而言之,如果您有object实例,请使用GetType. 如果您有泛型class类型,请使用is. 如果您有泛型struct类型,请使用typeof(T). 如果您不确定泛型类型是引用类型还是值类型,请使用is. 如果您想始终与一种样式保持一致(对于密封类型),请使用is..