Мой вопрос в некоторой степени связан с этим: Как универсальное ограничение предотвратить упаковку типа значения с неявно реализованным интерфейсом? , но отличается, потому что для этого не должно быть никаких ограничений, потому что он совсем не общий.
У меня есть код
interface I { void F(); }
struct C : I { void I.F() {} }
static class P {
static void Main()
{
C x;
((I)x).F();
}
}
Основной метод компилируется на это:
IL_0000: ldloc.0
IL_0001: box C
IL_0006: callvirt instance void I::F()
IL_000b: ret
Почему он не компилируется с этим?
IL_0000: ldloca.s V_0
IL_0002: call instance void C::I.F()
IL_0007: ret
Я понимаю, почему вам нужна таблица методов для выполнения виртуального вызова, но в этом случае вам не нужно делать виртуальный вызов. Если интерфейс реализован нормально, он не выполняет виртуальный вызов.
Также связано: Почему явные реализации интерфейса являются частными? - существующие ответы на этот вопрос неадекватно объясняют, почему методы помечены как частные в метаданных (а не просто имеют непригодные для использования имена). Но даже это не полностью объясняет, почему он упакован, поскольку он все еще упаковывается при вызове изнутри C.