Frage

Ich lese häufig, dass structs unveränderlich sein sollte - sind sie nicht per Definition

?

Halten Sie int unveränderlich sein?

int i = 0;
i = i + 123;

Es scheint in Ordnung - wir bekommen eine neue int und weisen es i zurück. Was ist das?

i++;

Okay, können wir denken, es als eine Verknüpfung.

i = i + 1;

Was ist mit dem struct Point?

Point p = new Point(1, 2);
p.Offset(3, 4);

Ist dies wirklich der Punkt (1, 2) mutieren? Sollten wir nicht als Abkürzung denken es für die folgenden mit Point.Offset() einen neuen Punkt zurückzukehren?

p = p.Offset(3, 4);

Der Hintergrund dieses Gedankens ist dies - wie kann ohne Identität ein Werttyp wandelbar sein? Sie haben es mindestens zweimal hinschauen, um zu bestimmen, ob es geändert. Aber wie können Sie dies tun, ohne eine Identität?

Ich will nicht Argumentation, um dies zu erschweren durch ref Parameter und Boxen betrachten. Ich bin mir auch bewusst, dass p = p.Offset(3, 4); drückt Unveränderlichkeit viel besser als p.Offset(3, 4); tut. Aber die Frage bleibt - nicht Typen Wert unveränderlich definitions

UPDATE

Ich denke, es gibt mindestens zwei Konzepte beteiligt -. Die Veränderlichkeit einer Variablen oder Feld und die Veränderlichkeit des Werts einer Variablen

public class Foo
{
    private Point point;
    private readonly Point readOnlyPoint;

    public Foo()
    {
        this.point = new Point(1, 2);
        this.readOnlyPoint = new Point(1, 2);
    }

    public void Bar()
    {
        this.point = new Point(1, 2);
        this.readOnlyPoint = new Point(1, 2); // Does not compile.

        this.point.Offset(3, 4); // Is now (4, 6).
        this.readOnlyPoint.Offset(3, 4); // Is still (1, 2).
    }
}

Im Beispiel wir Felder haben - ein veränderbaren ein und unveränderlich ein. Da ein Wert Typfeld des gesamten Wert enthält, muss unveränderlich sein ein Werttyp in einem unveränderlichen Feld gespeichert, auch. Ich bin immer noch ganz von dem Ergebnis überrascht -. Ich habe nicht das Nur-Lese-Feld exspect unmodifizierten bleiben

Variablen (neben Konstanten) sind durchweg wandelbar, damit sie keine Beschränkung der Veränderlichkeit der Werttypen bedeuten.


Die Antwort scheint nicht, dass gerade zu sein nach vorne, so werde ich die Frage anders formulieren.

In Anbetracht der folgenden.

public struct Foo
{
    public void DoStuff(whatEverArgumentsYouLike)
    {
        // Do what ever you like to do.
    }

    // Put in everything you like - fields, constants, methods, properties ...
}

Können Sie sich eine vollständige Version von Foo und ein Verwendungsbeispiel geben - die ref Parameter und Boxen enthalten kann - so dass es nicht möglich ist, alle Vorkommen neu zu schreiben

foo.DoStuff(whatEverArgumentsYouLike);

mit

foo = foo.DoStuff(whatEverArgumentsYouLike);
War es hilfreich?

Lösung

  

Ein Objekt ist unveränderlich, wenn sein Zustand   ändert sich nicht, wenn das Objekt   erstellt wurde.

Kurze Antwort: Nein, Werttypen per Definition nicht unveränderlich sind. Die beiden Strukturen und Klassen können entweder wandelbar oder unveränderlich sein. Alle vier Kombinationen möglich sind. Wenn eine Struktur oder Klasse hat nicht nur lesbar öffentliche Bereiche, öffentliche Eigenschaften mit Setter oder Methoden, die privaten Felder gesetzt, es ist wandelbar, weil Sie seinen Zustand eine neue Instanz dieses Typs ohne die Erstellung ändern können.


