Ширина байта типа значения
Я хотел бы передать тип значения в функцию и установить для него повторяющуюся битовую комбинацию (FF, AA и т. Д.) По всей ширине переменной. Прямо сейчас я передаю значение с
void foo(T val), где T: struct
поэтому я могу использовать любой тип значения. Проблема в том, что компилятор не позволит мне использовать sizeof(T), потому что T может быть ссылочным типом (за исключением того, что он не может, благодаря ограничению "где"). Я мог бы жестко кодировать все типы значений и проверять их самостоятельно, но это явно кажется излишним. Есть ли более простой способ сделать это?
Просто чтобы уточнить: если я прохожу byteInt64
Я хочу установить его на 0xFFFFFFFF.
Я старался Convert.ChangeType(0xFFFFFFFF, typeof(T))
, но это бросает, если val
например, чар. Я мог бы решить эту проблему: а) выяснить, насколько широк тип-параметр и "построить" достаточно большое значение для заполнения, б) выяснить, как принять любой тип значения (и только типы значений), например sizeof() будет работать, или c) выяснить, как автоматически обрезать 0xFFFFFFFF до правильной ширины для переменной.
4 ответа
Можете ли вы использовать метод Marshal.SizeOf?
http://msdn.microsoft.com/en-us/library/y3ybkfb3.aspx
РЕДАКТИРОВАТЬ: NB! Прочитайте комментарий Тор Хаугена, прежде чем делать это.
Вы также можете разыграть -1 как то, что вы проходите. Независимо от длины переменной, -1 всегда все F. Пока вы используете примитивные типы, это никогда не должно вызывать особых проблем.
Краткое объяснение того, почему это работает:
Все целые числа в системе содержатся в 2-х обозначениях дополнения. Это означает, что отрицательные числа - это не просто число со знаковым битом. Чтобы создать дополнение 2, просто переверните все биты и добавьте 1.
эрго:
-1 = нет (1) + 1
так
0000 0001 > 1111 1110 > 1111 1111 = 0xFF
Это всегда даст вам все 1 для любой длины элемента.
РЕДАКТИРОВАТЬ:
используйте оператор sizeof, чтобы получить размер типа в байтах, используйте typeof, чтобы получить тип, тогда я бы использовал сдвиг битов в цикле, чтобы заполнить элемент sooo...
for (int i = 0; i < sizeof(typeof(input)); i++)
{
input = (input << 8) | Ox<Pattern>
}
пожалуйста, прости мои синтаксические ошибки, давно, но это должно делать то, что вы хотите.
Вы можете использовать двоичную сериализацию, чтобы получить размер, но вам нужно сериализовать два массива объекта, один с двумя элементами, один с одним элементом, и вычесть один размер из другого, чтобы удалить издержки сериализации. Остерегайтесь таких типов, как System.Decimal, которые имеют разную сериализованную длину для разных значений.
Я думал, что я на что-то - sizeof() будет работать для структур, но только в небезопасных блоках. Итак, я попробовал:
// compile with /unsafe
public unsafe void Foo<T>(T val) where T : struct
{
// Works!
int size1 = sizeof(SomeStruct);
// Doesn't work, alas
int size2 = sizeof(T);
}
Кажется, у sizeof есть проблема с параметрами общего типа. Так что не уходи.
Как я прокомментировал в ответе norheim.se, вы должны знать, что Marshal.SizeOf() не обязательно даст вам размер вашего шрифта во время выполнения, поэтому я бы не рекомендовал его.
Рискуя насмешками за небрежность, я бы честно посчитал простой switch
заявление. Если ваши типы стоимости будут на складе int
s, long
s, byte
и т. д., существует множество возможностей. И вы должны помнить, что установка битового шаблона может быть другой задачей в зависимости от того, подписан тип или нет! Переключение позволит легко иметь дело с таким.