Ich suche das C # -Äquivalent von Java final
. Existiert es?
Hat C # Folgendes:
public Foo(final int bar);
Im obigen Beispiel bar
handelt es sich um eine schreibgeschützte Variable, die nicht von geändert werden kann Foo()
. Gibt es eine Möglichkeit, dies in C # zu tun?
Zum Beispiel, vielleicht habe ich eine lange Methode , die mit arbeiten werden x
, y
und z
Koordinaten eines Objekts (Ints). Ich möchte absolut sicher sein, dass die Funktion diese Werte in keiner Weise ändert und dadurch die Daten beschädigt. Daher möchte ich sie schreibgeschützt erklären.
public Foo(int x, int y, int z) {
// do stuff
x++; // oops. This corrupts the data. Can this be caught at compile time?
// do more stuff, assuming x is still the original value.
}
c#
const
readonly
parameter-passing
Nick Heiner
quelle
quelle
Antworten:
Leider können Sie dies in C # nicht tun.
Das
const
Schlüsselwort kann nur für lokale Variablen und Felder verwendet werden.Das
readonly
Schlüsselwort kann nur für Felder verwendet werden.von http://www.25hoursaday.com/CsharpVsJava.html
EDIT (2019/08/13): Ich werfe dies zur besseren Sichtbarkeit ein, da dies akzeptiert wird und auf der Liste am höchsten ist. Mit
in
Parametern ist das jetzt irgendwie möglich . Siehe die Antwort unter dieser für Details.quelle
Dies ist jetzt in C # Version 7.2 möglich:
Sie können das
in
Schlüsselwort in der Methodensignatur verwenden. MSDN-Dokumentation .Das
in
Schlüsselwort sollte hinzugefügt werden, bevor das Argument einer Methode angegeben wird.Beispiel eine gültige Methode in C # 7.2:
Während folgendes nicht erlaubt ist:
Folgende Fehler werden angezeigt, wenn entweder zu ändern versuchen ,
x
odery
weil sie markiert sind , mitin
:Ein Argument mit
in
Mitteln markieren :quelle
in
Schlüsselwörter für Parameter mit diesen Typen verwenden, verhindern Sie nur die Zuweisung zu diesen. Verhindern Sie nicht, die zugänglichen Felder oder Eigenschaften zu ändern! Habe ich recht?Hier ist eine kurze und süße Antwort, die wahrscheinlich viele negative Stimmen erhalten wird. Ich habe nicht alle Beiträge und Kommentare gelesen. Bitte verzeihen Sie mir, wenn dies zuvor vorgeschlagen wurde.
Nehmen Sie Ihre Parameter und übergeben Sie sie an ein Objekt, das sie als unveränderlich verfügbar macht, und verwenden Sie dieses Objekt dann in Ihrer Methode.
Mir ist klar, dass dies wahrscheinlich eine sehr offensichtliche Lösung ist, die bereits in Betracht gezogen wurde, und das OP versucht, dies zu vermeiden, indem es diese Frage stellt, aber ich war der Meinung, dass es trotzdem hier sein sollte ...
Viel Glück :-)
quelle
int* p; *p = 0;
. Das wird kompiliert und bis zum Segmentierungsfehler ausgeführt.Die Antwort: C # hat nicht die const-Funktionalität wie C ++.
Ich stimme Bennett Dill zu.
Das Schlüsselwort const ist sehr nützlich. In diesem Beispiel haben Sie ein int verwendet, und die Leute verstehen Ihren Standpunkt nicht. Aber warum, wenn Ihr Parameter ein riesiges und komplexes Objekt des Benutzers ist, das innerhalb dieser Funktion nicht geändert werden kann? Das ist die Verwendung des Schlüsselworts const: parameter kann innerhalb dieser Methode nicht geändert werden, da [aus welchem Grund auch immer] dies für diese Methode nicht wichtig ist. Das Const-Schlüsselwort ist sehr mächtig und ich vermisse es wirklich in C #.
quelle
Ich werde mit der
int
Portion beginnen.int
ist ein Werttyp, und in .Net bedeutet dies, dass es sich wirklich um eine Kopie handelt. Es ist eine wirklich seltsame Designbeschränkung, einer Methode mitzuteilen: "Sie können eine Kopie dieses Werts haben. Es ist Ihre Kopie, nicht meine. Ich werde sie nie wieder sehen. Aber Sie können die Kopie nicht ändern." Der Methodenaufruf impliziert, dass das Kopieren dieses Werts in Ordnung ist, da wir die Methode sonst nicht sicher aufrufen könnten. Wenn die Methode das Original benötigt, überlassen Sie es dem Implementierer, eine Kopie zum Speichern zu erstellen. Geben Sie der Methode entweder den Wert oder geben Sie der Methode nicht den Wert. Gehen Sie nicht zwischendurch auf die Wäsche.Kommen wir zu den Referenztypen. Jetzt wird es etwas verwirrend. Meinen Sie eine konstante Referenz, bei der die Referenz selbst nicht geändert werden kann, oder ein vollständig verriegeltes, unveränderliches Objekt? In diesem Fall werden Verweise in .Net standardmäßig als Wert übergeben. Das heißt, Sie erhalten eine Kopie der Referenz. Wir haben also im Wesentlichen die gleiche Situation wie bei Werttypen. Wenn der Implementierer die ursprüngliche Referenz benötigt, kann er diese selbst behalten.
Das lässt uns nur mit einem konstanten (gesperrten / unveränderlichen) Objekt zurück. Dies mag aus Sicht der Laufzeit in Ordnung erscheinen, aber wie soll der Compiler dies durchsetzen? Da Eigenschaften und Methoden alle Nebenwirkungen haben können, sind Sie im Wesentlichen auf den schreibgeschützten Feldzugriff beschränkt. Ein solches Objekt dürfte nicht sehr interessant sein.
quelle
Erstellen Sie eine Schnittstelle für Ihre Klasse, die nur schreibgeschützte Eigenschaftszugriffsmethoden enthält. Lassen Sie dann Ihren Parameter von dieser Schnittstelle und nicht von der Klasse selbst sein. Beispiel:
Erstellen Sie für Strukturen einen generischen const-Wrapper.
Es ist jedoch erwähnenswert, dass es seltsam ist, dass Sie das tun möchten, was Sie in Bezug auf Strukturen tun möchten. Als Verfasser der Methode sollten Sie erwarten, dass Sie wissen, was in dieser Methode vor sich geht. Die übergebenen Werte werden nicht beeinflusst, um sie innerhalb der Methode zu ändern. Sie müssen also nur sicherstellen, dass Sie sich in der von Ihnen geschriebenen Methode verhalten. Es kommt ein Punkt, an dem Wachsamkeit und sauberer Code der Schlüssel sind, um const und andere solche Regeln durchzusetzen.
quelle
Wenn Sie häufig auf solche Probleme stoßen, sollten Sie "Apps ungarisch" in Betracht ziehen. Die gute Art im Gegensatz zur schlechten Art . Während dies normalerweise nicht versucht, die Konstanz eines Methodenparameters auszudrücken (das ist einfach zu ungewöhnlich), hindert Sie nichts daran, ein zusätzliches "c" vor dem Bezeichnernamen anzuheften.
Lesen Sie bitte die Meinungen dieser Koryphäen zum Thema: Alle, die jetzt den Downvote-Button drücken möchten:
quelle
Ich weiß, dass dies etwas spät sein könnte. Aber für Leute, die immer noch nach anderen Wegen suchen, könnte es einen anderen Weg geben, um diese Einschränkung des C # -Standards zu umgehen. Wir könnten die Wrapper-Klasse ReadOnly <T> schreiben, wobei T: struct. Mit impliziter Konvertierung in Basistyp T. Aber nur explizite Konvertierung in die Wrapper <T> -Klasse. Dies erzwingt Compilerfehler, wenn der Entwickler versucht, den Wert vom Typ ReadOnly <T> implizit auf den Wert zu setzen. Wie ich im Folgenden zwei Verwendungsmöglichkeiten demonstrieren werde.
Für die Verwendung von USAGE 1 musste die Anruferdefinition geändert werden. Diese Verwendung wird nur zum Testen der Richtigkeit Ihres Funktionscodes "TestCalled" verwendet. Während der Release-Version / Builds sollten Sie es nicht verwenden. Da im großen Maßstab mathematische Operationen bei Konvertierungen möglicherweise zu viel bewirken und Ihren Code verlangsamen. Ich würde es nicht benutzen, aber nur zu Demonstrationszwecken habe ich es gepostet.
USAGE 2, das ich vorschlagen würde, hat die Verwendung von Debug vs Release in der TestCalled2-Funktion demonstriert. Bei Verwendung dieses Ansatzes würde die TestCaller-Funktion ebenfalls nicht konvertiert, erfordert jedoch ein wenig mehr Codierung der TestCaller2-Definitionen mithilfe der Compilerkonditionierung. Sie können Compilerfehler in der Debug-Konfiguration feststellen, während bei der Release-Konfiguration der gesamte Code in der TestCalled2-Funktion erfolgreich kompiliert wird.
quelle
Wenn struct an eine Methode übergeben wird, wird es von der Methode, an die es übergeben wird, nicht geändert, es sei denn, es wird von ref übergeben. In diesem Sinne ja.
Können Sie einen Parameter erstellen, dessen Wert innerhalb der Methode nicht zugewiesen werden kann oder dessen Eigenschaften innerhalb der Methode nicht festgelegt werden können? Nein. Sie können nicht verhindern, dass der Wert innerhalb der Methode zugewiesen wird, aber Sie können verhindern, dass seine Eigenschaften festgelegt werden, indem Sie einen unveränderlichen Typ erstellen.
Die Frage ist nicht, ob der Parameter oder seine Eigenschaften innerhalb der Methode zugewiesen werden können. Die Frage ist, was es sein wird, wenn die Methode beendet wird.
Externe Daten werden nur geändert, wenn Sie eine Klasse übergeben und eine ihrer Eigenschaften ändern oder wenn Sie einen Wert mit dem Schlüsselwort ref übergeben. Die Situation, die Sie skizziert haben, tut beides nicht.
quelle
x++
. Das heißt, er versucht, eine Neuzuweisung des Parameters zu verhindern, die orthogonal zur Veränderbarkeit des Parameterwerts ist.