En C #,
Existe-t-il un moyen de transformer une propriété automatique en propriété automatique chargée différemment avec une valeur par défaut spécifiée?
Essentiellement, j'essaie de transformer cela ...
private string _SomeVariable
public string SomeVariable
{
get
{
if(_SomeVariable == null)
{
_SomeVariable = SomeClass.IOnlyWantToCallYouOnce();
}
return _SomeVariable;
}
}
en quelque chose de différent, où je peux spécifier la valeur par défaut et il gère le reste automatiquement ...
[SetUsing(SomeClass.IOnlyWantToCallYouOnce())]
public string SomeVariable {get; private set;}
c#
automatic-properties
ctorx
la source
la source
Réponses:
Non, il n'y en a pas. Les propriétés implémentées automatiquement ne fonctionnent que pour implémenter les propriétés les plus élémentaires: un champ de sauvegarde avec getter et setter. Il ne prend pas en charge ce type de personnalisation.
Cependant, vous pouvez utiliser le
Lazy<T>
type 4.0 pour créer ce modèleCe code calculera paresseusement la valeur de
_someVariable
la première fois que l'Value
expression est appelée. Il ne sera calculé qu'une seule fois et mettra en cache la valeur pour les utilisations futures de laValue
propriétéla source
SomeClass.IOnlyWantToCallYouOnce
dans votre exemple, doit être statique pour être utilisé avec un initialiseur de champ.Le plus concis que vous puissiez obtenir est probablement d'utiliser l'opérateur null-coalescing:
la source
IOnlyWantToCallYouOnce
retour,null
il l'appellera plus d'une fois._SomeVariable ?? ( _SomeVariable = SomeClass.IOnlyWantToCallYouOnce() );
- notez l'ajout de parenthèses autour du paramètre_SomeVariable
s'il est nul.Lazy<>
, mais pour nos besoins, cela fonctionnait mieux. Avec le dernier C #, il peut également être écrit encore plus concis.=> _SomeVariable ?? (_SomeVariable = SomeClass.IOnlyWantToCallYouOnce());
Ce que certains pourraient ne pas remarquer du premier coup d'œil, c'est que l'opérateur évalue l'opérande de droite et renvoie son résultat .Il y a une nouvelle fonctionnalité en C # 6 appelée Expression Bodied Auto-Properties , qui vous permet de l'écrire un peu plus clairement:
Peut maintenant être écrit comme:
la source
IOnlyWantToCallYouOnce
serait appelée pendant la construction à chaque fois que la classe est instanciée.SomeVariable
est chargé paresseusement.Pas comme ça, les paramètres des attributs doivent être de valeur constante, vous ne pouvez pas appeler de code (même code statique).
Vous pouvez cependant être en mesure d'implémenter quelque chose avec les aspects de PostSharp.
Vérifie-les:
PostSharp
la source
Voici ma mise en œuvre d'une solution à votre problème. Fondamentalement, l'idée est une propriété qui sera définie par une fonction au premier accès et les accès suivants produiront la même valeur de retour que le premier.
Puis utiliser:
Il y a bien sûr la surcharge de passer le pointeur de fonction, mais cela fait le travail pour moi et je ne remarque pas trop de surcharge par rapport à l'exécution de la méthode encore et encore.
la source
Je suis un grand fan de cette idée et j'aimerais vous proposer l'extrait de code C # suivant que j'ai appelé proplazy.snippet (vous pouvez soit l'importer, soit le coller dans le dossier standard que vous pouvez obtenir à partir du gestionnaire d'extraits de code)
Voici un exemple de sa sortie:
Voici le contenu du fichier d'extrait: (enregistrer sous proplazy.snippet)
la source
Je ne pense pas que cela soit possible avec du C # pur. Mais vous pouvez le faire en utilisant un réécriveur IL comme PostSharp . Par exemple, il vous permet d'ajouter des gestionnaires avant et après des fonctions en fonction des attributs.
la source
Operator ?? = est disponible en utilisant C # 8.0 et versions ultérieures, vous pouvez donc le faire encore plus concis:
la source
Je l'ai fait comme ça:
et plus tard, vous pouvez l'utiliser comme
la source
public ISet<String> RegularProperty {get;set} public string CalculatedProperty => this.LazyValue(() => { return string.Join(",", RegularProperty.ToArray()); });
https://github.com/bcuff/AutoLazy utilise Fody pour vous donner quelque chose comme ça
la source
et j'appelle comme ci-dessous
la source
Si vous utilisez un constructeur lors de l'initialisation tardive, les extensions suivantes peuvent également être utiles
Usage
la source
LazyInitializer.EnsureInitialized()
? Parce que d'après ce que je peux dire, en plus des fonctionnalités ci-dessus,LazyInitializer
fournit une gestion des erreurs ainsi qu'une fonctionnalité de synchronisation. Code source de LazyInitializer .