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, ifA : B
than the equality test will fail forA.GetType() == typeof(B)
whereasA is B
will succeed.- If the object is
null
, it will throw aSystem.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
Deserializing Polymorphic Json Classes Without Type Information Using Json.Net
How to Calculate Someone'S Age Based on a Datetime Type Birthday
What Is the Purpose of "Return Await" in C#
Parsing CSV Files in C#, With Header
Split List into Sublists With Linq
C# Difference Between == and Equals()
How to Make a Textbox That Only Accepts Numbers
An Async/Await Example That Causes a Deadlock
How to Do Impersonation in .Net
Asynchronously Wait For Task≪T≫ to Complete With Timeout