12
votes

Comment créer un objet nul dans C #

Le refactoring de Martin Fowler discute de la création d'objets NULL pour éviter de nombreux tests

public class Animal
{
    public virtual string Name { get; set; }
    public virtual string Species { get; set; }
    public virtual bool IsNull 
    { 
        get { return false; }
    }
}

public sealed class NullAnimal : Animal
{
    public override string Name
    {
        get{ return "NULL"; }
        set { }
    }
    public override string Species
    {
        get { return "NULL"; }
        set { }
    }
    public virtual bool IsNull
    {
        get { return true; }
    }
}


4 commentaires

Quel est le problème que vous essayez de résoudre? Quel est le problème avec les références nulles, exactement?


refactoring.com/catalog/introducenullObject.html


Votre propriété Isnull dans la classe Nullanimal devrait être une substitution, pas un virtuel.


Mais si nous parlons de fonctions, retourne des types booléens? Que devrais-je retourner? Faux? Vrai? Ce n'est pas sans équivoque, je pense. Autre chose, dans la propriété publique "espèces", vous retourne toujours null ... Donc, si quelqu'un fera des tests, il obtiendra probablement un résultat inattendu. Par exemple, quelqu'un obtient un objet "Nullanimal", mais il le considère comme "animal". Il peut donc supposer s'il établit des espèces sur des "mammifères", il obtiendra des "mammifères". Mais ce n'est pas. Ce n'est pas si simple, imho


5 Réponses :


25
votes

aller chercher la quantité de douleur que les concepts intéressants, tels que DBNULL, ont causé et réfléchir si cela est vraiment une bonne idée.

ProTIP: Si vous vérifiez constamment des références NULL, vous devez probablement repenser l'API un peu pour vous aider à empêcher les objets nul plus proches du haut de la pile.

ProTIP II: Avoir quelque chose de jeter une exception lorsqu'il y a une null inattendue est en fait bien et dandy. Les choses devraient aller en flèche si vous avez des nuls où il ne devrait pas y avoir null.


7 commentaires

+1. NULL motif est un anti-motif imo. Jetez des nuls indésirables et vérifiez les nuls quand ils sont autorisés.


L'idée du modèle NullObject est que les choses ne vont pas boom - en particulier dans le produit.


@Wyatt: Jeremyjarrell.com/archive/2007/08/01/46.aspx a une belle démonstration des avantages des objets nuls ... Mais je ne suis pas un grand fan d'eux, personnellement.


Il y a une place pour des objets NULL, tels que des nœuds sentinelles dans un arbre noir rouge, mais je ne suis pas convaincu qu'ils sont généralement une bonne idée, pour les raisons mentionnées par Randolpho.


@superTUX: Quel est le meilleur - Application de l'application et n'envoie pas de mauvaises données ou n'envoie pas de données mauvaises, car vous avez du fétiche anti-null Wierd Anti-Null?


@Wyatt cela dépend du logiciel vraiment, dans certains cas, peut-être que vous n'utiliseriez pas un modèle NullObject. Je ne suis pas un fétichiste - la question portait sur NullObjects. Par exemple, dans l'aviation ou le logiciel médical - l'application de l'application est probablement une mauvaise chose. Mais dans mon projet d'animaux probablement pas si mal.


Ce n'est pas une sorte de "fétiche anti-null". Appelez cela que non seulement le respect de l'affiche originale, mais il y a des cas où une API pourrait en bénéficier en pardonnant. La comparaison avec DBNull / NULL n'est pas exacte, car DBNULL n'hérite pas de NULL. Puisque Nullanimal est un animal, passant nullanimal à quelque chose d'attendre qu'un animal ne peut pas causer de problèmes. Vous ne pouvez pas dire que sur quelque chose qui passe dbnull à quelque chose qui s'attend à NULL. Tout ce qui a dit +1 pour inviter la pensée sur la question de savoir s'il est une bonne idée. Dans la plupart des cas, j'ai tendance à convenir que ce n'est pas le cas.



3
votes

Le point du modèle d'objet NULL est qu'il ne nécessite pas de vérification null pour empêcher un crash ou une erreur.

