Gewusst wie: Überprüfen auf Verweisgleichheit (Identität) (C#-Programmierhandbuch)How to: Test for Reference Equality (Identity) (C# Programming Guide)

Sie müssen zur Unterstützung von Verweisgleichheitsprüfungen in Ihren Typen keine benutzerdefinierte Logik implementieren.You do not have to implement any custom logic to support reference equality comparisons in your types. Diese Funktionalität wird für alle Typen mit der statischen Object.ReferenceEquals-Methode bereitgestellt.This functionality is provided for all types by the static Object.ReferenceEquals method.

Im folgenden Beispiel wird gezeigt, wie Sie zwei Variablen auf Verweisgleichheit prüfen, d.h. ob diese auf das gleiche Objekt im Arbeitsspeicher verweisen.The following example shows how to determine whether two variables have reference equality, which means that they refer to the same object in memory.

Das Beispiel veranschaulicht außerdem, warum Object.ReferenceEquals immer false für Wertetypen zurückgibt und warum ReferenceEquals nicht zur Prüfung der Übereinstimmung von Zeichenfolgen geeignet ist.The example also shows why Object.ReferenceEquals always returns false for value types and why you should not use ReferenceEquals to determine string equality.

BeispielExample

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) = {0}",
                                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 asignment: ReferenceEquals(tcA, tcB) = {0}",
                                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 = {0} tcB.Num: {1}", tcB.Name, 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 copied on assignment. tsD and tsC have 
            // the same values but are not the same object.
            TestStruct tsD = tsC;
            Console.WriteLine("After asignment: ReferenceEquals(tsC, tsD) = {0}",
                                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) = {0}",
                             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 = \"{0}\" strB = \"{1}\"", strA, 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) = {0}",
                            Object.ReferenceEquals(stringC, strB));

            // The string class overloads the == operator to perform an equality comparison.
            Console.WriteLine("stringC == strB = {0}", 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 asignment: ReferenceEquals(tcA, tcB) = True
    tcB.Name = TestClass 42 tcB.Num: 42
    After asignment: ReferenceEquals(tsC, tsD) = False
    ReferenceEquals(strA, strB) = True
    strA = "Goodbye world!" strB = "Hello world!"
    After strA changes, ReferenceEquals(strA, strB) = False
*/

Die Implementierung von Equals in der universellen Basisklasse System.Object führt auch eine Verweisgleichheitsprüfung aus. Diese Methode wird jedoch nicht empfohlen, da es zu unerwarteten Ergebnissen kommen kann, wenn eine Klasse die Methode überschreibt.The implementation of Equals in the System.Object universal base class also performs a reference equality check, but it is best not to use this because, if a class happens to override the method, the results might not be what you expect. Dasselbe gilt für den ==-Operator und den !=-Operator.The same is true for the == and != operators. Bei Anwendung auf Verweistypen wird mit == und != standardmäßig eine Verweisgleichheitsprüfung ausgeführt.When they are operating on reference types, the default behavior of == and != is to perform a reference equality check. Der Operator kann aber von abgeleiteten Klassen überladen werden und eine Wertgleichheitsprüfung ausführen.However, derived classes can overload the operator to perform a value equality check. Um Fehler möglichst zu vermeiden, verwenden Sie am besten immer ReferenceEquals zur Prüfung der Verweisgleichheit zweier Objekte.To minimize the potential for error, it is best to always use ReferenceEquals when you have to determine whether two objects have reference equality.

Konstantenzeichenfolgen innerhalb der gleichen Assembly werden durch die Laufzeit immer intern gespeichert.Constant strings within the same assembly are always interned by the runtime. Das heißt, es wird nur eine Instanz jedes eindeutigen Zeichenfolgenliterals beibehalten.That is, only one instance of each unique literal string is maintained. Es gibt jedoch keine Garantie dafür, dass zur Laufzeit erstellte Zeichenfolgen oder zwei gleiche Konstantenzeichenfolgen in unterschiedlichen Assemblys intern gespeichert werden.However, the runtime does not guarantee that strings created at runtime are interned, nor does it guarantee that two equal constant strings in different assemblies are interned.

Siehe auchSee Also

ÜbereinstimmungsvergleicheEquality Comparisons