10
votes

Instantiquant des objets nuls avec ?? Opérateur

Considérez le scénario typique suivant: xxx pré>

Je me demande ce qui est pensé du remplacement suivant à l'aide de la ?? Opérateur: P>

anObject = anObject ?? new AClass();


5 commentaires

Si ce serait une odeur de code, cela ne serait pas introduit en premier lieu. La deuxième forme est plus concise et devrait être préférée.


@ Jeroenvannevel: la question est pas si l'opérateur ?? est une odeur de code, mais si elle utilise dans une expression qui est attribuée à ce qui est passé comme l'un de ses Les opérandes sont l'odeur de code.


En fait, c'est quatre lignes ...


Ce que je n'ai jamais compris, c'est pourquoi il n'y a pas de x ?? = y; opérateur, équivalent à x = x ?? y; . Il y a + = , - = , * = , etc ...


Mais vous NE PAS avez anObject = anObject au début. Vous avez une affectation avec anoObject à gauche et anoObject ?? Nouvelle aclass () à droite.


4 Réponses :


12
votes

mise à jour:

AS O. R. MAPPER a souligné, la question est de faire si l'auto-affectation est une odeur de code. C'est 6 et deux 3s dans mon livre. L'affectation n'est guère une opération coûteuse et vous le faites dans d'autres domaines à tout prix avec la plupart des opérateurs de mathématiques.

J'ai tendance à penser que ce n'est pas une odeur de code.


Je fais cela tout le temps des objets paresseux (une légère variation de votre exemple): xxx

Je pense que c'est bien. Curieusement, je n'ai pas tendance à utiliser paresseux ... Je ne sais pas pourquoi, mais encore une fois, je ne fais pas très souvent des objets paresseux. paresseux est plus expressif dans son intention, comme dans, vous pouvez lire que l'article est instancié paresseusement, mais techniquement, il ajoute un autre objet objet sur le dessus d'un élément existant. Je ne m'inquiète pas vraiment à ce sujet de toute façon vraiment.

comme pour "le surmonter", je pense que cela tombe probablement dans cette catégorie. Chacun à leur propre dans ce cas, je pense.


4 commentaires

Merci une très bonne idée que je marquerai la réponse après 12 minutes, je ne peux pas maintenant merci.


Je ne prétends pas d'entre eux est une odeur de code. Dans mon commentaire ci-dessus, j'aimerais juste souligner que, si "" il "a été introduit - it étant le ?? Opérateur - n'est pas pertinent, car la question ne se demande pas si l'opérateur lui-même est une odeur de code, mais le moyen particulier de l'utiliser montré dans la question.


@ O.R.Mapper Désolé je vais re-mot, ce que je voulais dire, c'est que vous avez souligné que la question portait sur l'auto-affectation et que c'était une odeur de code. Ma faute.


Conseil: Utilisez le constructeur paresseux qui prend un func délégué (lambda) si le constructeur de votre classe pourrait lancer une exception. Cela mettra en cache votre exception, où le constructeur de No-Ag lancerait une cibleVocationException. (Mieux - éviter de jeter des exceptions des constructeurs.)



6
votes

sans attribuer le résultat de l'expression de la même variable - par exemple. a = b ?? Nouvelle vérification (); - Ce modèle va bien et que cela sert à quelque chose comme une nouvelle instance par défaut: xxx

Dans ce cas, l'objet nouvellement créé n'est pas stocké. Pour une réutilisation ultérieure.

Lorsque vous attribuez à la même variable, on dirait que vous initialisez quelque chose de paresseusement, dans ce cas en utilisant paresseux serait le moyen plus expressif d'aller: xxx p> L'instance sera créée au plus tard lorsque la dernière ligne est exécutée.


3 commentaires

Bien que je suis d'accord paresseux est plus expressif et est évidemment conçu pour la tâche, je gagne un peu lorsque je lis "la voie préférée d'aller" comme si elle avait été universellement acceptée.


@AdamHouldsworth: Vous avez raison, j'ai amélioré mon choix de mots dans la réponse.


+1 pour cette correction. J'ai généralement tendance à rester en dehors des questions de «meilleure pratique», mais j'ai senti que celui-ci était plus inoffensif que le plus. Vous avez tendance à copier beaucoup de flak si vous allez contre la "NORM" :-P



1
votes
Option A                            Option B                            Description
IL_0000:  ldnull                    IL_0000:  ldnull                    // Push a null reference on the stack.
IL_0001:  stloc.0     // anObject   IL_0001:  stloc.0     // anObject   // Pop a value from stack into local variable 0.
IL_0002:  ldloc.0     // anObject   IL_0002:  ldloc.0     // anObject   // Load local variable 0 onto stack
                                    IL_0003:  dup                       // Duplicate the value on the top of the stack.
IL_0003:  brtrue.s    IL_000B       IL_0004:  brtrue.s    IL_000C       // Branch to target if value is non-zero
                                    IL_0006:  pop                       // Pop value from the stack
IL_0005:  newobj      AClass..ctor  IL_0007:  newobj      AClass..ctor  // Allocate an uninitialized object or value type and call ctor
IL_000A:  stloc.0     // anObject   IL_000C:  stloc.0     // anObject   // Pop a value from stack into local variable 0.

1 commentaires

Cela fait-il de dire que cela ne fait que dire que l'opérateur de coalesce produit plus de concis IL? Je ne sais pas comment cela seul sans explication ne répond rien, sans parler de la façon dont il a été avancé deux fois ...



0
votes

Il y a quelques motifs que j'ai vus utilisés dans les modèles de vue WPF (où je vois ce modèle utilisé principalement):

Méthode 1 Non paresseux: P>

public class ViewModel
{
    private SomeValue _value;

    public SomeValue Value { get { return _value ?? (_value = new SomeValue()); } } 
}


0 commentaires