Heim Backend-Entwicklung C#.Net-Tutorial .NET Framework-Code-Beispiel für die gemeinsame Nutzung von Referenz-Traps

.NET Framework-Code-Beispiel für die gemeinsame Nutzung von Referenz-Traps

Mar 18, 2017 pm 01:39 PM

1 Werte sind gleich, Objekte sind standardmäßig gleich?
Was sind die Standardregeln zum Bestimmen der Existenz eines -referenzierten -Typs in einem .net-Container? Bestimmen Sie, ob die Zeigerwerte gleich sind.

        private static List<int> list;        
        static void Main(string[] args)
        {            
        //新建实例instance1
            MyObject instance1 = new MyObject();
            instance1.Value = 10;            
            //新建list
            List<MyObject> list = new List<MyObject>();            
            //引用实例instance1
            list.Add(instance1);            
            //新建实例:instance2
            MyObject instance2 = new MyObject();            
            //赋值为instance1.Value
            instance2.Value = instance1.Value;       
        }
    }
Nach dem Login kopieren

Gebraucht Modell Klasse:

            public class MyObject
            {
                public int Value { get; set; }
            }
Nach dem Login kopieren

Führen Sie unten einen Test durch:

            //即便Value相等,instance2与instance1的内存地址不相等!
            bool isExistence1 = list.Contains(instance2);            //isExistence1 : false;
Nach dem Login kopieren

Das Ergebnis dieses Tests istfalse, weil sie auf unterschiedliche Speicheradressen verweisen, obwohl die Werte gleich sind, was bei „Werte sind gleich, Objekte sind nicht gleich“ der Fall ist.
 
Wenn ein Referenztyp basierend auf dem Wert eines der Attribute bestimmen möchte, ob er gleich ist, muss er die IEquatableSchnittstelle implementieren!
Wenn Sie weiterhin anhand der Gleichheit der Werte sehen möchten, ob Objekte gleich sind, lesen Sie bitte den Artikel: C#Container, Schnittstellenklassen, Leistung

2 Referenzfallen?

 Ein Objekt verweist auf ein anderes Objekt. Wenn sich eines ändert, ändert sich auch das andere . Wenn beispielsweise zwei Wörterbücher zusammengeführt werden, ist das Zusammenführungsergebnis korrekt, das ursprüngliche Objekt wird jedoch versehentlich geändert.

Hier ist ein Beispiel:

            var dict1 = new Dictionary<string, List<string>>();
            dict1.Add("qaz",new List<string>(){"100"});//含有qaz键
            dict1.Add("wsx",new List<string>(){"13"});            var dict2 = new Dictionary<string, List<string>>();
            dict2.Add("qaz", new List<string>() { "11" });//也含有qaz键
            dict2.Add("edc", new List<string>() { "17" });            //合并2个字典到dict            
            var dictCombine = new Dictionary<string, List<string>>();
            foreach (var ele in dict1) //拿到dict1
            {
               dictCombine .Add(ele.Key,ele.Value); 
            }

            foreach (var ele in dict2) //拿到dict2
            {                if(dictCombine.ContainsKey(ele.Key))//检查重复
                   dictCombine [ele.Key].AddRange(ele.Value); 
                else
                {
                    dictCombine .Add(ele.Key,ele.Value); 
                }
            }
Nach dem Login kopieren

Das Ergebnis von dictCombine ist korrekt, {"qaz", "100" und "11"}, { "wsx","13"}, {"edc","17"}
Aber was ist mit dem Ergebnis von dict1? Wurde geändert! dict1 wurde unerwartet zu {"qaz", "100" und "11"}, {"wsx", "13"}. Korrekte Zusammenführung, dict1 sollte nicht geändert werden!

Analyse des Grundes

dictCombine fügt zunächst den Schlüsselwert von dict1 hinzu, dh der Schlüsselwert von dictCombine verweist alle auf den Schlüsselwert von dict1; Als nächstes ermitteln Sie beim Zusammenführen von dictCombine zunächst, ob dictCombine den Schlüssel von dictCombine enthält. Der Wert bezieht sich auf dasselbe Objekt, das heißt, dieser Wert wird zum Schlüssel von dict1 hinzugefügt. Überprüfung, ob die Referenzen dictCombine[ele.Key] und dict1[ele.Key] gleich sind:

