В ответ на мой другой ответ Эрик Смит правильно отмечает:
"... потому что это потребовало бы неявного бокса параметра типа получателя ...". Что в любом случае происходит, если вы делаете что-то вроде этого: Func f = 5.ToString; Что совершенно законно.
Размышление об этом привело меня к новому ответу. Попробуйте это для размера:
Обычные методы «экземпляра» в структурах принимают на уровне CIL «управляемый указатель» (тип &
) в качестве параметра получателя. Это необходимо для того, чтобы методы экземпляра в структурах могли назначаться полям структуры. См. Раздел II, Раздел 13.3 .
Аналогично, методы экземпляра в классах принимают "ссылку на объект" (тип O
) в качестве параметра получателя (разница в том, что это указатель на управляемую кучу, и его необходимо отслеживать для GC).
Поскольку и CIL &
s, и O
s могут быть (и реализованы) указателями, все очень просто для реализации делегата. Независимо от того, захватывает ли делегат статический метод, метод экземпляра класса или метод экземпляра структуры, все, что ему нужно сделать, это передать указатель на его _target
на первый аргумент функции.
Но сценарий, который мы обсуждаем, рушит это. Метод статического расширения, принимающий int
в качестве первого аргумента, требует аргумент CIL типа int32
(см. Раздел III, раздел 1.1.1). Здесь все идет не так, как надо. Я не вижу никаких причин, по которым невозможно для реализации делегатами понять, что это происходит (например, проверяя метаданные, связанные с перехваченным MethodInfo, и испускает поток, который распаковывает _target
и передает его в качестве первого аргумента, но это не нужно для делегатов классических методов экземпляра на структурах, так как они ожидайте указатель в любом случае и не появится (судя по примеру в моем предыдущем неправильном ответе), который будет реализован. Очевидно, что конкретный тип значения, о котором идет речь, будет контролировать точный характер требуемого блока.
Если я не пропущу более фундаментальное препятствие для реализации (я мог бы предположить, что это может создать проблемы для верификатора, например), кажется, что может быть разумно продлить время выполнения для поддержки этого случая, но все знаки указывают на то, что это ограничение времени выполнения, а не компилятора C # как такового.