-
Notifications
You must be signed in to change notification settings - Fork 5.4k
Description
Rationale
The .NET framework provides the System.IntPtr and System.UIntPtr types which wrap the native int IL primitive (as per ECMA-335).
These types are frequently used to represent both handles/pointers and integers whose size depend on the underlying platform.
When being used to represent the latter (platform sized integer) type, users may find a difficult time performing some basic operations, such as comparing two native ints to determine sort order.
Additionally, with the proposed C# Native Sized Number Types (dotnet/csharplang#435) where language support for the primitive operations will be exposed (currently this will be done via partial erasure), the use of System.IntPtr and System.UIntPtr as native int types will become more prevalent (F# is one language that already exposes these operators).
As such, these types should be modified to expose a set of APIs that make other common operations easier to perform.
Proposed API
The proposed API here only shows the members that would be new to the types.
System.IntPtr
[StructLayout(LayoutKind.Sequential)] // This is implicitly set by the compiler, but should be explicitly declared, as it is done for System.Int32
public struct IntPtr : IComparable, IComparable<IntPtr>, IFormattable
{
public static IntPtr MaxValue { get; }
public static IntPtr MinValue { get; }
public static int ShiftMask { get; } // Runtime constant equivalent to (sizeof(nint) * 8) - 1
int IComparable.CompareTo(object value); // Explicitly implemented to ensure that users still get compile-time type checking
public int CompareTo(IntPtr value);
public bool Equals(IntPtr other); // This is currently explicitly implemented as IEquatable<IntPtr>.Equals(IntPtr other)
public string ToString(IFormatProvider provider);
public string ToString(string format, IFormatProvider provider);
public static IntPtr Parse(string s);
public static IntPtr Parse(string s, NumberStyles style);
public static IntPtr Parse(string s, IFormatProvider provider);
public static IntPtr Parse(string s, NumberStyles style, IFormatProvider provider);
public static bool TryParse(string s, out IntPtr result);
public static bool TryParse(string s, NumberStyles style, IFormatProvider provider, out IntPtr result);
}System.UIntPtr
public struct UIntPtr : IComparable, IComparable<UIntPtr>, IFormattable
{
public static UIntPtr MaxValue { get; }
public static UIntPtr MinValue { get; }
public static int ShiftMask { get; } // Runtime constant equivalent to (sizeof(nint) * 8) - 1
int IComparable.CompareTo(object value); // Explicitly implemented to ensure that users still get compile-time type checking
public int CompareTo(UIntPtr value);
public bool Equals(UIntPtr other); // This is currently explicitly implemented as IEquatable<UIntPtr>.Equals(UIntPtr other)
public string ToString(string format); // This is currently exposed on System.IntPtr, but not on System.UIntPtr
public string ToString(IFormatProvider provider);
public string ToString(string format, IFormatProvider provider);
public static UIntPtr Parse(string s);
public static UIntPtr Parse(string s, NumberStyles style);
public static UIntPtr Parse(string s, IFormatProvider provider);
public static UIntPtr Parse(string s, NumberStyles style, IFormatProvider provider);
public static bool TryParse(string s, out UIntPtr result);
public static bool TryParse(string s, NumberStyles style, IFormatProvider provider, out UIntPtr result);
}Other Thoughts
Implementing System.IConvertible is done by the other primitive types and may be useful in some cases here as well.
It might be worthwhile having int implement IComparable<IntPtr> and IEquatable<IntPtr>, given that these are valid operations as well.