Why do I get this compile error trying to call a base constructor/method that takes a dynamic argument?

C#.NetC# 4.0DynamicCompiler Construction

C# Problem Overview


While refactoring some code, I came across this strange compile error:

> The constructor call needs to be dynamically dispatched, but cannot be because it is part of a constructor initializer. Consider casting the dynamic arguments.

It seems to occur when trying to call base methods/constructors that take dynamic arguments. For example:

class ClassA
{
	public ClassA(dynamic test)
	{
		Console.WriteLine("ClassA");
	}
}

class ClassB : ClassA
{
	public ClassB(dynamic test)
		: base(test)
	{
		Console.WriteLine("ClassB");
	}
}

It works if I cast the argument to object, like this:

public ClassB(dynamic test)
	: base((object)test)

So, I'm a little confused. Why do I have to put this nasty cast in - why can't the compiler figure out what I mean?

C# Solutions


Solution 1 - C#

The constructor chain has to be determined for certain at compile-time - the compiler has to pick an overload so that it can create valid IL. Whereas normally overload resolution (e.g. for method calls) can be deferred until execution time, that doesn't work for chained constructor calls.

EDIT: In "normal" C# code (before C# 4, basically), all overload resolution is performed at compile-time. However, when a member invocation involves a dynamic value, that is resolved at execution time. For example consider this:

using System;

class Program
{
    static void Foo(int x)
    {
        Console.WriteLine("int!");
    }
    
    static void Foo(string x)
    {
        Console.WriteLine("string!");
    }
    
    static void Main(string[] args)  
    {
        dynamic d = 10;
        Foo(d);
    }
}

The compiler doesn't emit a direct call to Foo here - it can't, because in the call Foo(d) it doesn't know which overload it would resolve to. Instead it emits code which does a sort of "just in time" mini-compilation to resolve the overload with the actual type of the value of d at execution time.

Now that doesn't work for constructor chaining, as valid IL has to contain a call to a specific base class constructor. (I don't know whether the dynamic version can't even be expressed in IL, or whether it can, but the result would be unverifiable.)

You could argue that the C# compiler should be able to tell that there's only actually one visible constructor which can be called, and that constructor will always be available... but once you start down that road, you end up with a language which is very complicated to specify. The C# designers usually take the position of having simpler rules which occasionally aren't as powerful as you'd like them to be.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionDanny TuppenyView Question on Stackoverflow
Solution 1 - C#Jon SkeetView Answer on Stackoverflow