CLS-compliant alternative for ulong property
Background
I am writing a managed x64 assembler (which is开发者_运维问答 also a library), so it has multiple classes which define an unsigned 64-bit integer property for use as addresses and offsets. Some are file offsets, others are absolute addresses (relative to the main memory) and again others are relative virtual addresses.
Problem
I use the ulong
datatype for the properties in the mentioned scenarios, and this works fine. However, such properties are not CLS-compliant. I can mark them as [ClsCompliant(false)]
, but then I need to provide a CLS-compliant alternative to users of the library.
Options and questions
Some suggest providing an alternative property with a bigger data type, but this is not an option because there is no bigger signed integer primitive which could hold all values from 0
to UInt64.MaxValue
.
I would rather not mark my entire assembly as non-CLS-compliant, because in most usage scenario's, not all the possible values up to UInt64.MaxValue
are used. So, for e.g. Address
I could provide an alternative long
property AddressAlternative
, which only accepts positive values. However, what should happen when Address
somehow contains a value above Int64.MaxValue
. Should AddressAlternative
throw some exception?
And what would be an appropriate name for AddressAlternative
?
Providing an alternative for every usage of ulong
would result in many 'double' properties. Is there a better way to do this? Note that not all usages of ulong
properties have the same semantics, so a single struct
would not cut it.
And finally, I have the same CLS compliance problem in constructor parameters. So should I provide an alternative overload accepting long
for such a parameter?
I do not mind restricting the use of (some functionality) of the library when it is used from a CLS-only context, as long as it can be used in most scenarios.
but when it represents an unsigned address above Int64.MaxValue
You are using the wrong type, addresses must be stored in IntPtr or UIntPtr. There is just no way your problem is realistic. If you can't afford to lose the single bit in UInt64 then you are way too close to overflow. If this number represents an index then a plain Int32 will be fine, .NET memory blobs are limited to 2 gigabyte, even on a 64-bit machine.
If it is an address then IntPtr will be fine for a very, very long time. Currently available hardware is 4.5 orders of magnitude away from reaching that limit. Very drastic hardware redesign will be needed to get close, you'll have much bigger problems to worry about when that day ever comes. Nine exabyte of virtual memory is enough for everybody until I retire.
Microsoft defines a 64-bit address as Int64, not UInt64, so you can still be CLS compliant.
Please refer to http://msdn.microsoft.com/en-us/library/837ksy6h.aspx.
Which basically says:
IntPtr Constructor (Int64)
Initializes a new instance of IntPtr using the specified 64-bit pointer.
Parameters value Type: System.Int64 A pointer or handle contained in a 64-bit signed integer.
And yes, I just did a quick test and the following worked fine in a project targeted for either x64 or Any CPU. I placed a brekpoint in the code and examined x
. However, when targeted for only x86, it will throw an exception.
using System;
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
IntPtr x = new IntPtr(long.MaxValue);
}
}
}
But, if it turns out that you really need that extra bit. You could provide two libraries. One that is CLS-Compliant and one that is not--user's choice. This could be accomplished by using #if statements and using Conditional Compilation Symbols. This way, you can define the same variable name, but with different definitions. http://msdn.microsoft.com/en-us/library/4y6tbswk.aspx
精彩评论