Having a dynamic call inside a function prevents static context checking. Why?

I have the following code. Using Visual Studio 2013. Notice the dynamic function call within the function

class Someclass
{
   public static string[] BuildParametersString(ISomeInterface obj1, ISecondInterface obj2)
   {
      //.....

      var dt = obj1.GetDate();//this returns a dynamic type.
      SomeFunc(dt);//Run time error
   } 

   private string SomeFunc(DateTime somedate)
   {
     //......
   }
}

      

Runtime error (in SomeFunc (dt);): An object reference is required for a non-static field, method or property.

If I replace the following code

 var dt = obj1.GetDate();//this returns a dynamic type.

      

with this

DateTime dt = DateTime.Now;

      

I am getting compiler error (in SomeFunc (dt))

It is not possible to access the static SomeFunc method in a static context.

Any explanation for the behavior?

+3


source to share


2 answers


Overload resolution is still performed at compile time dynamic

to provide a list of possible functions that could be called. At run time, the list is narrowed to the maximum according to the actual type dynamic

.

As per the spec, however, overload resolution only considers the number and types of arguments - not, static

or even availability. According to some quick tests, it seems that the order of operations at compile time is:

  • Availability check
  • Overload resolution
  • Static check

Since it dynamic

affects overload resolution (step # 2), but cannot narrow down to the best possible candidate at compile time, it looks like check static

(# 3) is also delayed until runtime.



I do not see in theory any reason to believe that the steps cannot be reordered (NB: I don’t know if there is a relevant specification to consider) or that step # 3 cannot be performed (at compile time) against all possible candidates. out of "dynamic" overload resolution to ensure that at least one candidate remains.

Even if this is not a real mistake 1, I do think it is contrary to a design principle dynamic

- which I have always understood to only postpone what you have no choice but to postpone.

UPDATE: note that the C # 6 compiler in LINQPad 5 / VS2015 now specifies this at compile time; although the order of operations doesn't seem to have changed.

1 Section 7.6.5.1 of the C # 5 Method Specification (Method Calls) specifies that "final validation" (including static validation) occurs after overload resolution; Section 7.5.4 (Checking the Time of Dynamic Overload Resolution at Compile Time) only indicates that partial input and partial applicability (overload resolution) output routines are performed for method calls with dynamic arguments.

+3


source


Since it SomeFunc(DateTime)

has DateTime

a parameter type, you cannot give it an object dynamic

. It is waiting DateTime

, so you have to get it out.
EDIT: This is not actually what Chris Sinclair points out, you can use dynamic

like this. The rest of my answer still holds true though

You also cannot access an instance method SomeFunc(DateTime)

from a static method, as an instance method can rely on instance variables that do not exist in a static context. Either make it SomeFunc(DateTime)

static (if possible) or make BuildParametersString(ISomeInterface, ISecondInterface)

an instance method (or just return the result from GetDate()

) and send it as an argument SomeFunc(DateTime)

from client code.



I don't know if this is just an example to show the point, but I would also seriously reconsider using dynamic variables in this case. Are you getting anything from this? They should usually be avoided at all costs as they only complicate matters and you have lost all compile-time checks.

0


source







All Articles