Lange Antwort: Zunächst einmal gilt die Frage nach der Unveränderlichkeit nur auf Structs oder Klassen mit Feldern oder Eigenschaften. Die meisten Grundtypen (Zahlen, Strings und null) sind von Natur unveränderlich, weil es nichts (Feld / Objekt) ist über sie zu ändern. A 5 ist ein 5 ein 5. Jede Operation auf der 5 nur einen anderen unveränderlichen Wert zurückgibt.

Sie können die veränderbare Strukturen schaffen wie System.Drawing.Point. Sowohl X und Y haben Setter, die die Struktur der Felder zu ändern:

Point p = new Point(0, 0);
p.X = 5;
// we modify the struct through property setter X
// still the same Point instance, but its state has changed
// it's property X is now 5

Einige Leute scheinen immutablity mit der Tatsache zu verwechseln, dass Werttypen von Wert übergeben werden (daher der Name) und nicht Bezug genommen wird.

void Main()
{
    Point p1 = new Point(0, 0);
    SetX(p1, 5);
    Console.WriteLine(p1.ToString());
}

void SetX(Point p2, int value)
{
    p2.X = value;
}

In diesem Fall Console.WriteLine() "{X=0,Y=0}" schreibt. Hier wurde p1 nicht geändert, weil SetX() p2 modifiziert, die a Kopie von p1. Dies geschieht, weil p1 ist ein Werttyp , nicht, weil es unveränderlich (es ist nicht).

Warum sollte Werttypen unveränderlich sein? Viele Gründe ... Siehe diese Frage . Meistens ist es, weil wandelbar Werttypen für alle Arten von nicht so offensichtlichen Fehlern führen. Im obigen Beispiel könnte der Programmierer p1 nach dem Aufruf (5, 0) wird SetX() erwartet. Oder stellen Sie durch einen Wert Sortierung, die später ändern können. Dann ist Ihre sortierten Sammlung nicht mehr sortiert werden, wie erwartet. Das gleiche gilt für Wörterbücher und Hashes. Die Fabulous Eric Lippert ( Blog ) hat eine ganze Reihe geschrieben über Unveränderlichkeit und warum er es ist die Zukunft von C # glaubt. Hier ist eines seiner Beispiele dass lässt Sie „ändern“, um eine schreibgeschützte Variable.


UPDATE: Ihr Beispiel mit:

this.readOnlyPoint.Offset(3, 4); // Is still (1, 2).

ist genau das, was Lippert bezeichnete in seinem Beitrag zum Ändern von Lesevariablen. Offset(3,4) tatsächlich eine Point geändert, aber es war eine Kopie von readOnlyPoint, und es wurde nie etwas zugewiesen, so dass er verloren hat.

und , die Deshalb wandelbare Werttypen sind böse: Sie lassen Sie denken Sie etwas ändern, wenn manchmal sind Sie eigentlich eine Kopie zu modifizieren, die zu unerwarteten Fehlern führen . Wenn Point unveränderlich war, würde Offset() haben eine neue Point zurückzukehren, und Sie würden es nicht möglich gewesen zuweisen readOnlyPoint. Und dann gehen Sie „Oh richtig, es ist schreibgeschützt für einen Grund. Warum war ich versucht, es zu ändern? Gut, dass der Compiler hielt mich jetzt.“


UPDATE: Über Ihre umformuliert Anfrage ... Ich glaube, ich weiß, was Sie bekommen bei. In gewisser Weise können Sie „denken“ von structs als intern unveränderlich, dass eine Struktur modifiziert ist, dass gleiche, wie es mit einer modifizierten Kopie zu ersetzen. Es könnte sogar sein, was die CLR funktioniert intern im Speicher, für alles, was ich weiß. (Das ist, wie Flash-Speicher arbeitet. Sie können nicht bearbeitet werden nur wenige Bytes, benötigen Sie einen w lesenLoch Block Kilobyte in den Speicher, ändern Sie die wenigen Sie wollen, und schreiben Sie den ganzen Block zurück.) Aber selbst wenn sie „intern unveränderlich“ waren, das ist ein Detail Umsetzung und für uns Entwickler als Nutzer von Strukturen (deren Schnittstelle oder API , wenn man so will), sie können geändert werden. Wir können nicht diese Tatsache und „denken Sie an sie als unveränderlich“ ignorieren.

