首页 > 代码库 > C# to IL 5 Operator Overloading(操作符重载)

C# to IL 5 Operator Overloading(操作符重载)

Every operator overload that we use in C#, gets converted to a function call in IL. The
overloaded > operator translates into the function op_GreaterThan and a + gets converted
to op_Addition etc. In the first program of this chapter, we have overloaded the + operator
in class yyy to facilitate adding of two yyy objects.

技术分享

技术分享

技术分享

技术分享

技术分享

While using the plus (+) operator on the two yyy objects, C# is aware that IL does not
support operator overloading. Therefore, it creates a function called op_Addition in the
class yyy.
Thus, operator overloading gets represented as a mere function call. The rest of the code is
easy for you to figure out.
In IL, there is no rule stating that if the > operator is overloaded, then the < operator also
has to be overloaded. These rules are imposed by the C# compiler, and not by IL since, IL
does not support the concept of overloading at all.

技术分享

技术分享

技术分享

The C# compiler is extremely intelligent. Whenever a yyy object has to be converted to a
string, it first checks for the presence of an operator called string in the class yyy. If it
exists, it calls that operator.
The operator named string is a predefined data type in C#. Hence, it is converted into the
operator op_Implicit. This operator takes a yyy object as a parameter. It returns a string on
the stack for the WriteLine function. The ToString function is not called.
C# will generate an error if you alter even a single parameter to the operator string, but
such is not a case with IL as it does not support operator overloading and conversions

技术分享

技术分享

技术分享

技术分享

In the C# code above, we have dispensed with the operator string and instead, have used
the ToString function. As usual, we put the object a on the stack. In the IL code given
earlier, due to the presence of operator overloads in the C# code, the function op_Implicit
was called. In this case, since there are no operator overloads, the object reference to object
a is simply put on the stack. In class yyy, even though, the function ToString is not
explicitly called, the function does get executed.
Since the ToString is virtual in the class Object, at run time, the ToString function is called
from the class yyy, instead of being called from the class Object. This is due to the concept
of a vtable, where all virtual function addresses reside.
If the word virtual is removed from the function, the ToString function gets called from the
class Object instead of the class yyy

技术分享

技术分享

技术分享

In the above code, we have cast a yyy object into a string using an explicit cast. IL does not
understand C# keywords like implicit or explicit. It converts the cast to an actual function
such as op_Explicit or op_Implicit. Thus writing a C# compiler requires a lot of grey matter.

技术分享

技术分享

技术分享

In the code above, we are not creating an object that is an instance of class yyy. Instead,
we are simply initializing it to a numeric value of 10. This results in a call to the implicit
operator yyy, which takes an int value as a parameter and creates a yyy object.
The IL code does not understand any of this. It simply calls the relevant operator, which in
this case is op_Implicit, with an int value. It is the responsibility of this function to create
an object that is an instance of class yyy. We are, in effect, creating two locals that look like
yyy, and initializing them to the new yyy like object on the stack. Finally its value,10, is put
on the stack.

技术分享

技术分享

技术分享

技术分享

In the above code, we have created two objects, a and b, that are instances of a class yyy.
Then, we have employed the overloaded operators & and && to determine as to how IL
handles them internally. If we can grasp the intricacies of IL, our understanding of C# will
become so much better. Maybe, a programmer should be allowed to program in C# only if
he/she has learnt IL.
The dup operator duplicates the value present at the top of the stack. In this case, it is the
local V_0. All occurences of && and & in the C# code are replaced by the functions
op_False and op_BitwiseAnd respectively, on conversion to IL code.
The op_False operator returns either TRUE or FALSE.
? If it returns TRUE, then the answer is TRUE, and the rest of the condition is not
checked. This is how the code is short-circuited. We simply jump past code that is not
to be executed.
? If it returns FALSE, the & operator gets called. This operator gets converted to
op_BitwiseAnd. In order to enhance the efficiency, the two objects were already present
on the stack for the op_BitwiseAnd operator to act upon.
You will be appreciate that IL makes our understanding of abstract concepts of C# much
easier to understand.

 技术分享

技术分享

技术分享

In IL, the object m is a local named V_0 of type System.Type. In C#, the typeof keyword
returns a Type object, but in IL, a large number of steps have to be executed to achieve the
same result.
? Firstly, a type is placed on the stack using the instruction ldtoken. This loads a token
that represents a type or a field or a method.
? Next, the function GetTypeFromHandle is called that picks up a token, i.e. a
structure or value class from the stack.
? The function thereafter returns a Type object representing a type, which in this case
is an int. This is stored in the local V_0 and then again loaded on the stack.
? Next, the function get_FullName is called. The function is not called FullName but
get_FullName as it is a property. This property returns a string on the stack that is
displayed using the WriteLine function.

技术分享

技术分享

技术分享

The keyword is lets us determine the data type of an object at run-time. Thus the is
keyword of C# has an equivalent instruction in IL.We are passing a zzz like object and an
object that is an instance of class object to the function abc. This function demotes every
parameter it receives to a class object, but the is keyword is intelligent enough to know
that the run time data type can be of a type other than an object. Thus, it returns TRUE for
the z object, but not for the a object.
The assembler code in Main or vijay remains the same. The relevant source code is
present in the function abc.
? The instruction ldarg.1 pushes the value of parameter 1 onto the stack. The data type
of this parameter is Object.
? Next, the instruction isinst is called. The type with which we want to compare the
object on the stack is passed as a parameter to isinst. This instruction determines the

 data type of the value present on the stack.
? If the type of the isint instruction matches what is already there on the stack, the
object remains on the stack. If it does not match, a NULL is placed on the stack.
? The brfalse instruction executes the jump to a label if the result is TRUE in the il
code.

技术分享

技术分享

技术分享

The keyword as is similar to the is. Two objects have been placed on the stack and the
function abc is called. This function requires an object on the stack. The type of the
variable a has to be converted from int to an Object. The isinst instruction takes value at
the top of the stack and converts it into the data type specified. If it is unable to do so, it
puts a NULL on the stack.
In the second call, on the stack, a string is obtained for the WriteLine function. Since an
int32 value cannot be converted into a string, a NULL value is placed on the stack. Hence
the WriteLine function displays a blank line.
技术分享

技术分享

All pointers in C# have a size of 4 bytes each. The sizeof keyword is an instruction in IL
that returns the size of the variable that is passed as a parameter to it. It can only be used
on a value type variable, not on a reference type.

In C# we use the modifier unsafe while introducing pointers. This modifier does not exist
in IL, as IL regards everything as unsafe. Note that a byte in C# is converted into an int8 in
IL.

C# to IL 5 Operator Overloading(操作符重载)