Ответ 1
Хотя этот метод действительно использует инструкцию sizeof
IL - существует разница с регулярным оператором sizeof
, потому что этот оператор нельзя применять к произвольным типам:
Используется для получения размера в байтах для неуправляемого типа. Неуправляемый типы включают встроенные типы, перечисленные в таблице, которые следует, а также следующее:
Типы перечислений
Типы указателей
Определяемые пользователем структуры, которые не содержат поля или свойства, которые являются ссылочными типами
Если вы попытаетесь написать аналог Unsafe.SizeOf
- он не будет работать:
public static int SizeOf<T>()
{
// nope, will not compile
return sizeof(T);
}
Итак, Unsafe.SizeOf
отменяет ограничения оператора sizeof
и позволяет вам использовать инструкцию IL sizeof
с произвольными типами (включая ссылочные типы, для которых он будет возвращать размер ссылки).
Как для конструкции атрибута, вы видите в IL - это не означает, что для каждого вызова будет создан экземпляр атрибута - это просто синтаксис IL для связывания атрибутов с различными членами (в этом случае метод).
Примеры:
public struct Test {
public int Int1;
}
static void Main() {
// works
var s1 = Unsafe.SizeOf<Test>();
// doesn't work, need to mark method with "unsafe"
var s2 = sizeof(Test);
}
Другой пример:
public struct Test {
public int Int1;
public string String1;
}
static unsafe void Main() {
// works, return 16 in 64bit process - 4 for int, 4 for padding, because
// alignment of the type is the size of its largest element, which is 8
// and 8 for string
var s1 = Unsafe.SizeOf<Test>();
// doesn't work even with unsafe,
// cannot take size of variable of managed type "Test"
// because Test contains field of reference type (string)
var s2 = sizeof(Test);
}