In einem Kommentar sagte Sie „Sie nicht einen Verweis auf den Wert von Feld oder eine Variable haben kann“. Sie gehen davon aus, dass jede Struktur Variable eine andere Kopie hat, so dass eine Kopie zu modifizieren nicht die andere nicht beeinträchtigt. Das ist nicht ganz richtig. Die Linien markiert unten sind nicht austauschbar, wenn ...

interface IFoo { DoStuff(); }
struct Foo : IFoo { /* ... */ }

IFoo otherFoo = new Foo();
IFoo foo = otherFoo;
foo.DoStuff(whatEverArgumentsYouLike); // line #1
foo = foo.DoStuff(whatEverArgumentsYouLike); // line #2

Zeilen # 1 und # 2 nicht die gleichen Ergebnisse nicht hat ... Warum? Da foo und otherFoo beziehen sich auf die gleiche Box-Instanz von Foo. Was auch immer in foo in Zeile # 1 geändert reflektiert in otherFoo. Linie 2 ersetzt durch einen neuen Wert foo und hat nichts zu otherFoo (unter der Annahme, dass DoStuff() eine neue IFoo Instanz zurückgibt und verändert nicht foo selbst).

Foo foo1 = new Foo(); // creates first instance
Foo foo2 = foo1; // create a copy (2nd instance)
IFoo foo3 = foo2; // no copy here! foo2 and foo3 refer to same instance

Ändern foo1 nicht foo2 oder foo3 Affekt. Ändern foo2 reflektiert in foo3, aber nicht in foo1. Ändern foo3 wird in foo2 reflektiert aber nicht in foo1.

Verwirrend? Halten Sie sich an unveränderlichen Werttypen und Sie beseitigen den Drang eines von ihnen zu verändern.


UPDATE: fixed Tippfehler in der ersten Codebeispiel

Andere Tipps

Mutability und Werttypen sind zwei verschiedene Dinge.

einen Typ als Werttyp definieren, zeigt an, dass die Laufzeit die Werte anstelle eines Verweises auf die Laufzeit kopiert. Veränderlichkeit, auf der anderen Seite, hängt von der Implementierung, und jede Klasse kann es implementieren, wie es will.

Sie können structs schreiben, die wandelbar sind, aber es ist am beste Praxis zu Werttypen unveränderlich zu machen.

Zum Beispiel Datetime schafft immer wieder neue Fälle, bei denen eine Operation zu tun. Punkt ist wandelbar und kann geändert werden.

Um Ihre Frage zu beantworten: Nein, sie sind nicht unveränderlich definitions es hängt von dem Fall, wenn sie wandelbar sein sollen oder nicht. Zum Beispiel, wenn sie als Dictionary-Schlüssel dienen sollten, sollten sie unveränderlich sein.

Wenn Sie weit genug, um Ihre Logik nehmen, dann alle Typen sind unveränderlich. Wenn Sie einen Referenztyp ändern, könnte man argumentieren, dass Sie wirklich ein neues Objekt an die gleiche Adresse zu schreiben, anstatt etwas zu ändern.

Oder man könnte argumentieren, dass alles wandelbar ist, in jeder Sprache, weil gelegentlich Speicher, die vorher für eine Sache benutzt worden waren, wird durch eine andere überschrieben werden.

Mit genügend Abstraktionen und genügend Sprachfunktionen zu ignorieren, können Sie zu jedem Abschluss erhalten Sie möchten.

