diff --git a/src/libraries/System.Private.CoreLib/src/System/Reflection/Pointer.cs b/src/libraries/System.Private.CoreLib/src/System/Reflection/Pointer.cs
index 098ddfdcebaff1..ef8e82a9b0f18f 100644
--- a/src/libraries/System.Private.CoreLib/src/System/Reflection/Pointer.cs
+++ b/src/libraries/System.Private.CoreLib/src/System/Reflection/Pointer.cs
@@ -39,6 +39,18 @@ public static object Box(void* ptr, Type type)
return ((Pointer)ptr)._ptr;
}
+ public override unsafe bool Equals(object? obj)
+ {
+ if (obj is Pointer pointer)
+ {
+ return _ptr == pointer._ptr;
+ }
+
+ return false;
+ }
+
+ public override unsafe int GetHashCode() => ((nuint)_ptr).GetHashCode();
+
void ISerializable.GetObjectData(SerializationInfo info, StreamingContext context)
{
throw new PlatformNotSupportedException();
diff --git a/src/libraries/System.Reflection/tests/PointerTests.cs b/src/libraries/System.Reflection/tests/PointerTests.cs
new file mode 100644
index 00000000000000..cbcf7828df59ce
--- /dev/null
+++ b/src/libraries/System.Reflection/tests/PointerTests.cs
@@ -0,0 +1,136 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+using Xunit;
+using System.Reflection;
+
+namespace System.Reflection.Tests
+{
+ public class PointerTests
+ {
+ public unsafe struct BitwiseComparable
+ {
+ public int* PublicInt;
+ }
+
+ public unsafe struct MemberwiseComparable
+ {
+ public string ReferenceType;
+ public int* PublicInt;
+ }
+
+ [Fact]
+ public unsafe void EqualBitwiseComparables_AreEqual()
+ {
+ int someNumber = 1;
+ var a = new BitwiseComparable();
+ a.PublicInt = &someNumber;
+ BitwiseComparable b = a;
+
+ Assert.True(a.Equals(b));
+ Assert.Equal(a.GetHashCode(), b.GetHashCode());
+ }
+
+ [Fact]
+ public unsafe void UnequalBitwiseComparables_AreUnequal()
+ {
+ int someNumber = 1;
+ var a = new BitwiseComparable();
+ a.PublicInt = &someNumber;
+ var b = new BitwiseComparable();
+
+ Assert.False(a.Equals(b));
+ }
+
+ [Fact]
+ public unsafe void SameBitwiseComparable_EqualWithSelf()
+ {
+ int someNumber = 1;
+ var a = new BitwiseComparable();
+ a.PublicInt = &someNumber;
+
+ Assert.True(a.Equals(a));
+ }
+
+ [Fact]
+ public unsafe void EqualMemberwiseComparables_AreEqual()
+ {
+ int someNumber = 1;
+ var a = new MemberwiseComparable();
+ a.PublicInt = &someNumber;
+ MemberwiseComparable b = a;
+
+ Assert.True(a.Equals(b));
+ Assert.Equal(a.GetHashCode(), b.GetHashCode());
+ }
+
+ [Fact]
+ public unsafe void UnequalMemberwiseComparables_AreUnequal()
+ {
+ int someNumber = 1;
+ var a = new MemberwiseComparable();
+ a.PublicInt = &someNumber;
+ var b = new MemberwiseComparable();
+
+ Assert.False(a.Equals(b));
+ }
+
+ [Fact]
+ public unsafe void SameMemberwiseComparable_EqualWithSelf()
+ {
+ int someNumber = 1;
+ var a = new MemberwiseComparable();
+ a.PublicInt = &someNumber;
+
+ Assert.True(a.Equals(a));
+ }
+
+ [Fact]
+ public unsafe void EqualPointers_AreEqual()
+ {
+ object a = Pointer.Box((void*)0x12340000, typeof(int*));
+ object b = Pointer.Box((void*)0x12340000, typeof(int*));
+
+ Assert.True(a.Equals(b));
+ Assert.Equal(a.GetHashCode(), b.GetHashCode());
+ }
+
+ [Fact]
+ public unsafe void Nullptrs_AreEqual()
+ {
+ object a = Pointer.Box(null, typeof(int*));
+ object b = Pointer.Box(null, typeof(int*));
+
+ Assert.True(a.Equals(b));
+ Assert.Equal(a.GetHashCode(), b.GetHashCode());
+ }
+
+ [Fact]
+ public unsafe void DifferentPointerTypes_AreEqual()
+ {
+ object a = Pointer.Box((void*)0x12340000, typeof(int*));
+ object b = Pointer.Box((void*)0x12340000, typeof(uint*));
+
+ Assert.True(a.Equals(b));
+ Assert.Equal(a.GetHashCode(), b.GetHashCode());
+ }
+
+ [Fact]
+ public unsafe void DifferentPointers_AreUnequal()
+ {
+ object a = Pointer.Box((void*)0x12340000, typeof(int*));
+ object b = Pointer.Box((void*)0x56780000, typeof(int*));
+
+ Assert.False(a.Equals(b));
+ }
+
+ [Fact]
+ public unsafe void DifferentPointerTypes_Null_AreEqual()
+ {
+ object a = Pointer.Box(null, typeof(int*));
+ object b = Pointer.Box(null, typeof(long*));
+
+ Assert.True(a.Equals(b));
+ }
+ }
+}
diff --git a/src/libraries/System.Reflection/tests/System.Reflection.Tests.csproj b/src/libraries/System.Reflection/tests/System.Reflection.Tests.csproj
index 3d22e60dfd35c5..f480b9783c53d9 100644
--- a/src/libraries/System.Reflection/tests/System.Reflection.Tests.csproj
+++ b/src/libraries/System.Reflection/tests/System.Reflection.Tests.csproj
@@ -30,6 +30,7 @@
+
diff --git a/src/libraries/System.Runtime/ref/System.Runtime.cs b/src/libraries/System.Runtime/ref/System.Runtime.cs
index 2a0a3921bee9e7..7a44865a21f3ce 100644
--- a/src/libraries/System.Runtime/ref/System.Runtime.cs
+++ b/src/libraries/System.Runtime/ref/System.Runtime.cs
@@ -8551,6 +8551,8 @@ internal Pointer() { }
public unsafe static object Box(void* ptr, System.Type type) { throw null; }
void System.Runtime.Serialization.ISerializable.GetObjectData(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context) { }
public unsafe static void* Unbox(object ptr) { throw null; }
+ public override bool Equals(object? obj) { throw null; }
+ public override int GetHashCode() { throw null; }
}
[System.FlagsAttribute]
public enum PortableExecutableKinds