C# sizeof(enum) alternative? (to workaround resharper false error)?
In C# I've got some "safe" API code related to UAC elevation. It involves getting the size of an enum (as follows)
int myEnumSize = sizeof (MyEnum);
The code itself is valid, compiles, works correctly etc. But Resharper falsely flags it as a an error ("Cannot use unsafe construct in safe context") within the solution. (Starting with version 2.0 of C#, applying sizeof to built-in types no longer requires that unsafe mode be used.) I love Resharper, and I love the solution analysis, but with this code in the solution I have a big red dot in the corner that makes me always think something is broken. If I tell resharper to ignore this error it comes back within minutes.
I would raise the issue with JetBrains, but I looked on their tracker and they've already got one logged that has been ignored since March. Looking further they have at least two other instances of this logged going back several years, both were dismissed with a "no-repro" status. I don't want to sign-up to their tracker just to up-vote this bug. I could still end-up holding my breath for years. The fastest way forward is just to work-around the issue.
What is the best alternative that is still correct and has the least chance of causing a maintainer any trouble later on?
I could hard-code it to:
int myEnumSize = 4;
Is there are more correct solution? -- which doesn't use sizeof(enum)?
Btw:
Marshal.SizeOf()
is completely "safe" but returns the wro开发者_Python百科ng size.
PS. The code in questions is heavily influenced by the UACSelfElvation demo code from Microsoft. If you want more details. But I don't think they are relevant.
Looks ugly, but may work:
int myEnumSize = Marshal.SizeOf(Enum.GetUnderlyingType(typeof(MyEnum)));
Edit by John Gietzen:
Proof:
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): 8Marshal.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
The correct solution would be to add a comment before this line stating that the warning generated by the tool is incorrect. This will prevent future maintainers from becoming confused and trying to fix something that's not broken.
I imagine (if you really, really want to) you could use a switch/case on the enumeration. But my guess is the sizeof is there for a reason.
If you're interested in getting the size of the underlying data object of the enum, perhaps a better way would be to get hold of the System.Type object first.
Type type = typeof (MyEnum);
int enumSize = sizeof (Enum.GetUnderlyingType (type));
You can ignore it in ReSharper but it's a bit of a pain and compromises/changes your design. You can put the Enum definition and a method to get the size (using sizeof) in a class in it's own file and click on ReSharper > Options... > Code Inspection > Settings > Edit Items to Skip and then select that file (I'm using R# 5.1).
Obviously you won't get code analysis but you still get the code format cleaning.
精彩评论