简体   繁体   中英

If you need no casting, and you need to check the most specific (runtime) type of an object, which is faster? .GetType() & typeof(), or is operator?

1) .GetType() will return the runtime type of the object on which it is called, which is the most specific type in the inheritance hierarchy. You can use the typeof() function to get a Type for a classname
2) The is operator will check whether the type of the left hand side object is a subtype of, or the same type as the type specified on the right hand side
3) Given that you only need to check the most specific type of an object, and you need no casting, is the former (1) considerably faster than the latter (2)?
4) Does the is operator actually perform casting and checks for null, or this behaviour have been modified in a later version of C Sharp?

typeof(x) is to get a Type-Object of a type Literal, like typeof(int) . It's a runtime constant.

For object.GetType() you need an object instance.

 if (x is IList)

The is operator does a casting, but returns bool on success, or false, if x is null or an incompatible type. With

 if (x is IList list)

You can do the boolean test and the casting at the same time.

It does not make sense, to talk about performance, cause that are completly different operations.

if you want to get the type of an object instance object.GetType() is your only option, but you can test it agains a type literal like

 x.GetType() == typeof(List)

While you can be sure

 x.GetType() == typeof(IList)

will always be false, since GetType will never return the type of an interface. For this test you would need

typeof(IList).IsAssignableFrom(x.GetType());

First 4) as it's simpler. The is operator is implemented with the as operator.

x is C

is the same as

x as C != null

For the source you can look at the fabulous Eric Lippert's blog . Currently (commit e09c42a), the Roslyn compiler translates both to

isinst C
ldnull
cgt.un

Where isinst is the magic instruction that tries to cast x to C and leaves the casted reference on top of the stack, or null if it fails. The remaining two instructions are the check for null .

As for performance, it's hard to say definitely. In theory, checking with is should be faster, as it's a built-in CLR instruction that's heavily optimized for what it does, while the other check has to call three methods, the GetType() , GetTypeFromHandle(RuntimeTypeHandle) and the equality on Type . There's also the standard check-for-null-and-throw-NRE involved with calling the GetType() . A very crude benchmark supports this hypothesis: link to DotNetFiddle . If someone is willing to perform a more sophisticated benchmark, go ahead.

Obviously I can imagine you could have an inheritance hierarchy so deep and complicated the is check will take longer than any overhead of GetType() ever could. Feel free to subtype my benchmark up to C100 and check if that's enough :)

EDIT: I think I should add that this discussion is purely theoretical. In production code you should use x is C , as it's concise and more robust since it checks the entire hierarchy for subtyping. If you have a hot path that checks a given instance's type and you know for a fact that the hierarchy is flat, you probably should redesign the system to avoid that check instead of uglifying the code to squeeze out some performance.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM