У меня есть устройство, которое передает двоичные данные. Для интерпретации данных я определил struct
, соответствующий формату данных. struct
имеет атрибут StuctLayoutAttribute
с LayoutKind.Sequential
. Это работает, как и ожидалось, например:
[StructLayout(LayoutKind.Sequential)]
struct DemoPlain
{
public int x;
public int y;
}
Marshal.OffsetOf<DemoPlain>("x"); // yields 0, as expected
Marshal.OffsetOf<DemoPlain>("y"); // yields 4, as expected
Marshal.SizeOf<DemoPlain>(); // yields 8, as expected
Теперь я хочу рассматривать одну структуру как другую структуру, поэтому я поэкспериментировал со структурой, реализующей интерфейс:
interface IDemo
{
int Product();
}
[StructLayout(LayoutKind.Sequential)]
struct DemoWithInterface: IDemo
{
public int x;
public int y;
public int Product() => x * y;
}
Marshal.OffsetOf<DemoWithInterface>("x").Dump(); // yields 0
Marshal.OffsetOf<DemoWithInterface>("y").Dump(); // yields 4
Marshal.SizeOf<DemoWithInterface>().Dump(); // yields 8
К моему удивлению, смещения и размер DemoWithInterface
остаются такими же, как DemoPlain
, и преобразование тех же двоичных данных с устройства либо в массив DemoPlain
, либо в массив DemoWithInterface
работает. Как это возможно?
Реализации C++ часто используют виртуальную таблицу (см. Где в памяти хранится виртуальная таблица?) наболеть виртуальными методами. Я считаю, что в C# методы, опубликованные в интерфейсе, и методы, объявленные virtual
, аналогичны виртуальным методам в C++ и что для поиска правильного метода требуется что-то похожее на виртуальную таблицу. Это правильно или С# делает это совершенно по-другому? Если правильно, где хранится структура, подобная vtable? Если отличается, как реализован C# в отношении наследования интерфейсов и виртуальных методов?
var s = new DemoWithInterface(); s.Product()
. Здесь не нужна виртуальная диспетчеризация, можно вызвать только один конкретный метод. А вот если структура упакована - тогда другое дело и такая запись есть, но коробочная структура - это не то же самое, что неупакованная. Так вот:IDemo s = new DemoWithInterface(); s.Product()
нужна виртуальная диспетчеризация, но структура упакована и представлена по-другому (не только простые поля). - person Evk   schedule 06.04.2018