Type Checking: Typeof, Gettype, or Is

Type Checking: typeof, GetType, or is?

All are different.

  • typeof takes a type name (which you specify at compile time).
  • GetType gets the runtime type of an instance.
  • is returns true if an instance is in the inheritance tree.

Example

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);

What about typeof(T)? Is it also resolved at compile time?

Yes. T is always what the type of the expression is. Remember, a generic method is basically a whole bunch of methods with the appropriate type. Example:

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"

Which is good to use: Object.GetType() == typeof(Type) or Object is Type?

The second one:

Object is Type

Tested this 1'000'000'000 times with string versus int one gets:

//Release
00:00:18.1428040 //Object.GetType() == typeof(Type)
00:00:03.9791070 //Object is Type
//Debug
00:00:21.3545510 //Object.GetType() == typeof(Type)
00:00:06.2969510 //Object is Type
//Machine specs:
//Intel(R) Core(TM) i5-3210M CPU @ 2.50GHz
//6 GB RAM memory
//Ubuntu 14.04 (OS)
//Runtime: Mono JIT compiler version 3.2.8
//Compiler: Mono dmcs
//Notes: ran these with some background processes, but the difference in time
// is significant enough I guess.

Note: There is a strong semantic difference between the two:

  • The equality == checks on type equality: in other words, if A : B
    than the equality test will fail for A.GetType() == typeof(B)
    whereas A is B will succeed.
  • If the object is null, it will throw a System.NullReferenceException. In the second case, it will return
    false.

This is rather logic from a compiler point-of-view: in the first variant, you query the object for its type. In case that's not really optimized, you do a function call first, that call then says it must return a pointer to the type-table.

In the second case, you omit such calls: the compiler will specialize it by returning the type-code. And if the Type is known in advance, it can even work out a very fast test for it.

Note furthermore that for some trivial cases, Object is Type can be optimized: for instance because the compiler can already derive that Object can't/is always of type Type.

More advanced

One can also analyze the CIL virtual machine source code, for the first variant, this is:

IL_0000: ldarg.0
IL_0001: callvirt instance class [mscorlib]System.Type [mscorlib]System.Object::GetType()
IL_0006: ldtoken [mscorlib]System.Int32
IL_000b: call class [mscorlib]System.Type [mscorlib]System.Type::GetTypeFromHandle(valuetype [mscorlib]System.RuntimeTypeHandle)
IL_0010: call bool [mscorlib]System.Type::op_Equality(class [mscorlib]System.Type, class [mscorlib]System.Type)
IL_0015: ret

For the second variant this is:

IL_0000: ldarg.0
IL_0001: isinst [mscorlib]System.Int32
IL_0006: ldnull
IL_0007: cgt.un
IL_0009: ret

(you can of course fill in other types). Now the ldarg.0 and ret are simply by-products of using a method, so one can ignore them.

What one sees is that in the first variant, one calls the GetType method explicitly and then calls the == operator. Function calls are in general expensive. In the second variant, it checks immediately for isinst. The code requires less bytes and uses less expensive methods. Although performance of course depends on the implementation of the runtime environment, I think it's rather safe to say the second variant will nearly always beat the first one on performance.

A compiler could probably specialize the first variant such that it runs as efficient as the second, but the Mono C# compiler doesn't seem to do this. Probably none of the available C# compilers will.

When and where to use GetType() or typeof()?

typeof is an operator to obtain a type known at compile-time (or at least a generic type parameter). The operand of typeof is always the name of a type or type parameter - never an expression with a value (e.g. a variable). See the C# language specification for more details.

GetType() is a method you call on individual objects, to get the execution-time type of the object.

Note that unless you only want exactly instances of TextBox (rather than instances of subclasses) you'd usually use:

if (myControl is TextBox)
{
// Whatever
}

Or

TextBox tb = myControl as TextBox;
if (tb != null)
{
// Use tb
}

GetType() == typeOf(string) or var is string ...?

The code you wrote is nonsense, because Console.ReadLine always returns a string (it is its return type after all!).

To answer your question, the is operator is not equivalent to the GetType() == typeof() statement. The reason is that is will return true if the object can be cast to the type. In particular, it will return true for derived types, which would fail the other check. From MSDN:

An is expression evaluates to true if the provided expression is non-null, and the provided object can be cast to the provided type without causing an exception to be thrown.