Und das trifft nicht den Punkt. Nach .NET-Spezifikation sind, Werttypen wandelbar. Sie können es ändern.

int i = 0;
Console.WriteLine(i); // will print 0, so here, i is 0
++i;
Console.WriteLine(i); // will print 1, so here, i is 1

, aber es ist immer noch die gleiche i. Die Variable i wird nur einmal erklärt. Alles, was nach dieser Erklärung, um es geschieht, ist eine Modifikation.

In so etwas wie eine funktionale Sprache mit unveränderlichen Variablen, wäre dies nicht legal. Die ++ i nicht möglich wäre. Sobald eine Variable deklariert wurde, hat es einen festen Wert.

In .NET, das ist nicht der Fall ist, gibt es nichts, mich zu stoppen ist von Modifizierung der i, nachdem es erklärt worden ist.

über sie ein bisschen mehr Nachdem ich, hier ist ein weiteres Beispiel, das besser sein könnte:

struct S {
  public S(int i) { this.i = i == 43 ? 0 : i; }
  private int i;
  public void set(int i) { 
    Console.WriteLine("Hello World");
    this.i = i;
  }
}

void Foo {
  var s = new S(42); // Create an instance of S, internally storing the value 42
  s.set(43); // What happens here?
}

In der letzten Zeile, nach Ihrer Logik, könnten wir sagen, dass wir tatsächlich ein neues Objekt konstruieren, und die alten mit diesem Wert überschreiben. Aber das ist nicht möglich! Um ein neues Objekt zu konstruieren, hat der Compiler die i Variable auf 42 setzen Aber es ist privat! Es ist nur über einen benutzerdefinierten Konstruktor, der explizit den Wert 43 nicht zulässt (es auf 0 statt Einstellbetrieb) und dann durch unsere set-Methode, die eine unangenehme Nebenwirkung hat. Der Compiler hat keine Möglichkeit, nur ein neues Objekt mit den Werten zu schaffen es mag. Der einzige Weg, in dem s.i kann auf 43 eingestellt werden, ist durch Modifizieren das aktuelle Objekt durch set() aufrufen. Der Compiler kann nicht nur das tun, weil sie das Verhalten des Programms ändern würde (es auf der Konsole gedruckt werden soll)

Also für alle structs unveränderlich zu sein, würde der Compiler zu betrügen und die Regeln der Sprache zu brechen. Und natürlich, wenn wir bereit sind, die Regeln zu brechen, können wir nichts beweisen. Ich konnte beweisen, dass alle Zahlen zu gleich sind, oder dass eine neue Klasse definiert, wird Ihren Computer Feuer zu fangen. Solange wir innerhalb der Regeln der Sprache bleiben, sind structs wandelbar.

  

Ich will nicht Argumentation erschweren   darüber unter Berücksichtigung ref   Parameter und Boxen. Ich bin mir auch bewusst   dass p = p.Offset(3, 4); drückt   Unveränderlichkeit viel besser als   p.Offset(3, 4); tut. Aber die   Frage bleibt - nicht Werttypen   unveränderlich per Definition?

Nun, dann bist du nicht wirklich in der realen Welt arbeiten, sind Sie? In der Praxis ist die Neigung von Werttypen Kopien von sich selbst zu machen, wie sie zwischen den Funktionen bewegen Maschen gut mit Unveränderlichkeit, aber sie sind nicht wirklich unveränderlich, wenn Sie sie unveränderlich machen, da, wie Sie wies darauf hin, können Sie Verweise auf sie verwenden nur wie alles andere.

  

ist nicht Wertetypen unveränderlich per Definition?

Nein, sie sind nicht: Wenn Sie an der System.Drawing.Point Struktur zum Beispiel aussehen, ist es eine Setter sowie Getter auf seiner X Eigenschaft hat

.

Allerdings kann es wahr sein, zu sagen, dass alle Werttypen sollte mit unveränderlichen APIs definiert werden.

