3 Stimmen

Foreach struct seltsame Kompilierungsfehler in C#

namespace MyNamespace
{
    public struct MyStruct
    {
        public string MyString;
        public int MyInt;
        public bool MyBool;
    }

    public class MyClass
    {
        private List MyPrivateVariable;

        public List MyVariable
        {
            get
            {
                if (MyPrivateVariable == null)
                {
                    MyPrivateVariable = new List();

                    MyPrivateVariable.Add(new MyStruct());
                    MyPrivateVariable.Add(new MyStruct());
                }

                return MyPrivateVariable;
            }
        }

        public void MyLoop()
        {
            foreach (MyStruct ms in MyVariable)
            {
                // Kompiliert nicht, funktioniert aber, wenn Sie es über das Immediate-Fenster oder in Quickwatch ausführen
                ms.MyBool = false;

                // Kompiliert, funktioniert
                MyFunction(ms);
            }
        }

        public void MyFunction(MyStruct ms)
        {
            ms.MyBool = false;
        }
    }
}

Eine vernünftige Erklärung dafür?

Der Compiler gibt zurück:

Fehler: Kann Elemente von 'ms' nicht ändern, weil es die 'foreach-Iteration Variable' ist

BEARBEITEN:

Zusätzliche Frage:

Ich habe gerade versucht, einen String von MyFunction zu ändern, und er aktualisiert ms tatsächlich nicht. ABER: Wenn ich in Quickwatch denselben Wert zuweise, aktualisiert es ms. Warum passiert das, wenn es eigentlich gar nicht kompilieren sollte, sollte Quickwatch nicht eine Ausnahme auslösen?

BEARBEITEN2:

Okay, Quickwatch funktioniert auch auf einer Kopie von ms, daher kann ich seinen Wert ändern, es ändert tatsächlich nicht den Inhalt von MyPrivateVariable.

14voto

Joel Etherton Punkte 36629

Sie verwenden sie als veränderbare Strukturen. Vermeiden Sie das:

Warum sind veränderbare Strukturen "böse"?

6voto

Rohith Punkte 2003

Struktur hat Werttypsemantik. Daher wird jede Änderung, die Sie an der Strukturinstanz vornehmen, die Originalinstanz nicht beeinflussen. Der C#-Compiler versucht, Sie darauf hinzuweisen.

5voto

burkestar Punkte 753

C# iteriert Strukturen nicht per Referenz in der "foreach (MyStruct ms...)", daher ist ms in diesem Kontext unveränderlich.

Ersetzen Sie MyStruct stattdessen durch eine Klasse.

QuickWatch kann Werttypen auf dem Stack manipulieren.

1voto

Vinay B R Punkte 7701

Dies liegt daran, dass struct ein Wertetyp und kein Verweistyp ist. Wenn MyStruct eine Klasse wäre, hätte es ohne Probleme kompiliert. Überprüfe diesen Thread für Details.

0voto

Jeff Sternal Punkte 46528

Sie können nicht ändern, auf was eine Iterationsvariable verweist: Das heißt, Sie können die Variable nicht auf eine andere Instanz zeigen lassen (um herauszufinden, warum das so ist, siehe Warum ist die Iterationsvariable in einer C# foreach-Anweisung schreibgeschützt?).

'Ändern' einer Struktur (einem Werttyp) erzeugt eine neue Instanz des Typs, daher ist die Anweisung ms.MyBool = false sinnlos.

Der Aufruf von MyFunction(ms) kompiliert, weil er auf einer Kopie von ms arbeitet (auch wenn es trotzdem nicht das tut, was man erwarten könnte).

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X