Posted by: Zeeshan Amjad | July 15, 2009

Function overloading on Return type


When we are studying C++, C# or any other object oriented programming, we were told that functions can’t be overloaded on return type. And this is one of the favorite interview question that why can’t we overload functions on return type. The answer is quite simple because at the time of calling the function, it is not necessary to assign its return value to any variable and if we just call the function without storing its return value anywhere then it would be ambiguous for compiler.

  1: void Function()
  2: {
  3: 	// do something
  4: }
  5: 
  6: int Function()
  7: {
  8:      // do something
  9: }
 10: 
 11: float Function()
 12: {
 13: 	// do something
 14: }
 15: 
 16: // Compiler dont know which function to call here
 17: Function();
 18: 

We can simulate this thing with the help of conversion operator in C++, but that is not a function overloading. Here is an example of conversion operator.

 

  1: class Fun
  2: {
  3: public:
  4: 	operator int ();
  5: 	operator char();
  6: 	operator float();
  7: };
  8: 

And the calling of these conversion operators are just like calling the functions. And it seems that functions are overloaded on the basis of return type.

  1: 	// call int function
  2: 	int i = Fun();
  3: 	// call char function
  4: 	char c = Fun();
  5: 	// call float function
  6: 	float f = Fun();
  7: 

But if we are programming directly in MSIL (Microsoft Intermediate Language) then we can actually do true function overloading on return type of the function. And why it is possible at MSIL level but not other high level language, because when calling function in MSIL, we have to give the complete signature of the function including its return type. Because of this feature it is possible for compiler to pick the correct version of the function even if we are not storing the return value of the function.

Here is one simple IL code to demonstrate this concept.

  1: .assembly function{}
  2: 
  3: .method public static void  Function() il managed
  4: {
  5:   ldstr "Hello World from void Function"
  6:   call void [mscorlib]System.Console::WriteLine(class System.String)
  7:   ret
  8: }
  9: 
 10: .method public static int32  Function() il managed
 11: {
 12:   ldstr "Hello World from int32 Function"
 13:   call void [mscorlib]System.Console::WriteLine(class System.String)
 14:   ldc.i4 0
 15:   ret
 16: } 
 17:  
 18: .method public static float32  Function() il managed
 19: {
 20:   ldstr "Hello World from float32 Function"
 21:   call void [mscorlib]System.Console::WriteLine(class System.String)
 22:   ldc.i4 0
 23:   ret
 24: } 
 25: 
 26: .method public static int64  Function() il managed
 27: {
 28:   ldstr "Hello World from int64 Function"
 29:   call void [mscorlib]System.Console::WriteLine(class System.String)
 30:   ldc.i8 0
 31:   ret
 32: } 
 33: 
 34: .method static void start ()
 35: {
 36:     .entrypoint
 37:     .maxstack 1
 38: 
 39: 	call void Function()
 40: 	call int32 Function()
 41: 	pop
 42: 	call float32 Function()
 43: 	pop
 44: 	call int64 Function()
 45: 	pop
 46: 	ret
 47: }
 48: 

There are two more important concepts shown in this program other than function overloading. First one is that our starting function name is not necessary Main it can be anything with “.entrypoint” attribute. Here we select the startup function named “start”.

The other important concept is we don’t have to make classes. We can make global function without any classes when working directly at IL level. In fact in this program all of the functions are global functions.


Responses

  1. […] We already saw one example how to overload function on return type using MSIL here because MSIL supports this. In fact we can do the same with field. We can’t create more than one […]

  2. This seems interesting, but unfortunately your code blocks seem not to be properly closed, thus making the article very hard to read…

    (In the HTML source: each line of code is enclosed in “pre” “/pre” tags, but in addition, each block of code as a whole is introduced by an opening “pre” which is missing a corresponding closing “/pre”.)


Leave a comment

Categories