Ich denke, die Verwirrung ist, dass, wenn Sie einen Referenztyp haben, der wie ein Werttyp handeln sollte es eine gute Idee ist es unveränderlich zu machen. Einer der wichtigsten Unterschiede zwischen Werttypen und Referenztypen ist, dass eine Änderung durch einen Namen auf einem ref Art gemacht in den anderen Namen auftauchen. Das funktioniert nicht mit Werttypen geschehen:

public class foo
{
    public int x;
}

public struct bar
{
    public int x;
}


public class MyClass
{
    public static void Main()
    {
        foo a = new foo();
        bar b = new bar();

        a.x = 1;
        b.x = 1;

        foo a2 = a;
        bar b2 = b;

        a.x = 2;
        b.x = 2;

        Console.WriteLine( "a2.x == {0}", a2.x);
        Console.WriteLine( "b2.x == {0}", b2.x);
    }
}

Erzeugt:

a2.x == 2
b2.x == 1

Nun, wenn Sie einen Typ haben, die Sie möchten Wert Semantik haben, aber nicht wollen, eigentlich ist es einen Werttyp machen - vielleicht, weil die Speicher es erfordert, ist zu viel oder was auch immer, sollten Sie diese Unveränderlichkeit betrachten Teil des Designs ist. Mit einem unveränderlichen ref Typ, jede zu einem bestehenden Referenzvorgenommene Änderung erzeugt ein neues Objekt anstelle der Veränderung des bestehenden, so erhalten Sie das Verhalten des Wertes, der der Wert, Sie halten nicht durch einen anderen Namen geändert werden kann.

Natürlich ist der System.String-Klasse ist ein hervorragendes Beispiel für ein solches Verhalten.

Im vergangenen Jahr schrieb ich einen Blog-Post die Probleme in Bezug auf Sie in durch nicht machen structs laufen kann  unveränderlich.

den vollständigen Beitrag können Sie hier lesen

Dies ist ein Beispiel dafür, wie die Dinge gehen schief:

//Struct declaration:

struct MyStruct
{
  public int Value = 0;

  public void Update(int i) { Value = i; }
}

Codebeispiel:

MyStruct[] list = new MyStruct[5];

for (int i=0;i<5;i++)
  Console.Write(list[i].Value + " ");
Console.WriteLine();

for (int i=0;i<5;i++)
  list[i].Update(i+1);

for (int i=0;i<5;i++)
  Console.Write(list[i].Value + " ");
Console.WriteLine();

Die Ausgabe dieses Codes ist:

0 0 0 0 0
1 2 3 4 5

Nun wollen wir das gleiche tun, aber das Array für eine generische List<> ersetzen:

List<MyStruct> list = new List<MyStruct>(new MyStruct[5]); 

for (int i=0;i<5;i++)
  Console.Write(list[i].Value + " ");
Console.WriteLine();

for (int i=0;i<5;i++)
  list[i].Update(i+1);

for (int i=0;i<5;i++)
  Console.Write(list[i].Value + " ");
Console.WriteLine();

Die Ausgabe lautet:

0 0 0 0 0
0 0 0 0 0

Die Erklärung ist sehr einfach. Nein, es ist nicht Boxen / Unboxing ...

Wenn Elemente aus einem Array zugreift, wird die Laufzeit die Array-Elemente direkt erhalten, so dass die Update () Methode auf dem Array-Elemente arbeitet selbst. Das bedeutet, dass die Strukturen selbst im Array aktualisiert werden.

Im zweiten Beispiel haben wir eine generische List<>. Was passiert, wenn wir ein bestimmtes Element zugreifen? Nun, die Indexer Eigenschaft genannt wird, das ein Verfahren ist. Werttypen werden immer kopiert, wenn sie von einer Methode zurückgegeben wird, so ist dies genau das, was passiert: Der Indexer-Methode der Liste ruft die Struktur aus einem internen Array und gibt es an den Anrufer. Weil es einen Werttyp handelt, wird eine Kopie erstellt werden, und die Update () -Methode wird auf der Kopie aufgerufen werden, was natürlich keine Wirkung auf die ursprünglichen Elemente der Liste.

