vote buttons
07 Apr 2015 by K Bonneau

Predict the Output Challenge (C#) - Part 4


Predict the Output Challenge (C#) - Part 1

Predict the Output Challenge (C#) - Part 2

Predict the Output Challenge (C#) - Part 3

Incrementing a Null Value

Would the below code throw an exception? What would it print?

The above code does not throw an exception and i++ evaluates as null. This is even true for other unary operators like +, ++, -, --, !, ~ and mathematical operations like *, / etc. Same operators defined for underlying type are used ("Lifted") for Nullable types.  C# 5 Specification states:

For the unary operators +  ++  -  --  !  ~ a lifted form of an operator exists if
the operand and result types are both non-nullable value types. The lifted form is 
constructed by adding a single ? modifier to the operand and result types. The 
lifted operator produces a null value if the operand is null. Otherwise, the lifted
operator unwraps the operand, applies the underlying operator, and wraps the result.

String Equality Test

Console.WriteLine(i.ToString() == i.ToString());
This returns true. This is obvious as we know == operator is overloaded for strings, and it compares the actual value of the strings and not the reference.
Console.WriteLine(AreEqual(i.ToString(), i.ToString()));
This returns false. This may surprise a few. AreEqual is a generic function. For the above statement T is inferred as String. However the == operator used here is the Object's == operator and not the String's. Object's == operator compares the reference address and not its value. Hence it returns false.
Console.WriteLine(AreEqual("0", "0"));
This returns true. The argument remains the same as in previous case. However in this case Object's == returns true as "0" and "0" refer to the same memory location, due to compiler optimization (interning). In this case compiler knows "0" and "0" are same unlike in previous case where the value of i cannot be determined at compile time.

Default Parameters in Non Sealed Class are Evil

Optional Parameters are processed during compile time. The call to Print in the first case gets replaced by Print("Class Default"), and in the second case as "Interface Default". The compiler can only check the function declaration of the type it is called on, as the actual type can only be determined during run time.

Converting Double To Int32

The statement Console.WriteLine((int)dVal); works fine, as double is converted to an int truncating the decimal points. However in the second case, it throws an invalid cast exception. The double value is actually boxed, when assigning it to an object. As after boxing it is a "reference type", the runtime tries to see if it is of type int (or a subclass of int), which double is not, and hence it fails.

Next: Predict the Output Chanllenge (C#) - Part 5