bool flag = object.ReferenceEquals(dictCombine[ele.Key], dict1[ele.Key]);//true
Nach dem Login kopieren

Richtige Lösung

dictCombine[ele.Key] vermeiden und dict1 [ele.Key] Referenzgleichheit! ! !

Dictionary<string, List<string>> dict = new Dictionary<string, List<string>>();            
//先把键都合并到dictCombine中,值都是新创建的
            foreach (var key in dict1.Keys)
            {                if (!dictCombine.ContainsKey(key))
                    dictCombine.Add(key, new List<string>());
            }            foreach (var key in dict2.Keys)
            {                if (!dictCombine.ContainsKey(key))
                    dictCombine.Add(key, new List<string>());
            }     //分别将值添加进去
            foreach (var ele in dict1)
            {
                dictCombine[ele.Key].AddRange(ele.Value);
            }            foreach (var ele in dict2)
            {
                dictCombine[ele.Key].AddRange(ele.Value);
            }
Nach dem Login kopieren

Das dictCombine-Zusammenführungsergebnis ist korrekt und weder dict1 noch dict2 haben sich geändert!

Zusammenfassung
  Die Verwendung von Referenzgleichheit bringt viele Vorteile mit sich, wie z. B. Referenzen zwischen FunktionenWertübergabe(per Referenz) . Bei unsachgemäßer Verwendung wird es uns jedoch auch unnötige Probleme bereiten.​

3 Falsche Referenz zerstört die Kapselung?
 
Wenn das private Feld in der gekapselten Klasse als Rückgabewert der Schnittstellenmethode verwendet wird, zerstört dieser Ansatz die Kapselung von die Klasse, insbesondere ein Problem, das leicht übersehen wird. Wenn Sie dieses Problem ignorieren, können unerklärliche Probleme auftreten.
 
 Wie im folgenden Code gezeigt,
 

public class TestPrivateEncapsulate
{
    private List<object> _refObjs;

    public List<object> GetRefObjs()
    {
        _refObjs = new List<object>();        ...
        ...
       //其他逻辑处理计算出来的_refObjs={1,4,2};    
        return _refObjs; //返回私有字段
    }

    public object GetSumByIterRefObjs()
    {        if (_refObjs == null)            return null;
        foreach (var item in _refObjs)
        {            ...//处理逻辑
        }
    }  
}
Nach dem Login kopieren

  Mit der Klasse TestPrivateEncapsulate, die wir gerade geschrieben haben, erstellen wir nun zunächst eine Instanz,

TestPrivateEncapsulate test = new TestPrivateEncapsulate();
Nach dem Login kopieren

Dann rufen Sie auf:

List<object> wantedObjs = test.GetRefObjs();
Nach dem Login kopieren

Die erwarteten zurückgegebenen WantedObjs sollten 3 Elemente vom Typ Integer haben, 1, 4, 2.

Weiter:

List<object> sol = wantedObjs; //我们将sol指向wantedObjssol.Add(5); //加入元素5
Nach dem Login kopieren

Wenn wir zurückgehen und berechnen wollen, ist die ursprüngliche Summe der Elemente von wantObjs:

test.GetSum();
Nach dem Login kopieren

Wir haben versehentlich 12 erhalten, nicht was wir erwartet hatten 7 Zoll. Warum ist das so?

Nach sorgfältiger Analyse haben wir festgestellt, dass wir nach dem Aufruf von sol.Add(5) auf dem Client indirekt die Variable in TestPrivateEncapsulate geändert haben: _refObjs, die von {1,4,2} in {1, 4 ,2,5}.

 Private Variablen wurden auf der Clientseite geändert! Dies ist der Nebeneffekt der Schnittstelle, die private Variablen zurückgibt!

 Richtige Lösung:

    // 将原来的公有变为私有
    private List<object> getRefObjs()
    {
        _refObjs = new List<object>();        ...
        ...
       //其他逻辑处理计算出来的_refObjs={1,4,2};    
        return _refObjs; //返回私有字段
    }

    //只带只读的属性
    public RefObjs
    {
        get
         {
            getRefObjs();            
            return _refObjs;
         }
    }
Nach dem Login kopieren

