Ich frage mich, ob ich ein privates schreibgeschütztes Feld ändern kann, nachdem der Konstruktor seine Ausführung abgeschlossen hat, da viele Dinge mithilfe von Reflektion erledigt werden können.
(Anmerkung: nur Neugier)
public class Foo
{
private readonly int bar;
public Foo(int num)
{
bar = num;
}
public int GetBar()
{
return bar;
}
}
Foo foo = new Foo(123);
Console.WriteLine(foo.GetBar()); // display 123
// reflection code here...
Console.WriteLine(foo.GetBar()); // display 456
c#
reflection
field
readonly
Ron Klein
quelle
quelle
Das Offensichtliche ist, es zu versuchen:
Das funktioniert gut. (Interessanterweise hat Java andere Regeln - Sie müssen explizit festlegen
Field
, dass auf diese zugegriffen werden soll, und es funktioniert sowieso nur für Instanzfelder.)quelle
Ich stimme den anderen Antworten darin zu, dass es allgemein und insbesondere mit dem Kommentar von E. Lippert funktioniert, dass dies kein dokumentiertes Verhalten und daher kein zukunftssicherer Code ist.
Wir haben jedoch auch ein anderes Problem festgestellt. Wenn Sie Ihren Code in einer Umgebung mit eingeschränkten Berechtigungen ausführen, wird möglicherweise eine Ausnahme angezeigt.
Wir hatten gerade einen Fall, in dem unser Code auf unseren Computern einwandfrei funktionierte, aber wir haben einen erhalten,
VerificationException
als der Code in einer eingeschränkten Umgebung ausgeführt wurde. Der Täter war ein Reflexionsaufruf an den Setter eines schreibgeschützten Feldes. Es hat funktioniert, als wir die schreibgeschützte Einschränkung dieses Feldes aufgehoben haben.quelle
Sie haben gefragt, warum Sie die Kapselung so aufheben möchten.
Ich verwende eine Entity-Helfer-Klasse, um Entities zu hydratisieren. Dies verwendet Reflection, um alle Eigenschaften einer neuen leeren Entität abzurufen, und ordnet den Eigenschafts- / Feldnamen der Spalte in der Ergebnismenge zu und setzt ihn mit propertyinfo.setvalue ().
Ich möchte nicht, dass jemand anderes den Wert ändern kann, aber ich möchte auch nicht alle Anstrengungen unternehmen, um benutzerdefinierte Code-Hydratationsmethoden für jede Entität zu erstellen.
Meine vielen meiner gespeicherten Prozesse geben Ergebnismengen zurück, die nicht direkt Tabellen oder Ansichten entsprechen, sodass die ORMs des Codegens nichts für mich tun.
quelle
Eine andere einfache Möglichkeit, dies mit unsicher zu tun (oder Sie können das Feld über DLLImport an eine C-Methode übergeben und dort festlegen).
quelle
Die Antwort lautet ja, aber was noch wichtiger ist:
Warum willst du? Das absichtliche Unterbrechen der Kapselung scheint mir eine schrecklich schlechte Idee zu sein.
Das Verwenden der Reflexion zum Ändern eines schreibgeschützten oder konstanten Feldes ist wie das Kombinieren des Gesetzes der unbeabsichtigten Konsequenzen mit dem Murphyschen Gesetz .
quelle
Tu das nicht.
Ich habe gerade einen Tag damit verbracht, einen surrealen Fehler zu beheben, bei dem Objekte nicht von ihrem eigenen deklarierten Typ sein konnten.
Das Ändern des schreibgeschützten Feldes hat einmal funktioniert. Wenn Sie jedoch versuchen, es erneut zu ändern, erhalten Sie folgende Situationen:
Also tu es nicht.
Dies war auf der Mono-Laufzeit (Unity-Game-Engine).
quelle
Ich möchte nur hinzufügen, dass Sie Folgendes verwenden können, wenn Sie dieses Zeug für Unit-Tests ausführen müssen:
A) Die PrivateObject- Klasse
B) Sie benötigen weiterhin eine PrivateObject-Instanz, können jedoch mit Visual Studio "Accessor" -Objekte generieren. Gewusst wie: Private Accessoren neu generieren
Wenn Sie private Felder eines Objekts in Ihrem Code außerhalb von Unit-Tests festlegen, ist dies eine Instanz von "Code-Geruch". Ich denke, dass der einzige andere Grund, warum Sie dies tun möchten, darin besteht, dass Sie sich mit einem Dritten befassen Bibliothek und Sie können den Zielklassencode nicht ändern. Selbst dann möchten Sie wahrscheinlich den Dritten kontaktieren, Ihre Situation erklären und prüfen, ob er seinen Code nicht ändert, um Ihren Anforderungen gerecht zu werden.
quelle