Mit anderen Worten, immer sicherstellen, dass Ihr structs unveränderlich ist, weil man nie sicher ist, wenn eine Kopie gemacht werden. Die meiste Zeit ist es offensichtlich, aber in manchen Fällen kann es wirklich überraschen ...

Nein, sie sind es nicht. Beispiel:

Point p = new Point (3,4);
Point p2 = p;
p.moveTo (5,7);

In diesem Beispiel moveTo() ist ein in-place Betrieb. Es ändert die Struktur, die hinter dem Verweis p verbirgt. Sie können, dass bei p2 von Blick sehen: Es ist Position wird auch geändert. Mit unveränderlichen Strukturen würde moveTo() hat eine neue Struktur zurück:

p = p.moveTo (5,7);

Nun Point ist unveränderlich, und wenn Sie einen Verweis auf sie überall in Ihrem Code zu erstellen, werden Sie keine Überraschungen. Lassen Sie uns an i aussehen:

int i = 5;
int j = i;
i = 1;

Das ist anders. i nicht unveränderlich ist, 5 ist. Und die zweite Zuordnung nicht einen Verweis auf die Struktur kopieren, die i aber es kopiert den Inhalt von i enthält. So hinter den Kulissen, etwas ganz anderes geschieht: Sie erhalten eine vollständige Kopie der Variablen statt nur eine Kopie der Adresse im Speicher (die Referenz)

.

Ein äquivalent mit Objekten würden den Copykonstruktor sein:

Point p = new Point (3,4);
Point p2 = new Point (p);

Hier wird die innere Struktur von p in ein neues Objekt / Struktur kopiert und p2 den Verweis auf sie enthalten. Aber das ist eine ziemlich teuere Operation (im Gegensatz zu der ganzzahligen Zuordnung oben), weshalb die meisten Programmiersprachen, die Unterscheidung zu machen.

Da Computer immer leistungsfähiger werden und mehr Speicher erhalten, diese Unterscheidung weg gehen wird, weil es eine enorme Menge an Bugs und Probleme verursacht. In der nächsten Generation wird es nur unveränderliche Objekte sein, wird jede Operation durch eine Transaktion geschützt werden und sogar ein int wird ein vollständiges geblasen-Objekt sein. Genau wie Müllabfuhr, wird es ein großer Schritt nach vorn in der Programmstabilität sein, eine Menge Ärger in den ersten Jahren dazu führen, aber es ermöglicht zuverlässige Software zu schreiben. Heute Computer sind einfach nicht schnell genug.

Nein, Werttypen sind nicht unveränderlich per Definition.

Zuerst sollte ich besser die Frage gestellt haben „Do Werttypen wie unveränderliche Typen verhalten?“ statt zu fragen, ob sie unveränderlich sind - ich nehme an, das eine Menge Verwirrung verursacht

.
struct MutableStruct
{
    private int state;

    public MutableStruct(int state) { this.state = state; }

    public void ChangeState() { this.state++; }
}

struct ImmutableStruct
{
    private readonly int state;

    public MutableStruct(int state) { this.state = state; }

    public ImmutableStruct ChangeState()
    {
        return new ImmutableStruct(this.state + 1);
    }
}

[Fortsetzung folgt ...]

Um festzulegen, ob ein Typ wandelbar oder unveränderlich ist, muss man definieren, was der „Typ“ sich bezieht. Wenn eine Speicherstelle des Referenztypen deklariert ist, ordnet die Erklärung lediglich Raum eine Referenz auf ein Objekt an anderer Stelle gespeichert zu halten; ist die Erklärung nicht das eigentliche Objekt in Frage erstellen. Trotzdem in den meisten Kontexten, in denen man spricht über bestimmte Referenztypen, wird man nicht von einer Ablageort zu sprechen, die einen Verweis hält , sondern das Objekt mit diesem Verweis identifiziert . Die Tatsache, dass man zu einem Lagerort schreiben kann einen Verweis auf ein Objekt impliziert in keiner Weise hält, die das Objekt selbst wandelbar ist.