Legen Sie ein öffentliches Feld mit nur schreibgeschützten Attributen fest und ändern Sie die ursprüngliche öffentliche Methode GetRefObjs in die private Methode getRefObjs Auf diese Weise ist es unmöglich, private Felder auf der Clientseite zu ändern!

Zusammenfassung
Die Attributwerte der Objekte sind alle gleich, aber die Objektreferenzen sind nicht unbedingt gleich.
Zwei oder mehr Objekte verweisen auf ein Objekt. Wenn dieses Objekt geändert wird, sind die Attributwerte aller Referrer gleich ebenfalls geändert;
Member return Gekapselte Referenzvariablen zerstören die Kapselung.

Das obige ist der detaillierte Inhalt von.NET Framework-Code-Beispiel für die gemeinsame Nutzung von Referenz-Traps. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Erklärung dieser Website
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn

Heiße KI -Werkzeuge

Undresser.AI Undress

Undresser.AI Undress

KI-gestützte App zum Erstellen realistischer Aktfotos

AI Clothes Remover

AI Clothes Remover

Online-KI-Tool zum Entfernen von Kleidung aus Fotos.

Undress AI Tool

Undress AI Tool

Ausziehbilder kostenlos

Clothoff.io

Clothoff.io

KI-Kleiderentferner

AI Hentai Generator

AI Hentai Generator

Erstellen Sie kostenlos Ai Hentai.

Heißer Artikel

R.E.P.O. Energiekristalle erklärten und was sie tun (gelber Kristall)
1 Monate vor By 尊渡假赌尊渡假赌尊渡假赌
R.E.P.O. Beste grafische Einstellungen
1 Monate vor By 尊渡假赌尊渡假赌尊渡假赌
R.E.P.O. So reparieren Sie Audio, wenn Sie niemanden hören können
1 Monate vor By 尊渡假赌尊渡假赌尊渡假赌
R.E.P.O. Chat -Befehle und wie man sie benutzt
1 Monate vor By 尊渡假赌尊渡假赌尊渡假赌

Heiße Werkzeuge

Notepad++7.3.1

Notepad++7.3.1

Einfach zu bedienender und kostenloser Code-Editor

SublimeText3 chinesische Version

SublimeText3 chinesische Version

Chinesische Version, sehr einfach zu bedienen

Senden Sie Studio 13.0.1

Senden Sie Studio 13.0.1

Leistungsstarke integrierte PHP-Entwicklungsumgebung

Dreamweaver CS6

Dreamweaver CS6

Visuelle Webentwicklungstools

SublimeText3 Mac-Version

SublimeText3 Mac-Version

Codebearbeitungssoftware auf Gottesniveau (SublimeText3)

Wie man mit Sonderfiguren in der C -Sprache umgeht Wie man mit Sonderfiguren in der C -Sprache umgeht Apr 03, 2025 pm 03:18 PM

In der C -Sprache werden Sonderzeichen durch Escape -Sequenzen verarbeitet, wie z. B.: \ n repräsentiert Linienbrüche. \ t bedeutet tab charakter. Verwenden Sie Escape -Sequenzen oder Zeichenkonstanten, um Sonderzeichen darzustellen, wie z. B. char c = '\ n'. Beachten Sie, dass der Backslash zweimal entkommen muss. Verschiedene Plattformen und Compiler haben möglicherweise unterschiedliche Fluchtsequenzen. Bitte wenden Sie sich an die Dokumentation.

Was ist die Rolle von CHAR in C -Saiten? Was ist die Rolle von CHAR in C -Saiten? Apr 03, 2025 pm 03:15 PM

In C wird der Zeichenentyp in Saiten verwendet: 1. Speichern Sie ein einzelnes Zeichen; 2. Verwenden Sie ein Array, um eine Zeichenfolge darzustellen und mit einem Null -Terminator zu enden. 3. Durch eine Saitenbetriebsfunktion arbeiten; 4. Lesen oder geben Sie eine Zeichenfolge von der Tastatur aus.

Wie man verschiedene Symbole in der C -Sprache verwendet Wie man verschiedene Symbole in der C -Sprache verwendet Apr 03, 2025 pm 04:48 PM

