С# sizeof(enum) альтернатива? (для обхода ложной ошибки решарпера)?

В С# у меня есть некоторый «безопасный» код API, связанный с повышением прав UAC. Это включает в себя получение размера перечисления (следующим образом)

int myEnumSize = sizeof (MyEnum);

Сам код действителен, компилируется, работает правильно и т. д. Но Resharper ложно помечает его как ошибку («Невозможно использовать небезопасную конструкцию в безопасном контексте») в решении. (Начиная с версии 2.0 C# применение sizeof к встроенным типам больше не требует, чтобы использовать небезопасный режим.) Я люблю Resharper и люблю анализ решений, но с этим кодом в решении у меня появляется большая красная точка в углу, из-за которой я всегда думаю, что что-то не работает. Если я скажу resharper игнорировать эту ошибку, она вернется в течение нескольких минут.

Я бы поднял этот вопрос с JetBrains, но я посмотрел на их трекере, и они уже зарегистрировали один, который игнорировался с марта. Глядя дальше, у них есть как минимум два других экземпляра этого журнала, зарегистрированных несколько лет назад, оба были уволены со статусом «невоспроизведение». Я не хочу подписываться на их трекер только для того, чтобы проголосовать за эту ошибку. Я все еще мог бы задерживать дыхание на долгие годы. Самый быстрый путь вперед — просто обойти проблему.

Какова наилучшая альтернатива, которая по-прежнему верна и имеет наименьшие шансы вызвать какие-либо проблемы у сопровождающего в дальнейшем?

Я мог бы жестко закодировать это:

int myEnumSize = 4;  

Есть ли более правильное решение? -- который не использует sizeof(enum)?

Кстати:

 Marshal.SizeOf() 

полностью «безопасен», но возвращает неправильный размер.

PS. На рассматриваемый код сильно повлиял демонстрационный код UACSelfElvation от Microsoft. Если вы хотите больше деталей. Но я не думаю, что они актуальны.


person DanO    schedule 18.11.2010    source источник


Ответы (5)


Выглядит некрасиво, но может работать:

int myEnumSize = Marshal.SizeOf(Enum.GetUnderlyingType(typeof(MyEnum)));


Под редакцией Джона Гитцена:
Доказательство:

enum Enum1 : sbyte { A, B, C, D }
enum Enum2 : short { A, B, C, D }
enum Enum3 : int { A, B, C, D }
enum Enum4 : long { A, B, C, D }

enum Enum5 : byte { A, B, C, D }
enum Enum6 : ushort { A, B, C, D }
enum Enum7 : uint { A, B, C, D }
enum Enum8 : ulong { A, B, C, D }

sizeof(Enum1): 1
sizeof(Enum2): 2
sizeof(Enum3): 4
sizeof(Enum4): 8
sizeof(Enum5): 1
sizeof(Enum6): 2
sizeof(Enum7): 4
sizeof(Enum8): 8

Marshal.SizeOf(Enum.GetUnderlyingType(typeof(Enum1))): 1
Marshal.SizeOf(Enum.GetUnderlyingType(typeof(Enum2))): 2
Marshal.SizeOf(Enum.GetUnderlyingType(typeof(Enum3) )): 4
Marshal.SizeOf(Enum.GetUnderlyingType(typeof(Enum4))): 8
Marshal.SizeOf(Enum.GetUnderlyingType(typeof(Enum5))): 1
Marshal.SizeOf(Enum .GetUnderlyingType(typeof(Enum6))): 2
Marshal.SizeOf(Enum.GetUnderlyingType(typeof(Enum7))): 4
Marshal.SizeOf(Enum.GetUnderlyingType(typeof(Enum8))): 8

person max    schedule 18.11.2010
comment
Идеально. Это именно то, что я искал. Это работает, и хотя это не красиво, с комментарием, показывающим более краткий способ и указывающим, почему он не использовался здесь, это будет здорово. Спасибо. Это именно то, на что я надеялся, когда спрашивал Stackoverflow. - person DanO; 19.11.2010

Правильным решением было бы добавить комментарий перед этой строкой о том, что предупреждение, сгенерированное инструментом, неверно. Это не позволит будущим сопровождающим запутаться и попытаться исправить то, что не сломано.

person cdhowie    schedule 18.11.2010
comment
Как это решит его проблему? - person John Gietzen; 18.11.2010
comment
Если не считать исправления ошибки в Resharper, решения действительно нет, не так ли? - person cdhowie; 18.11.2010
comment
Нет, не исправить. Но обходной путь? может быть. Вот что он спрашивает. - person John Gietzen; 18.11.2010
comment
И я говорю, что обходной путь не будет таким эффективным, как просто отметить в источнике, что созданное предупреждение неверно. Я сомневаюсь, что какое-либо обходное решение приведет к более читаемому и поддерживаемому коду. - person cdhowie; 18.11.2010
comment
Он пытается избежать отчета об ошибках, чтобы видеть, когда ошибки действительно возникают. Этот ответ не является ответом. - person John Gietzen; 19.11.2010

Я предполагаю (если вы действительно этого хотите), вы могли бы использовать переключатель/регистр в перечислении. Но я предполагаю, что sizeof существует не просто так.

person rtpg    schedule 18.11.2010

Если вы заинтересованы в получении размера базового объекта данных перечисления, возможно, лучшим способом было бы сначала получить объект System.Type.

Type type = typeof (MyEnum);
int enumSize = sizeof (Enum.GetUnderlyingType (type));
person AK.    schedule 18.11.2010

Вы можете игнорировать это в ReSharper, но это немного неудобно и ставит под угрозу/меняет ваш дизайн. Вы можете поместить определение Enum и метод получения размера (используя sizeof) в классе в его собственном файле и щелкнуть ReSharper > Параметры... > Проверка кода > Настройки > Редактировать элементы для пропуска, а затем выбрать этот файл (я использую R# 5.1).

Очевидно, вы не получите анализ кода, но вы все равно получите очистку формата кода.

person Luke Hutton    schedule 18.11.2010