IntPtr.cs 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195
  1. // Licensed to the .NET Foundation under one or more agreements.
  2. // The .NET Foundation licenses this file to you under the MIT license.
  3. // See the LICENSE file in the project root for more information.
  4. using System.Globalization;
  5. using System.Runtime.CompilerServices;
  6. using System.Runtime.Serialization;
  7. using System.Runtime.Versioning;
  8. #pragma warning disable SA1121 // explicitly using type aliases instead of built-in types
  9. #if BIT64
  10. using nint = System.Int64;
  11. #else
  12. using nint = System.Int32;
  13. #endif
  14. namespace System
  15. {
  16. [Serializable]
  17. [System.Runtime.CompilerServices.TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")]
  18. public readonly struct IntPtr : IEquatable<IntPtr>, ISerializable
  19. {
  20. // WARNING: We allow diagnostic tools to directly inspect this member (_value).
  21. // See https://github.com/dotnet/corert/blob/master/Documentation/design-docs/diagnostics/diagnostics-tools-contract.md for more details.
  22. // Please do not change the type, the name, or the semantic usage of this member without understanding the implication for tools.
  23. // Get in touch with the diagnostics team if you have questions.
  24. private readonly unsafe void* _value; // Do not rename (binary serialization)
  25. [Intrinsic]
  26. public static readonly IntPtr Zero;
  27. [Intrinsic]
  28. [NonVersionable]
  29. public unsafe IntPtr(int value)
  30. {
  31. _value = (void*)value;
  32. }
  33. [Intrinsic]
  34. [NonVersionable]
  35. public unsafe IntPtr(long value)
  36. {
  37. #if BIT64
  38. _value = (void*)value;
  39. #else
  40. _value = (void*)checked((int)value);
  41. #endif
  42. }
  43. [CLSCompliant(false)]
  44. [Intrinsic]
  45. [NonVersionable]
  46. public unsafe IntPtr(void* value)
  47. {
  48. _value = value;
  49. }
  50. private unsafe IntPtr(SerializationInfo info, StreamingContext context)
  51. {
  52. long l = info.GetInt64("value");
  53. if (Size == 4 && (l > int.MaxValue || l < int.MinValue))
  54. throw new ArgumentException(SR.Serialization_InvalidPtrValue);
  55. _value = (void*)l;
  56. }
  57. unsafe void ISerializable.GetObjectData(SerializationInfo info, StreamingContext context)
  58. {
  59. if (info == null)
  60. throw new ArgumentNullException(nameof(info));
  61. info.AddValue("value", ToInt64());
  62. }
  63. public override unsafe bool Equals(object? obj) =>
  64. obj is IntPtr other &&
  65. _value == other._value;
  66. unsafe bool IEquatable<IntPtr>.Equals(IntPtr other) =>
  67. _value == other._value;
  68. public override unsafe int GetHashCode()
  69. {
  70. #if BIT64
  71. long l = (long)_value;
  72. return unchecked((int)l) ^ (int)(l >> 32);
  73. #else
  74. return unchecked((int)_value);
  75. #endif
  76. }
  77. [Intrinsic]
  78. [NonVersionable]
  79. public unsafe int ToInt32()
  80. {
  81. #if BIT64
  82. long l = (long)_value;
  83. return checked((int)l);
  84. #else
  85. return (int)_value;
  86. #endif
  87. }
  88. [Intrinsic]
  89. [NonVersionable]
  90. public unsafe long ToInt64() =>
  91. (nint)_value;
  92. [Intrinsic]
  93. [NonVersionable]
  94. public static unsafe explicit operator IntPtr(int value) =>
  95. new IntPtr(value);
  96. [Intrinsic]
  97. [NonVersionable]
  98. public static unsafe explicit operator IntPtr(long value) =>
  99. new IntPtr(value);
  100. [CLSCompliant(false)]
  101. [Intrinsic]
  102. [NonVersionable]
  103. public static unsafe explicit operator IntPtr(void* value) =>
  104. new IntPtr(value);
  105. [CLSCompliant(false)]
  106. [Intrinsic]
  107. [NonVersionable]
  108. public static unsafe explicit operator void*(IntPtr value) =>
  109. value._value;
  110. [Intrinsic]
  111. [NonVersionable]
  112. public static unsafe explicit operator int(IntPtr value)
  113. {
  114. #if BIT64
  115. long l = (long)value._value;
  116. return checked((int)l);
  117. #else
  118. return (int)value._value;
  119. #endif
  120. }
  121. [Intrinsic]
  122. [NonVersionable]
  123. public static unsafe explicit operator long(IntPtr value) =>
  124. (nint)value._value;
  125. [Intrinsic]
  126. [NonVersionable]
  127. public static unsafe bool operator ==(IntPtr value1, IntPtr value2) =>
  128. value1._value == value2._value;
  129. [Intrinsic]
  130. [NonVersionable]
  131. public static unsafe bool operator !=(IntPtr value1, IntPtr value2) =>
  132. value1._value != value2._value;
  133. [NonVersionable]
  134. public static IntPtr Add(IntPtr pointer, int offset) =>
  135. pointer + offset;
  136. [Intrinsic]
  137. [NonVersionable]
  138. public static unsafe IntPtr operator +(IntPtr pointer, int offset) =>
  139. new IntPtr((nint)pointer._value + offset);
  140. [NonVersionable]
  141. public static IntPtr Subtract(IntPtr pointer, int offset) =>
  142. pointer - offset;
  143. [Intrinsic]
  144. [NonVersionable]
  145. public static unsafe IntPtr operator -(IntPtr pointer, int offset) =>
  146. new IntPtr((nint)pointer._value - offset);
  147. public static int Size
  148. {
  149. [Intrinsic]
  150. [NonVersionable]
  151. get => sizeof(nint);
  152. }
  153. [CLSCompliant(false)]
  154. [Intrinsic]
  155. [NonVersionable]
  156. public unsafe void* ToPointer() => _value;
  157. public override unsafe string ToString() =>
  158. ((nint)_value).ToString(CultureInfo.InvariantCulture);
  159. public unsafe string ToString(string format) =>
  160. ((nint)_value).ToString(format, CultureInfo.InvariantCulture);
  161. }
  162. }