Die Nutzungsmethoden von Symbolen in der C-Sprachabdeckung Arithmetik, Zuordnung, Bedingungen, Logik, Bitoperatoren usw. werden für grundlegende mathematische Operationen verwendet, Zuordnungsoperatoren werden zur Zuordnung und Addition verwendet, Subtraktion, Multiplikationszuordnung und Abteilungszuweisung, Zustandsbetreiber werden für Unterschiede verwendet. Logische Operationen werden verwendet. Logische Operationen werden verwendet. Logische Operationen werden verwendet. Zeiger, Markierungen am Ende der Datei und nicht numerische Werte.

Der Unterschied zwischen char und wchar_t in der C -Sprache Der Unterschied zwischen char und wchar_t in der C -Sprache Apr 03, 2025 pm 03:09 PM

In der C -Sprache ist der Hauptunterschied zwischen char und wchar_t die Zeichencodierung: char verwendet ASCII oder erweitert ASCII, wchar_t Unicode; char nimmt 1-2 Bytes auf, wchar_t nimmt 2-4 Bytes auf; char ist für englischen Text geeignet. Wchar_t ist für mehrsprachige Text geeignet. char ist weithin unterstützt, wchar_t hängt davon ab, ob der Compiler und das Betriebssystem Unicode unterstützen. char ist in der Charakterbereich begrenzt, WCHAR_T hat einen größeren Charakterbereich und spezielle Funktionen werden für arithmetische Operationen verwendet.

Der Unterschied zwischen Multithreading und asynchronem C# Der Unterschied zwischen Multithreading und asynchronem C# Apr 03, 2025 pm 02:57 PM

Der Unterschied zwischen Multithreading und Asynchron besteht darin, dass Multithreading gleichzeitig mehrere Threads ausführt, während asynchron Operationen ausführt, ohne den aktuellen Thread zu blockieren. Multithreading wird für rechenintensive Aufgaben verwendet, während asynchron für die Benutzerinteraktion verwendet wird. Der Vorteil des Multi-Threading besteht darin, die Rechenleistung zu verbessern, während der Vorteil von Asynchron nicht darin besteht, UI-Threads zu blockieren. Die Auswahl von Multithreading oder Asynchron ist von der Art der Aufgabe abhängt: Berechnungsintensive Aufgaben verwenden Multithreading, Aufgaben, die mit externen Ressourcen interagieren und die UI-Reaktionsfähigkeit asynchron verwenden müssen.

Wie man CHO in C -Sprache umwandelt Wie man CHO in C -Sprache umwandelt Apr 03, 2025 pm 03:21 PM

In der C -Sprache kann die char -Typ -Konvertierung direkt in einen anderen Typ konvertiert werden, wenn: Casting: Verwenden von Casting -Zeichen. Automatische Konvertierung des Typs: Wenn ein Datentyp einen anderen Werttyp berücksichtigen kann, wandelt der Compiler diese automatisch um.

So verwenden Sie char Array in C -Sprache So verwenden Sie char Array in C -Sprache Apr 03, 2025 pm 03:24 PM

Das Char -Array speichert Zeichensequenzen in der C -Sprache und wird als char Array_name [Größe] deklariert. Das Zugriffselement wird durch den Einweisoperator weitergeleitet, und das Element endet mit dem Null -Terminator '\ 0', der den Endpunkt der Zeichenfolge darstellt. Die C -Sprache bietet eine Vielzahl von String -Manipulationsfunktionen wie Strlen (), Strcpy (), Strcat () und strcmp ().

Was ist die Funktion der C -Sprachsumme? Was ist die Funktion der C -Sprachsumme? Apr 03, 2025 pm 02:21 PM

Es gibt keine integrierte Summenfunktion in der C-Sprache, daher muss sie selbst geschrieben werden. Die Summe kann erreicht werden, indem das Array durchquert und Elemente akkumulieren: Schleifenversion: Die Summe wird für die Schleifen- und Arraylänge berechnet. Zeigerversion: Verwenden Sie Zeiger, um auf Array-Elemente zu verweisen, und eine effiziente Summierung wird durch Selbststillstandszeiger erzielt. Dynamisch Array -Array -Version zuweisen: Zuordnen Sie Arrays dynamisch und verwalten Sie selbst den Speicher selbst, um sicherzustellen, dass der zugewiesene Speicher befreit wird, um Speicherlecks zu verhindern.

See all articles