Note that the is operator only considers reference conversions, boxing conversions, and unboxing conversions. Other conversions, such as user-defined conversions, are not considered.

If you are looking for a specific type of input (say a number) then you need to try and Parse or TryParse it into that type. Something like:

double output;
if (double.TryParse(answer, out output)
{
//Its a number!
}
else
{
//Its some regular string
}

Without seeing more its impossible to say what exactly you need to write though.

typeof(T) vs. Object.GetType() performance

typeof is used when you want to get the Type instance representing a specific type. GetType gives the runtime type of the object on which it is called, which may be different from the declared type.

For example:

class A {}

class B : A {}

class Program
{
static A CreateA()
{
return new B();
}

static void Main()
{
A a = CreateA();
Console.WriteLine(typeof(A)); // Writes "A"
Console.WriteLine(a.GetType()); // Writes "B"
}
}

In the above case, within the Main method, you're dealing with instances of type A; thus, if you care about the declared type, you would use typeof(A). However, the CreateA method actually returns an instance of a derived class, B, despite declaring the base class as the return type. If you want to find out about this runtime type, call GetType on the returned instance.

Edit: Mehrdad's comment points in the right direction. Although typeof emits a GetTypeFromHandle call that takes a RuntimeTypeHandle as parameter, the said parameter would actually correspond to the specific type whose metadata token is on the evaluation stack. In some instances, this token would be there implicitly (due to the current method invocation); otherwise, it can be pushed there explicitly by calling ldtoken. You can see more examples of this in these answers:

  • Efficiency of C#'s typeof operator (or whatever its representation is in MSIL)
  • Generating IL for 2D Arrays

Edit2: If you're looking for performance benchmarks, you can refer to Jon Skeet's answer. His results were (for 100 million iterations):

typeof(Test):   2756ms
test.GetType(): 3734ms

What is the difference of getting Type by using GetType() and typeof()?

You can only use typeof() when you know that type at compile time, and you're trying to obtain the corresponding Type object. (Although the type could be a generic type parameter, e.g. typeof(T) within a class with a type parameter T.) There don't need to be any instances of that type available to use typeof. The operand for typeof is always the name of a type or type parameter. It can't be a variable or anything like that.

Now compare that with object.GetType(). That will get the actual type of the object it's called on. This means:

  • You don't need to know the type at compile time (and usually you don't)
  • You do need there to be an instance of the type (as otherwise you have nothing to call GetType on)
  • The actual type doesn't need to be accessible to your code - for example, it could be an internal type in a different assembly

One odd point: GetType will give unexpected answers on nullable value types due to the way that boxing works. A call to GetType will always involve boxing any value type, including a nullable value type, and the boxed value of a nullable value type is either a null reference or a reference to an instance of a non-nullable value type.

What is the difference between typeof and is when comparing object types?

GetType returns an instance of System.Type and this is never an instance of TSendForReview. You probably want to use

if(control[0] is TSendForReview)

to see if the control is an instance of your type.

Your modified version gets the runtime type of the control and compares it to the type instance for TSendForReview. This is not the same as using is since it must have the exact type, whereas is will return true for a subtype of TSendForReview.

And why the warning?

The is keyword causes a compile-time warning if the expression is
known to always be true or to always be false, but typically evaluates
type compatibility at run time.

Source: MSDN

Typescript: Check typeof against custom type

Short answer:

You can't use typeof at runtime to check for interface types, which only exist at compile time. Instead you can write a user-defined type guard function to check for such types:

const fruit = ["apple", "banana", "grape"] as const;
type Fruit = (typeof fruit)[number];
const isFruit = (x: any): x is Fruit => fruit.includes(x);

let myfruit = "pear";
if (isFruit(myfruit)) {
console.log("My fruit is of type 'Fruit'");
}

Long answer follows:


You might be confused about the difference between values and types in TypeScript, especially as it relates to the typeof operator. As you may be aware, TypeScript adds a static type system to JavaScript, and that type system gets erased when the code is transpiled. The syntax of TypeScript is such that some expressions and statements refer to values that exist at runtime, while other expressions and statements refer to types that exist only at design/compile time. Values have types, but they are not types themselves. Importantly, there are some places in the code where the compiler will expect a value and interpret the expression it finds as a value if possible, and other places where the compiler will expect a type and interpret the expression it finds as a type if possible.

The typeof operator leads a double life. The expression typeof x always expects x to be a value, but typeof x itself could be a value or type depending on the context:

