형식에서 참조 같음 비교를 지원하기 위해 사용자 지정 논리를 구현할 필요가 없습니다. 이 기능은 정적 Object.ReferenceEquals 메서드에서 모든 형식에 대해 제공됩니다.
다음 예제에서는 두 변수에 참조 같음있는지 여부를 확인하는 방법을 보여 줍니다. 즉, 메모리에서 동일한 개체를 참조합니다.
이 예제에서는 Object.ReferenceEquals 항상 값 형식에 대한 false
반환하는 이유도 보여 있습니다. 이는 각 값 형식 인수에 대해 별도의 개체 인스턴스를 만드는 boxing때문입니다. 또한 ReferenceEquals 사용하여 문자열 같음을 확인하면 안 됩니다.
예시
using System.Text;
namespace TestReferenceEquality
{
struct TestStruct
{
public int Num { get; private set; }
public string Name { get; private set; }
public TestStruct(int i, string s) : this()
{
Num = i;
Name = s;
}
}
class TestClass
{
public int Num { get; set; }
public string? Name { get; set; }
}
class Program
{
static void Main()
{
// Demonstrate reference equality with reference types.
#region ReferenceTypes
// Create two reference type instances that have identical values.
TestClass tcA = new TestClass() { Num = 1, Name = "New TestClass" };
TestClass tcB = new TestClass() { Num = 1, Name = "New TestClass" };
Console.WriteLine($"ReferenceEquals(tcA, tcB) = {Object.ReferenceEquals(tcA, tcB)}"); // false
// After assignment, tcB and tcA refer to the same object.
// They now have reference equality.
tcB = tcA;
Console.WriteLine($"After assignment: ReferenceEquals(tcA, tcB) = {Object.ReferenceEquals(tcA, tcB)}"); // true
// Changes made to tcA are reflected in tcB. Therefore, objects
// that have reference equality also have value equality.
tcA.Num = 42;
tcA.Name = "TestClass 42";
Console.WriteLine($"tcB.Name = {tcB.Name} tcB.Num: {tcB.Num}");
#endregion
// Demonstrate that two value type instances never have reference equality.
#region ValueTypes
TestStruct tsC = new TestStruct( 1, "TestStruct 1");
// Value types are boxed into separate objects when passed to ReferenceEquals.
// Even if the same variable is used twice, boxing ensures they are different instances.
TestStruct tsD = tsC;
Console.WriteLine($"After assignment: ReferenceEquals(tsC, tsD) = {Object.ReferenceEquals(tsC, tsD)}"); // false
#endregion
#region stringRefEquality
// Constant strings within the same assembly are always interned by the runtime.
// This means they are stored in the same ___location in memory. Therefore,
// the two strings have reference equality although no assignment takes place.
string strA = "Hello world!";
string strB = "Hello world!";
Console.WriteLine($"ReferenceEquals(strA, strB) = {Object.ReferenceEquals(strA, strB)}"); // true
// After a new string is assigned to strA, strA and strB
// are no longer interned and no longer have reference equality.
strA = "Goodbye world!";
Console.WriteLine($"strA = '{strA}' strB = '{strB}'");
Console.WriteLine("After strA changes, ReferenceEquals(strA, strB) = {0}",
Object.ReferenceEquals(strA, strB)); // false
// A string that is created at runtime cannot be interned.
StringBuilder sb = new StringBuilder("Hello world!");
string stringC = sb.ToString();
// False:
Console.WriteLine($"ReferenceEquals(stringC, strB) = {Object.ReferenceEquals(stringC, strB)}");
// The string class overloads the == operator to perform an equality comparison.
Console.WriteLine($"stringC == strB = {stringC == strB}"); // true
#endregion
// Keep the console open in debug mode.
Console.WriteLine("Press any key to exit.");
Console.ReadKey();
}
}
}
/* Output:
ReferenceEquals(tcA, tcB) = False
After assignment: ReferenceEquals(tcA, tcB) = True
tcB.Name = TestClass 42 tcB.Num: 42
After assignment: ReferenceEquals(tsC, tsD) = False
ReferenceEquals(strA, strB) = True
strA = "Goodbye world!" strB = "Hello world!"
After strA changes, ReferenceEquals(strA, strB) = False
ReferenceEquals(stringC, strB) = False
stringC == strB = True
*/
Equals
유니버설 기본 클래스에서 System.Object 구현은 참조 같음 검사도 수행하지만 클래스가 메서드를 재정의하는 경우 결과가 예상과 다를 수 있으므로 이를 사용하지 않는 것이 가장 좋습니다.
==
및 !=
연산자도 마찬가지입니다. 참조 형식에서 작동하는 경우 ==
및 !=
기본 동작은 참조 같음 검사를 수행하는 것입니다. 그러나 파생 클래스는 연산자를 오버로드하여 값 같음 검사를 수행할 수 있습니다. 오류 가능성을 최소화하려면 두 개체에 참조 같음이 있는지 확인해야 하는 경우 항상 ReferenceEquals 사용하는 것이 가장 좋습니다.
동일한 어셈블리 내의 상수 문자열은 항상 런타임에 의해 인턴됩니다. 즉, 각 고유 리터럴 문자열의 인스턴스는 하나만 유지 관리됩니다. 그러나 런타임은 런타임에 만든 문자열이 인턴되는 것을 보장하지 않으며, 서로 다른 어셈블리의 동일한 두 상수 문자열이 인턴되는 것을 보장하지도 않습니다.
메모
ReferenceEquals
는 false
때문에 값 형식에 대해 을 반환합니다. 각 인수는 독립적으로 별도의 객체로 박싱되기 때문입니다.
또한 참조하십시오
.NET