C# by nature is a very strongly typed language which signifies that most of the verifications are executed statically during compile time. If not all, most of the features and structs exposed by C# language adhere to this principle. With the introduction of Dynamic in C# 4.0, I found that there is confusion in developer’s community around the difference between Var
, Object
, and Dynamic
. In this blog, I will try to highlight the differences from the CLR and the compiler’s perspective.
System.Object
All the objects (value and referenced types) in managed environment are directly or indirectly inherited from System.Object
. With this inheritance in place, a variable of System.Object
can hold the reference of instance of any type.
In the above example, o1
is holding the reference of XmlDocument
and o2
is holding the reference of boxed double value. However in either case, the compiler will allow to call only those methods /properties which exist in System.Object
type. In other words, the compiler will not allow you to call ChildNodes
property from o1
and similarly o2
cannot be used for any arithmetic operation. All of these restrictions are in place because from the compiler’s perspective, o1
and o2
are holding the reference of System.Object
type. The only way to access the ChildNodes
property is to typecast it into XmlDocument
type. In that case, the compiler will emit the code to validate the type casting during runtime.
Hence:
- Though variable of
System.Object
type can hold the reference of any type, compiler will ensure the type safety. If type casting is happening, the compiler will emit the code to validate the type safety during runtime.
- Assigning the value type to a variable of
System.Object
will suffer from Boxing / Unboxing.
Var Keyword
The var
keyword was introduced in C# 3.0. It was primarily introduced to support the notion of anonymous types (which was the key requirement for LINQ). But the important part is, var
is resolved at the compile time, i.e., the actual type is resolved by the compiler during the compile time. Hence, it provides same type safety as using normal typed variable.
In the above example, var1
is resolved by compiler as double
, var2
is resolved by compiler as int
and var3
is resolved by compiler as string
. From the CLR perspective, there is nothing known as var
.
Hence:
var
is a compile time feature resolved to a valid underlying type. Due to this, the compiler enforces you to assign a value during the declaration so it can infer the actual type.
- Since
var
is resolved to a valid type during compilation, the compiler will enforce all type safety and code will not suffer from boxing / unboxing.
In my own opinion, we should use “var
” only when actual type is not known during development, i.e., type is anonymous as shown in the following example.
If the actual type is known, then I will not recommend using var
to save few keyboard strokes as it reduces the readability of code.
Dynamic
With C# 4.0, Microsoft introduces dynamic
. When you define a variable of type dynamic, compiler internally performs two steps. The first thing compiler does is, it converts the type to System.Object
and then it postpones all the type validation to the runtime. The following example uses the dynamic to declare an int
type.
In the above example, Double
declares the multiplier as dynamic
. During compilation, dynamic
will be converted to System.Object
and the compiler will emit the code for type safety during runtime as shown in the following IL.
Hence:
- During compilation time,
dynamic
is converted to System.Object
and the compiler will emit the code for type safety during runtime.
- As dynamic is treated as
System.Object
, it suffers from boxing / unboxing similar to System.Object
.
- Since compiler emits the code for all the type safety, the application’s performance will suffer.
dynamic
was introduced only to simplify the access to the COM APIs. I strongly recommend that we should restrict the use of dynamic
only when handling the COM APIs as it might cause runtime exceptions and can cause performance issues.