let bar = {a: 0};
let TypeofBar = typeof bar; // the value "object"
type TypeofBar = typeof bar; // the type {a: number}

The line let TypeofBar = typeof bar; will make it through to the JavaScript, and it will use the JavaScript typeof operator at runtime and produce a string. But type TypeofBar = typeof bar; is erased, and it is using the TypeScript type query operator to examine the static type that TypeScript has assigned to the value named bar.

In your code,

let myfruit = "pear";
if (typeof myfruit === "Fruit") { // "string" === "Fruit" ?!
console.log("My fruit is of type 'Fruit'");
}

typeof myfruit is a value, not a type. So it's the JavaScript typeof operator, not the TypeScript type query operator. It will always return the value "string"; it will never be Fruit or "Fruit". You can't get the results of the TypeScript type query operator at runtime, because the type system is erased at runtime. You need to give up on the typeof operator.


What you can do is check the value of myfruit against the three known Fruit string literals... like, for example, this:

let myfruit = "pear";
if (myfruit === "apple" || myfruit === "banana" || myfruit === "grape") {
console.log("My fruit is of type 'Fruit'");
}

Perfect, right? Okay, maybe that seems like a lot of redundant code. Here's a less redundant way to do it. First of all, define your Fruit type in terms of an existing array of literal values... TypeScript can infer types from values, but you can't generate values from types.

const fruit = ["apple", "banana", "grape"] as const;
export type Fruit = (typeof fruit)[number];

You can verify that Fruit is the same type as you defined yourself manually. Then, for the type test, you can use a user-defined type guard like this:

const isFruit = (x: any): x is Fruit => fruit.includes(x);

isFruit() is a function which checks if its argument is found in the fruit array, and if so, narrows the type of its argument to Fruit. Let's see it work:

let myfruit = "pear";
if (isFruit(myfruit)) {
console.log("My fruit is of type 'Fruit'");
}

That type guard also lets the compiler know that inside the "then" clause of the if statement, that myfruit is a Fruit. Imagine if you had a function that only accepts Fruit, and a value that may or may not be a Fruit:

declare function acceptFruit(f: Fruit): void;
const myfruit = Math.random() < 0.5 ? "pear" : "banana";

You can't call the function directly:

acceptFruit(myfruit); // error, myfruit might be "pear"

But you can call it inside the "then" clause after checking it:

if (isFruit(myfruit)) {
acceptFruit(myfruit); // okay, myfruit is known to be "banana"
}

Which is presumably why you want to check against your custom type in the first place. So that lets you do it.


To recap: you can't use typeof. You can compare against strings. You can do some type inference and a type guard to eliminate duplicated code and get control flow type analysis from the compiler.

Playground link to code

How to check if an object is a certain type

In VB.NET, you need to use the GetType method to retrieve the type of an instance of an object, and the GetType() operator to retrieve the type of another known type.

Once you have the two types, you can simply compare them using the Is operator.

So your code should actually be written like this:

Sub FillCategories(ByVal Obj As Object)
Dim cmd As New SqlCommand("sp_Resources_Categories", Conn)
cmd.CommandType = CommandType.StoredProcedure
Obj.DataSource = cmd.ExecuteReader
If Obj.GetType() Is GetType(System.Web.UI.WebControls.DropDownList) Then

End If
Obj.DataBind()
End Sub

You can also use the TypeOf operator instead of the GetType method. Note that this tests if your object is compatible with the given type, not that it is the same type. That would look like this:

If TypeOf Obj Is System.Web.UI.WebControls.DropDownList Then

End If

Totally trivial, irrelevant nitpick: Traditionally, the names of parameters are camelCased (which means they always start with a lower-case letter) when writing .NET code (either VB.NET or C#). This makes them easy to distinguish at a glance from classes, types, methods, etc.

How to check a runtime type in C#

You need to wrap ConsoleApp2.Class1 with the typeof operator to get an object of type Type, which can be compared to your other type object.

If you want to check for exact equality, you can use Type.Equals or ==.

var type1 = Type.GetType("ConsoleApp2.Class1");
var type2 = typeof(ConsoleApp2.Class1);

if (type1.Equals(type2)) { ... }
if (type1 == type2) { ... }

If you want to check for equality or a subtype relationship (similar to myObject is SomeType), you can use

if (type1.IsAssignableFrom(type2)) { ... }


Related Topics



Leave a reply



Submit