Par exemple, si vous avez essayé d'effectuer une opération sur la propriété de l'espèce et que c'était Null - il serait null. Cause une erreur. p>

Donc, vous ne devez pas avoir besoin d'une méthode ISNULL, il suffit de retourner quelque chose dans le getter qui ne causera pas de crash / d'erreur / erreur, par exemple: P>

public class Animal
{
    public virtual string Name { get; set; }
    public virtual string Species { get; set; }
}

public sealed class NullAnimal : Animal
{
    public override string Name
    {
        get{ return string.Empty; }
        set { ; }
    }
    public override string Species
    {
        get { return string.Empty; }
        set { ; }
    }
}


2 commentaires

Bien, mais cela enfreint toujours l'appel du membre virtuel dans la règle du constructeur.


Techniquement pas, car il n'y a pas de constructeur.



2
votes

Vous utilisez cette approche que si elle est appropriée. Votre exemple d'un objet animal pourrait ne pas être un bon exemple car il ne présente pas de cas approprié où vous utiliseriez cette approche. Par exemple: xxx

Dans cet exemple, vous devez construire l'objet animal de sorte que si l'animal n'a pas de queue, il peut gérer avec succès la commande wertail () sans s'écraser. xxx

Vous n'avez pas besoin de faire une chèque nulle, mais peut simplement appeler animal.wagtail (), que l'animal a une queue ou non. < / p>


0 commentaires

11
votes

J'ai tendance à être d'accord avec Wyatt Barnett's Réponse en ce que vous devriez faire preuve de retenue lors de la création de ce type d'objets "null". Cela dit, il y a de belles raisons pour cela. À l'occasion.

J'ai aussi tendance à être d'accord avec La réponse de SuperTeux en ce que tout le point d'un objet NULL est de ne pas avoir besoin de vérifier s'il est null, vous devriez donc perdre la propriété Isnull. Si vous sentez vraiment que vous avez vraiment besoin de la propriété Isnull, lisez à nouveau la réponse de Wyatt et de reconsidérer.

et merci Craigtp pour les liens Nice pour plus d'informations. Bonnes choses.

Maintenant, je suppose que dans votre code réel, vous avez un constructeur qui tente de définir les valeurs de nom ou d'espèces (quel que soit l'équivalent de votre code réel pourraient être appelés). Sinon, pourquoi obtiendriez-vous l'avertissement / l'erreur "Membre virtuel dans le constructeur"? Je rencontre quelques problèmes similaires lors de l'utilisation de la nouvelle entreprise myProperty {get; ensemble; } Raccourci moi-même (en particulier lorsqu'il est utilisé dans les structures, et ne me faites pas commencer à propos de la diffusion des versions). Votre solution consiste à ne pas utiliser le raccourci, mais faites-la de la manière à l'ancienne. xxx

Ceci résout le problème de la définition de vos propriétés virtuelles dans le constructeur. Au lieu de cela, vous définissez vos valeurs de champ privées (quelque chose que vous n'avez pas la possibilité de référencer si vous utilisez le raccourci). Pour un crédit supplémentaire, compilez les deux méthodes et utilisez le réflecteur pour examiner les assemblages résultants.

Plus j'utilise le {get; ensemble; } raccourci, plus je n'aime pas ça.


0 commentaires

0
votes

J'aimerais mentionner ici quelques détails intéressants. Regardez votre classe. A-t-il une logique dedans? Ce n'est pas une classe en son sens, il s'agit d'une structure de données. Ce que vous essayez de faire est d'appliquer un modèle d'objet NULL à quelque chose qu'il ne s'applique pas. Les structures de données sont plus proches des types de valeur que les classes. Par exemple, la vérification nulle peut être bonne en place pour résoudre votre problème. Null Object Motif n'est pas quelque chose que vous devriez toujours suivre. Null Object Motif est une chose que vous pouvez utiliser pour éviter la violation du principe de substitution de Liskov pour représenter une classe qui ne fait rien, car NULL n'est pas une substitution appropriée pour une classe car c'est une valeur, mais pas une classe. Mais les choses sont différentes avec les types de valeur et les structures de données. Null est la valeur! Donc, dans ce cas, la vérification nulle est la bonne chose à faire.


0 commentaires