What is a better way to check that a given object is a particular value type? [closed]
Asked Answered
M

2

2

Below are the 2 commonly used approaches to check before unbox.

myObject.GetType() == typeof(MyValueType)

IL_0001:  callvirt    System.Object.GetType
IL_0006:  ldtoken     UserQuery.MyValueType
IL_000B:  call        System.Type.GetTypeFromHandle
IL_0010:  call        System.Type.op_Equality


myObject is MyValueType

IL_0001:  isinst      UserQuery.MyValueType

Plus, I am wondering why C# calls System.Type.op_Equality instead of ceq Isn't that reference equality check?

Update

Actually, there is a 3rd way. (from C# 5.0 in a Nutshell)

MyValueType? x = myObject as MyValueType?;

Then check x.HasValue and use x.Value

Which one of the 3 would you use?

Moureaux answered 13/7, 2013 at 21:30 Comment(2)
Flip a three-sided coin?Frosty
Which one would I use? Certainly myObject is MyValueType. That's what the is keyword is there for. I have faith that the compiler will choose a gode translation of it. Side note: With a value type, the two forms give the same result. But in other cases there's a difference, of course. For example myObject is IDisposable works fine while myObject.GetType() could never give an interface type or an abstract class. Another example, myObject is Func<object> will give true for a Func<string> even if the type Func<> is a sealed type. Covariance.Buckman
H
4

I am wondering why C# calls System.Type.op_Equality instead of ceq.

Because types are compared by value, not by reference. There could be two type objects in memory that refer to the same type.

Which one of the three would you use?

If you want to know whether an instance is of a particular type, there is an operator specifically designed to solve that problem and that problem alone: is. Why would you ever not use the tool that was specifically designed to solve your problem? If you're replacing a roof and you have a choice between a roofing hatchet and a hammer, I hope you would use the roofing hatchet.

Now, if you need to both do a type test and obtain the value then I would be inclined to use as because that is the operator specifically designed to solve that problem.

Hurlyburly answered 14/7, 2013 at 15:1 Comment(6)
I thought that is is designed to solve if an instance is "compatible" with a given type, whereas GetType() is for that the types are actually identical. In this case since the type is sealed so the 2 give the same result. However, I felt that is is a bit of overuse.Moureaux
By using as I must also bring in Nullable, wouldn't that be a bit overuse as well? Does it weight cheaper than is + unboxing ?Moureaux
From MSDN msdn.microsoft.com/en-us/library/system.type.aspx " Type object that represents a type is unique; that is, two Type object references refer to the same object if and only if they represent the same type. This allows for comparison of Type objects using reference equality" So it says reference equalityMoureaux
@colinfang: Your question was not which is cheaper, your question was which one would you use? I answered the question you asked. If you want to know the answer to which one is cheaper: write the code both ways, run it both ways, measure the expense, and then you'll know which one is cheaper.Hurlyburly
@colinfang: Type objects provided by the CLR guarantee reference equality. Remember, Type is unsealed; if you want to create your own Type objects, you are not required to enforce reference equality (though doing so is a good idea.) Therefore the C# compiler does not attempt to optimize equality operations on types down to reference equality; the op_Equality method will check for reference equality.Hurlyburly
Note that it is highly unlikely that the performance of this operation will be of relevance in your benchmarks. Presumably other code will run in response to determining the type of your object, and that code will almost always be more expensive than answering the type question.Yumuk
T
0

If an overloaded == operator exists it is being preferred. If not, what would be the point of it?

Besides of doing the measurement to find out what is faster, I think the type equality check will be faster because the JIT contains a special optimization that recognizes this pattern and optimizes it to the fullest. On the other hand, maybe the isinst will be compiled to the same instructions if the JIT recognizes that you are casting to a value type (which cannot possibly have subtypes).

Your 3rd method of checking cannot beat the 2nd because you are requiring the JIT to do more than before. At best this optimized back into the 2nd form, but I would be surprised to see that given the poor optimization capabilities of the current JIT.

Tullius answered 13/7, 2013 at 21:36 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.