In C #,
Gibt es eine Möglichkeit, eine automatische Eigenschaft in eine verzögert geladene automatische Eigenschaft mit einem angegebenen Standardwert umzuwandeln?
Im Wesentlichen versuche ich dies zu ändern ...
private string _SomeVariable
public string SomeVariable
{
get
{
if(_SomeVariable == null)
{
_SomeVariable = SomeClass.IOnlyWantToCallYouOnce();
}
return _SomeVariable;
}
}
in etwas anderes, wo ich den Standard angeben kann und es den Rest automatisch erledigt ...
[SetUsing(SomeClass.IOnlyWantToCallYouOnce())]
public string SomeVariable {get; private set;}
c#
automatic-properties
ctorx
quelle
quelle
Antworten:
Nein, da ist kein. Automatisch implementierte Eigenschaften dienen nur dazu, die grundlegendsten Eigenschaften zu implementieren: Hintergrundfeld mit Getter und Setter. Diese Art der Anpassung wird nicht unterstützt.
Sie können jedoch den
Lazy<T>
Typ 4.0 verwenden, um dieses Muster zu erstellenDieser Code berechnet träge den Wert des
_someVariable
ersten Aufrufs desValue
Ausdrucks. Es wird nur einmal berechnet und der Wert für zukünftige Verwendungen derValue
Eigenschaft zwischengespeichertquelle
SomeClass.IOnlyWantToCallYouOnce
in Ihrem Beispiel statisch sein muss, um mit einem Feldinitialisierer verwendet zu werden.Am prägnantesten ist es wahrscheinlich, den Null-Koaleszenz-Operator zu verwenden:
quelle
IOnlyWantToCallYouOnce
in dem zurückgegeben wirdnull
, wird es mehrmals aufgerufen._SomeVariable ?? ( _SomeVariable = SomeClass.IOnlyWantToCallYouOnce() );
- Beachten Sie das Hinzufügen der Klammer um die Einstellung,_SomeVariable
wenn sie null ist.Lazy<>
, aber für unsere Zwecke hat dies besser funktioniert. Mit dem neuesten C # kann es auch noch präziser geschrieben werden.=> _SomeVariable ?? (_SomeVariable = SomeClass.IOnlyWantToCallYouOnce());
Was manche auf den ersten Blick vielleicht nicht bemerken, ist, dass der Operator den rechten Operanden auswertet und sein Ergebnis zurückgibt .In C # 6 gibt es eine neue Funktion namens Expression Bodied Auto-Properties , mit der Sie sie etwas sauberer schreiben können:
Kann jetzt geschrieben werden als:
quelle
IOnlyWantToCallYouOnce
wird während der Erstellung jedes Mal aufgerufen, wenn die Klasse instanziiert wird.SomeVariable
ist faul geladen.Nicht so, Parameter für Attribute müssen einen konstanten Wert haben, Sie können keinen Code aufrufen (auch keinen statischen Code).
Möglicherweise können Sie jedoch etwas mit den Aspekten von PostSharp implementieren.
Schau sie dir an:
PostSharp
quelle
Hier ist meine Implementierung einer Lösung für Ihr Problem. Grundsätzlich handelt es sich um eine Eigenschaft, die beim ersten Zugriff von einer Funktion festgelegt wird, und nachfolgende Zugriffe ergeben denselben Rückgabewert wie der erste.
Dann zu verwenden:
Es gibt natürlich den Aufwand, den Funktionszeiger herumzugeben, aber er erledigt den Job für mich und ich bemerke nicht zu viel Aufwand im Vergleich zum wiederholten Ausführen der Methode.
quelle
Ich bin ein großer Fan dieser Idee und möchte das folgende C # -Snippet anbieten, das ich proplazy.snippet genannt habe (Sie können es entweder importieren oder in den Standardordner einfügen, den Sie über den Snippet-Manager erhalten können).
Hier ist ein Beispiel für die Ausgabe:
Hier ist der Inhalt der Snippet-Datei: (als proplazy.snippet speichern)
quelle
Ich denke nicht, dass dies mit reinem C # möglich ist. Sie können dies jedoch mit einem IL-Umschreiber wie PostSharp tun . Beispielsweise können Sie abhängig von den Attributen Handler vor und nach Funktionen hinzufügen.
quelle
Ich habe es so gemacht:
und später können Sie es wie verwenden
quelle
public ISet<String> RegularProperty {get;set} public string CalculatedProperty => this.LazyValue(() => { return string.Join(",", RegularProperty.ToArray()); });
https://github.com/bcuff/AutoLazy verwendet Fody, um Ihnen so etwas zu geben
quelle
und ich rufe wie unten
quelle
Wenn Sie während der verzögerten Initialisierung einen Konstruktor verwenden, können auch die folgenden Erweiterungen hilfreich sein
Verwendung
quelle
LazyInitializer.EnsureInitialized()
? DennLazyInitializer
soweit ich das beurteilen kann, bietet es zusätzlich zu den oben genannten Funktionen eine Fehlerbehandlung sowie Synchronisierungsfunktionen. LazyInitializer-Quellcode .Operator ?? = ist mit C # 8.0 und höher verfügbar, sodass Sie dies jetzt noch präziser tun können:
quelle