Polymorphism has been the interviewer's delight for ages. I have been taking interviews for quite some time. And ever since I started preparing questions on C# polymorphism, I have been getting surprises. To prepare interview questions, I try writing code, verify it and then twist the code snippet to make it "interview-able".
This blog is to highlight some of the surprises that I have got while preparing the questions.
The motive of this blog is to highlight tricky points to keep in mind while writing overloaded functions with Generic parameter.
To explain the concept, I'll start with this short code snippet and would like readers to predict the output without scrolling down to the answer.
Code 1
If you know the output and the reasoning behind it, then you may leave the rest of blog as you probably are a better expert than the rest of my audience.
And if you are still reading this line, it means you are searching for the answer. You will definitely get to know the answer, but before I reveal it, I would like you to guess the output of the below code:
Code 2
If you could get the output of the above snippet, then you are one of my category who too will be surprised to see the output of my first problem statement.
And if you couldn't guess the below shown output, it means you need to develop a deeper understanding of C# Type conversion and probably the following post is of better help than mine:
Output 2
So finally if you are the filtered one who is eager to know the answer, then please get yourself ready to be surprised by the answer below:
Output 1
Surprise surprise...
- Generic is called for
2
instead of short
String
is called for "s
" instead of generic
The question that comes to mind is:
- If
2
was considered as Short
in our second code, why was it considered as generic in the first code? - Why
string
was not considered as Generic?
The answer to both these questions is the same. It's the way the C# compiler resolves the ambiguity. The compiler always considers any literal digits as integers (Int32
to be specific) while calling a function until and unless the digit is type casted to other compatible type.
The other point to note is, the compiler tries to do an implicit conversion before doing any boxing unboxing. This is the reason why 2
was downcasted to short
and was not boxed to object in our second example.
So the order of precedence is:
- Exact type match (This is the reason why
string
argument was called with string
function and not generic) - Generic Match (This is why
2
was called with Generic and not short
in our first example) - Implicit conversion match (This is why
2
was called with short
in our second example) - Boxed conversion match (Note that there is no provision of implicit unbox match, so you cannot call an
integer
function with boxed int
argument).
Another interesting observation is, in the second code, the short version is called for -32768
to 32767
. As soon as we provide any integer outside this range (say 32768
), object version gets called. Obviously, this is in line with our order of precedence as no implicit conversion exists to convert 32768
to short
.
Hope this was useful. Please feel free to leave relevant feedback.
Happy coding.
Thanks for reading!