Почему компилятор С# не проверяет "статичность" метода на сайтах вызовов с динамическим аргументом?

Почему компилятор С# не говорит, что этот фрагмент кода недействителен?

class Program
{
    static void Main(string[] args)
    {
        dynamic d = 1;
        MyMethod(d);
    }

    public void MyMethod(int i) 
    {
        Console.WriteLine("int");
    }
}

Вызов MyMethod завершается с ошибкой во время выполнения, потому что я пытаюсь вызвать нестатический метод из статического метода. Это очень разумно, но почему компилятор не считает это ошибкой во время компиляции?

Ниже не будет компилироваться

class Program
{
    static void Main(string[] args)
    {
        dynamic d = 1;
        MyMethod(d);
    }
}

поэтому, несмотря на динамическую отправку, компилятор проверяет, существует ли MyMethod. Почему он не проверяет "статичность"?

Ответ 1

Разрешение перегрузки здесь динамическое. Видимый в этом фрагменте кода:

class Program {
    public static void Main() {
        dynamic d = 1.0;
        MyMethod(d);
    }

    public void MyMethod(int i) {
        Console.WriteLine("int");
    }

    public static void MyMethod(double d) {
        Console.WriteLine("double");
    }
}

Прекрасно работает. Теперь назначьте от 1 до d и обратите внимание на сбой выполнения. Компилятор не может разумно эмулировать динамическое разрешение перегрузки во время компиляции, поэтому он не пытается.

Ответ 2

Когда компилятор обнаружил операцию с/с переменной типа dynamic, она будет передавать эту информацию с помощью объекта CallSite. (Объект CallSite хранит информацию о вызове.)

В вашем первом примере он может скомпилироваться, потому что компилятор может испускать информацию (например, тип вызова, метод, который вы хотите вызвать и т.д.). Во втором коде вы пытаетесь вызвать метод, который не существует, поэтому компилятор не может испустить код IL для вас.