Im Gegensatz dazu, wenn ein Ablageort Werttypen deklariert wird, wird das System innerhalb dieser Lagerort verschachtelt Speicherplatz für jeden öffentlichen oder privaten Bereich von diesem Werttyp gehalten zuordnen. Alles rund um den Werttyp wird in dieser Speicherstelle gehalten. Wenn man eine variable foo vom Typ Point und seine zwei Felder, und X Y definiert, halten 3 bzw. 6. Wenn man die „Instanz“ von Point in foo definiert als das Paar von Feldern , wird diese Instanz wandelbar sein, wenn und nur wenn foo ist wandelbar. Wenn man eine Instanz von Point definiert als der Werte in diesen Bereichen statt (zum Beispiel „3,6“), dann ist ein solcher Fall ist definitions unveränderlich, da eines dieser Felder zu ändern würde verursachen Point zu hält eine andere Instanz.

Ich denke, es hilfreicher ist ein Werttyp „Instanz“ als die Felder zu denken, anstatt die Werte, die sie halten. Nach dieser Definition in einem wandelbaren Lagerort jeder Werttyp gespeichert ist, und, für die ein nicht-Standardwert vorhanden ist, wird immer wandelbar sein, unabhängig davon, wie sie deklariert ist. Eine Anweisung MyPoint = new Point(5,8) konstruiert eine neue Instanz von Point, mit Feldern X=5 und Y=8 und mutiert dann MyPoint durch die Werte in ihren Bereichen mit denen der neu erstellten Point ersetzen. Selbst wenn eine Struktur keine Möglichkeit bietet eines seiner Felder außerhalb seines Konstruktor zu ändern, gibt es keine Möglichkeit, eine Strukturtyp eine Instanz aus, die alle ihre Felder mit dem Inhalt einer anderen Instanz überschrieben schützen kann.

übrigens ein einfaches Beispiel, bei dem ein veränderliche struct Semantik nicht erreichbar über andere Mittel erreicht werden kann: Unter der Annahme, myPoints[] ist ein Einzelelement-Array, das auf mehrere Threads zugänglich ist, sind zwanzig Fäden gleichzeitig den Code ausführen:

Threading.Interlocked.Increment(myPoints[0].X);

Wenn myPoints[0].X beginnt gleich null und zwanzig Fäden führen Sie den obigen Code, ob gleichzeitig oder nicht, myPoints[0].X wird zwanzig gleich. Würde man versuchen, den obigen Code zu imitieren mit:

myPoints[0] = new Point(myPoints[0].X + 1, myPoints[0].Y);

dann, wenn ein Thread myPoints[0].X zwischen der Zeit, liest ein anderer Thread lesen und schrieb den revidierten Wert zurück, würden die Ergebnisse des Zuwachses verloren (mit der Folge, dass myPoints[0].X willkürlich mit einem beliebigen Wert zwischen 1 und 20 könnte am Ende

Objekte / Structs sind unveränderlich, wenn sie in eine Funktion in einer solchen Art und Weise geführt werden, da die Daten nicht geändert werden können, und das zurückgegebene Struktur ist ein new Struktur. Das klassische Beispiel ist

String s = "abc";

s.toLower();

, wenn die toLower Funktion geschrieben wird, so dass sie eine neue Zeichenfolge zurückgegeben wird, das „s“ ersetzt, es ist unveränderlich, aber wenn die Funktion geht Buchstaben für Buchstaben, die Buchstaben innen „s“ ersetzt und nie einen „neuen String“ erklärt, es wandelbar ist.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top