I had following piece of code
try
{
object s = new object();
s = 10;
Console.WriteLine(\"{0}\", Convert.ToInt16(s));
Console.WriteLine(\"{0}\", (In
Your code is violating a C# language rule. Chapter 4.3.2 of the C# Language Specification says:
For an unboxing conversion to a given non-nullable-value-type to succeed at run-time, the value of the source operand must be a reference to a boxed value of that non-nullable-value-type. If the source operand is null, a System.NullReferenceException is thrown. If the source operand is a reference to an incompatible object, a System.InvalidCastException is thrown.
Perhaps not the most clearest possible language, "incompatible object" doesn't help much when talking about value types, but what it says that you can only unbox to an int. A conversion to Int16 (aka short) is not permitted. This rule is not arbitrary, it allows the jitter to generate very efficient code. It doesn't have to consider conversion so it can directly access the bits in the boxed object. Which can be done entirely inline without any helper method, it takes a dozen machine code instructions. This mattered a great deal back in .NET 1.x where generics were not available yet. So collection classes like ArrayList had to store boxed values. Getting them out of the collection required unboxing.
And yes, the Convert class is the workaround. It takes advantage of the value types implementing the IConvertible interface. So it will end up calling the Int32.ToInt16() method. Which first unboxes to int and then casts to Int16. Not as efficient but no kaboom.