CLS compliant types in P/Invoke helper assembly
Having a separate helper assembly containing only P/Invoke declarations for legacy 3rd party components, I wonder which of these two ways is The Better One™ if the开发者_Go百科 assembly must be marked CLS compliant:
- Use
Int32
in a public P/Invoke declaration where the unmanaged declaration hasunsigned int
. - Use
UInt32
in an internal P/Invoke declaration where the unmanaged declaration hasunsigned int
, and wrap it in a public method that takes anInt32
and converts it toUInt32
when calling the internal method.
What are the up- and downsides of these?
The P/Invoke marshaller isn't going to complain when the uint gets too big, you'll just end up with a negative int. The extra layer does allow you to use the checked keyword to generate an OverflowException. Which is fairly desirable.
Whether it is worth the hassle is a secondary question. Lots of APIs, like Win32, use unsigned as a logical constraint. Like the length of the string or the size of a block of memory, it can never be negative. In practice, such a number can never overflow. Because it isn't possible to allocate that much memory. I can't remember running once in an API where it was a slam-dunk that uint should be used. As such, I think you're fine just using a straight pinvoke declaration with ints.
I don't think you'd get correct behavior if you went with option 1. Int32 can only go as high as 2,147,483,647. Whereas the unsigned int goes up to 4,294,967,295. As long as you KNOW you don't need any values above 2 billion, it doesn't really matter. But to be technically correct, the public interface should expose a larger type and perform bounds checking to make sure it fits in an unsigned int and throw an exception if it doesn't. An Int64 will do (9,223,372,036,854,775,807).
精彩评论