Evil Code #003 : Casting

Welcome to first post on ‘Back to basics’. Yeah, as you guessed right, this series attempt to check minor differences in our understanding of basic concepts.

Predict the output of following.


public class FirstType
{

}
public class SecondType
{
private FirstType _mType;

public static implicit operator FirstType(SecondType t)
{
return t._mType;
}
}

static void Main(string[] args)
{
object objectInstance = new SecondType();

FirstType attempt1 = objectInstance as FirstType;
if (attempt1 != null)
{
Console.WriteLine("'As' Conversion Succeeded");
}
else
{
Console.WriteLine("'As' Conversion Failed");
}

try
{
FirstType attempt2 = (FirstType)objectInstance;
Console.WriteLine("Cast Succeeded");
}
catch (Exception)
{
Console.WriteLine("Cast Failed");
}

}

Ideally, One would expect the first attempt to fail, but would feel the second would succeed considering we have implemented implicit conversion. But unfortunately, that’s not the case. The output would be

‘As’ Conversion Failed.
Cast Failed.

The reason for this is that, the compiler generates code based on the compile time type of the objectInstance, which in this case is ‘object’. It then checks if there is any conversion declared to convert object to FirstType, which doesn’t exist. The compiler doesn’t check the type of the objectInstance during runtime, which results in the above output.

The reason for this is that, the compiler generates code based on the compile time type of the objectInstance, which in this case is ‘object’. It then checks if there is any conversion declared to convert object to FirstType, which doesn’t exist. The compiler doesn’t check the type of the objectInstance during runtime, which results in the above output.

Updated

The behavior is even more tricky when we change the type of objectInstance from ‘object’ to SecondType. We would expect it to work smoothly now, however, you end up with a compiler exception this time .

“Cannot convert type ‘Cast.SecondType’ to ‘Cast.FirstType’ via a reference conversion, boxing conversion, unboxing conversion, wrapping conversion, or null type conversion”

This is what makes ‘as’ operators great as it provides early detection of errors. The ‘as’ operator, notices that there is a implicit conversion declared between FirstType and SecondType. However, it also recognizes that two types aren’t related by inheritance. This is the reason ‘as’ statements throws a compile-time error at this stage.

 

Evil Code 0002 Optional Parameter Vs Method Overloading

Again one of those things which looks so simple, but could drive one mad during debugging.

Much before Optional Parameters came in, C# developers used to depend on Method Overloading for mimicking Optional Parameters. Consider a scenario where both exists, what would be the output ?

Image

The output would be :

Image

The reason behind this is the overload resolution method adopted when we have a overloaded method and a method with optional parameter. Here is what MSDN says.

If two candidates are judged to be equally good, preference goes to a candidate that does not have optional parameters for which arguments were omitted in the call. This is a consequence of a general preference in overload resolution for candidates that have fewer parameters.

Evil Code 0001 : Lambda and Ref/out

What would be output of following ?

        static void Main(string [] args)
        {
            List< int> numlist = new List< int>() {1,2, 3, 4, 5, 6, 7 };
            CalculateAndPrint( ref numlist);
        }
 
        public static void CalculateAndPrint( ref List< int> Num)
        {
            var n = Num.Where(d => d > Num[2]);
 
            foreach ( var item in n)
            {
                Console.WriteLine(item);
            }
        }

The most obvious answer is 4,5,6,7. However that’s not. This code refuses to compile because Lamba expressions  cannot accept variables that are declared in an outer scope.