Les fonctions retourneront-elles null ou un objet vide?

qu'est-Ce que le meilleures pratiques lorsque le renvoi de données à partir de fonctions. Vaut-il mieux retourner un objet nul ou vide? Et pourquoi devrait-on faire l'un sur l'autre?

considérez ceci:

public UserEntity GetUserById(Guid userId)
{
     //Imagine some code here to access database.....

     //Check if data was returned and return a null if none found
     if (!DataExists)
        return null; 
        //Should I be doing this here instead? 
        //return new UserEntity();  
     else
        return existingUserEntity;
}

laisse prétendre qu'il y aurait des cas valides dans ce programme qu'il n'y aurait aucune information d'utilisateur dans la base de données avec ce guide. J'imagine qu'il ne serait pas opportun de lancer une exception dans ce cas?? J'ai aussi l'impression que la manipulation d'exception peut nuire à la performance.

210
demandé sur 7wp 2009-10-26 21:44:05
la source

30 ответов

Retourner null est généralement la meilleure idée si vous avez l'intention d'indiquer qu'aucune donnée n'est disponible.

un objet vide implique que des données ont été retournées, alors que retourner null indique clairement que rien n'a été retourné.

de plus, retourner un null entraînera une exception null si vous tentez d'accéder à des membres dans l'objet, ce qui peut être utile pour mettre en évidence le code buggy - tenter d'accéder à un membre de rien ne fait pas sens. L'accès aux membres d'un objet vide n'échouera pas, ce qui signifie que les bogues peuvent passer inaperçus.

208
répondu ljs 2009-11-26 10:08:12
la source

cela dépend de ce qui a le plus de sens pour votre cas.

est-ce logique de retourner null, par exemple"aucun utilisateur n'existe"?

ou est-ce logique de créer un utilisateur par défaut? Cela a le plus de sens lorsque vous pouvez supposer en toute sécurité que si un utilisateur n'existe pas, le code d'appel veut que l'un existe quand il le demande.

ou est-ce logique de lancer une exception (a la "FileNotFound") si le code d'appel est vous exigez un utilisateur dont l'identité n'est pas valide?

cependant - du point de vue de la séparation des préoccupations/PRS, les deux premières sont plus correctes. Et techniquement le premier est le plus correct (mais seulement par un cheveu) - GetUserById ne devrait être responsable que d'une chose - obtenir l'utilisateur. Gérer son propre cas" l'utilisateur n'existe pas " en retournant quelque chose d'autre pourrait être une violation de SRP. La séparation en un contrôle différent - bool DoesUserExist(id) serait appropriée si vous choisissez de lancer une exception.

basé sur de nombreux commentaires au-dessous de : si c'est une question de conception au niveau de L'API, cette méthode pourrait être analogue à "OpenFile"ou " ReadEntireFile". Nous "ouvrons" un utilisateur à partir d'un dépôt et nous hydratons l'objet à partir des données résultantes. Une exception pourrait être appropriée dans ce cas. Il peut ne pas l'être, mais il pourrait être.

Toutes les approches sont acceptables - cela dépend juste, basé sur le contexte plus large de L'API/application.

44
répondu Rex M 2009-10-26 22:33:42
la source

personnellement, J'utilise NULL. Il indique clairement qu'il n'y a pas de données à retourner. Mais il y a des cas où un Null Object peut être utile.

30
répondu Fernando 2009-10-26 21:48:32
la source

si votre type de retour est un tableau, retournez un tableau vide sinon retournez null.

27
répondu Darin Dimitrov 2009-10-26 21:48:49
la source

vous devriez jeter une exception (seulement) si un contrat spécifique est rompu.

Dans votre exemple spécifique, Demander une identité D'utilisateur basée sur un Id connu, cela dépend du fait que si les utilisateurs manquants (supprimés) sont un cas attendu. Si c'est le cas, retourner null mais si ce n'est pas un cas prévu alors jeter une exception.

Notez que si la fonction était appelée UserEntity GetUserByName(string name) elle ne lancerait probablement pas mais retournerait null. Dans les deux cas, le retour un vide UserEntity serait inutile.

pour les chaînes, tableaux et collections la situation est généralement différente. Je me souviens de certains formulaires de lignes directrices selon lesquels les méthodes devraient accepter null comme liste "vide", mais renvoyer des collections de zéro longueur plutôt que null . De même pour les chaînes. Notez que vous pouvez déclarer des tableaux vides: int[] arr = new int[0];

12
répondu Henk Holterman 2009-10-27 01:20:16
la source

il s'agit d'une question d'affaires, dépendant du fait que l'existence d'un utilisateur avec un identifiant spécifique est un cas d'utilisation normal prévu pour cette fonction, ou est-ce une anomalie qui empêchera l'application de remplir avec succès quelle que soit la fonction que cette méthode fournit à l'objet utilisateur...

si c'est une" exception", en ce que l'absence d'un utilisateur avec cette Id empêchera l'application de remplir avec succès quelle que soit la fonction qu'elle fait, (dire nous créons une facture pour un client à qui nous avons envoyé un produit...), alors cette situation devrait jeter un ArgumentException (ou une autre exception personnalisée).

si un utilisateur manquant est ok, (un des résultats normaux potentiels de l'appel de cette fonction) alors retourner un null....

EDIT: (pour répondre au commentaire de Adam dans une autre réponse)

si l'application contient plusieurs processus opérationnels, dont un ou plusieurs nécessitent une Utilisateur afin de compléter avec succès, et un ou plusieurs d'entre eux peuvent compléter avec succès sans un utilisateur, alors l'exception devrait être jeté plus loin dans la pile d'appels, plus près de l'endroit où les processus d'affaires qui exigent un utilisateur appellent ce fil de l'exécution. Méthodes entre cette méthode et que le point (où l'exception est levée) doit communiquer qu'aucun utilisateur n'existe (null, boolean, c'est un détail d'implémentation).

mais si tous processus dans l'application exiger un utilisateur, je voudrais encore jeter l'exception dans cette méthode...

11
répondu Charles Bretana 2009-11-28 14:43:59
la source

personnellement, je retournerais null, parce que c'est ainsi que je m'attendrais à ce que la couche DAL/Repository agisse.

S'il n'existe pas, ne retournez rien qui pourrait être interprété comme une recherche réussie d'un objet, null fonctionne magnifiquement ici.

la chose la plus importante est d'être cohérent à travers votre couche DAL/Repos, de cette façon vous ne vous trompez pas sur la façon de l'utiliser.

10
répondu Alex Moore 2009-10-26 21:47:51
la source

j'ai tendance à

  • return null si l'objet id n'existe pas alors qu'on ne sait pas à l'avance si devrait .
  • throw si l'objet id n'existe pas alors qu'il devrait exister.

Je différencie ces deux scénarios avec ces trois types de méthodes. Premier:

Boolean TryGetSomeObjectById(Int32 id, out SomeObject o)
{
    if (InternalIdExists(id))
    {
        o = InternalGetSomeObject(id);

        return true;
    }
    else
    {
        return false;
    }
}

la Deuxième:

SomeObject FindSomeObjectById(Int32 id)
{
    SomeObject o;

    return TryGetObjectById(id, out o) ? o : null;
}

troisième:

SomeObject GetSomeObjectById(Int32 id)
{
    SomeObject o;

    if (!TryGetObjectById(id, out o))
    {
        throw new SomeAppropriateException();
    }

    return o;
}
7
répondu Johann Gerell 2010-10-19 16:04:44
la source

encore une autre approche consiste à passer dans un objet callback ou délégué qui fonctionnera sur la valeur. Si une valeur n'est pas trouvée, la fonction de rappel n'est pas appelé.

public void GetUserById(Guid id, UserCallback callback)
{
    // Lookup user
    if (userFound)
        callback(userEntity);  // or callback.Call(userEntity);
}

cela fonctionne bien quand vous voulez éviter les vérifications null sur tout votre code, et quand ne pas trouver une valeur n'est pas une erreur. Vous pouvez également fournir un rappel lorsque aucun objet n'est trouvé, si vous avez besoin d'un traitement spécial.

public void GetUserById(Guid id, UserCallback callback, NotFoundCallback notFound)
{
    // Lookup user
    if (userFound)
        callback(userEntity);  // or callback.Call(userEntity);
    else
        notFound(); // or notFound.Call();
}

la même approche un seul objet pourrait ressembler à:

public void GetUserById(Guid id, UserCallback callback)
{
    // Lookup user
    if (userFound)
        callback.Found(userEntity);
    else
        callback.NotFound();
}

du point de vue de la conception, j'aime vraiment cette approche, mais j'ai l'inconvénient de rendre le site d'appel plus volumineux dans des langues qui ne supportent pas facilement les fonctions de première classe.

6
répondu Marc 2009-11-07 18:05:25
la source

Nous utilisons CSLA.NET et il estime que l'échec d'une extraction de données doit retourner un objet "vide". Cela est en fait assez gênant, car il exige la convention de vérifier si obj.IsNew rathern plutôt que obj == null .

comme le mentionnait une affiche précédente, les valeurs de retour null feront immédiatement échouer le code, réduisant ainsi la probabilité de problèmes de furtivité causés par des objets vides.

personnellement, je pense null est plus élégant.

c'est un cas très courant, et je suis surpris que les gens ici semblent surpris par cela: sur n'importe quelle application web, les données sont souvent récupérées à l'aide d'un paramètre querystring, qui peut évidemment être altéré, ce qui exige que le développeur gère les incidences de"non trouvé".

, Vous pouvez gérer cela par:

if (User.Exists(id)) {
  this.User = User.Fetch(id);
} else {
  Response.Redirect("~/notfound.aspx");
}

...mais c'est un appel supplémentaire à la base de données à chaque fois, ce qui peut être un problème sur pages très achalandées. Considérant ce qui suit:

this.User = User.Fetch(id);

if (this.User == null) {
  Response.Redirect("~/notfound.aspx");
}

...ne nécessite qu'un appel.

4
répondu Keith Williams 2009-10-27 01:14:38
la source

je préfère null , car il est compatible avec l'opérateur ?? .

4
répondu Andrew Medico 2009-10-27 06:18:32
la source

je dirais "retour nul" au lieu d'un objet vide.

mais le cas précis que vous avez mentionné ici, vous recherchez un utilisateur par ID utilisateur, qui est Tri de la clé de cet utilisateur, dans ce cas je voudrais probablement to lancer une exception si aucune instance de l'utilisateur n'est trouver.

C'est la règle que j'ai généralement suivre:

  • si aucun résultat trouvé sur une recherche par opération de clé primaire, jeter ObjectNotFoundException.
  • si aucun résultat trouvé sur une Rechercher selon tout autre critère, retourner la valeur null.
  • si aucun résultat trouvé sur une recherche par un critère non-clé qui peut retourner plusieurs objets retourner une collection vide.
4
répondu Partha Choudhury 2010-10-19 15:22:20
la source

cela variera en fonction du contexte, mais je retournerai généralement null si je suis à la recherche d'un objet particulier (comme dans votre exemple) et je retournerai une collection vide si je suis à la recherche d'un ensemble d'objets mais il n'y en a aucun.

si vous avez fait une erreur dans votre code et retourner null mène à null pointer exceptions, alors le plus tôt vous attrapez que le mieux. Si vous retournez un objet vide, son utilisation initiale peut fonctionner, mais vous pourriez avoir des erreurs plus tard.

3
répondu Jacob Mattison 2009-10-26 21:48:17
la source

le meilleur dans ce cas retourner" null " dans un cas il n'y a pas un tel utilisateur. Également rendre votre méthode statique.

Edit:

habituellement les méthodes comme celle-ci sont des membres d'une certaine classe "Utilisateur" et n'ont pas accès à ses membres d'instance. Dans ce cas, la méthode doit être statique, sinon vous devez créer une instance de "User" et ensuite appeler la méthode GetUserById qui retournera une autre instance de "User". D'accord c'est déroutant. Mais si la méthode GetUserById est membre d'une classe" DatabaseFactory " - pas de problème de le laisser comme membre d'instance.

3
répondu Kamarey 2009-10-26 22:14:43
la source

je renvoie personnellement une instance par défaut de l'objet. La raison en est que je m'attends à ce que la méthode renvoie zéro à plusieurs ou zéro à un (selon le but de la méthode). La seule raison pour laquelle ce serait un État d'erreur de n'importe quelle sorte, en utilisant cette approche, est si la méthode ne retournait aucun objet(s) et était toujours attendue (en termes de un à plusieurs ou singulier retour).

quant à la supposition qu'il s'agit d'une question de domaine d'affaires - Je ne le vois pas de du côté de l'équation. La normalisation des types de retour est une question d'architecture d'application valide. À tout le moins, il fait l'objet d'une normalisation dans les pratiques de codage. Je doute qu'il y ait un utilisateur commercial qui va dire "dans le scénario X, donnez-leur un nul".

3
répondu Joseph Ferris 2009-10-26 22:27:06
la source

dans nos objets D'affaires, nous avons 2 principales méthodes Get:

Pour garder les choses simples dans le contexte ou vous question serait:

// Returns null if user does not exist
public UserEntity GetUserById(Guid userId)
{
}

// Returns a New User if user does not exist
public UserEntity GetNewOrExistingUserById(Guid userId)
{
}

la première méthode est utilisée lors de l'obtention d'entités spécifiques, la deuxième méthode est utilisée spécifiquement lors de l'ajout ou l'édition d'entités sur les pages web.

Cela nous permet d'avoir le meilleur des deux mondes dans le contexte où ils sont utilisés.

3
répondu Mark Redman 2009-10-26 22:31:32
la source

je suis un étudiant en informatique français, alors excusez mon mauvais anglais. Dans nos classes, nous dit que cette méthode ne devrait jamais retourner null, ni un objet vide. L'utilisateur de cette méthode est censée vérifier d'abord que l'objet qu'il cherche existe avant d'essayer de l'obtenir.

en utilisant Java, on nous demande d'ajouter un assert exists(object) : "You shouldn't try to access an object that doesn't exist"; au début de toute méthode qui pourrait retourner null, pour exprimer la "condition préalable" (Je ne sais pas quel est le mot en anglais).

IMO ce n'est vraiment pas facile à utiliser, mais c'est ce que j'utilise, en attendant quelque chose de mieux.

3
répondu Saend 2009-10-28 12:45:25
la source

si le cas de l'utilisateur n'étant pas trouvé apparaît assez souvent, et que vous voulez y faire face de différentes façons selon les circonstances (parfois en lançant une exception, parfois en remplaçant un utilisateur vide), vous pouvez également utiliser quelque chose proche de F#'s Option ou du type Maybe de Haskell, qui sépare explicitement le cas de "Aucune valeur" de " Trouvé quelque chose!'. Le code d'accès à la base de données pourrait ressembler à ceci:

public Option<UserEntity> GetUserById(Guid userId)
{
 //Imagine some code here to access database.....

 //Check if data was returned and return a null if none found
 if (!DataExists)
    return Option<UserEntity>.Nothing; 
 else
    return Option.Just(existingUserEntity);
}

et être utilisé comme ceci:

Option<UserEntity> result = GetUserById(...);
if (result.IsNothing()) {
    // deal with it
} else {
    UserEntity value = result.GetValue();
}

malheureusement, tout le monde semble rouler un type comme celui-ci.

3
répondu yatima2975 2009-10-28 13:58:54
la source

en général, je retourne null. Il fournit un mécanisme rapide et facile pour détecter si quelque chose a foiré sans jeter des exceptions et en utilisant des tonnes d'essayer/attraper partout.

2
répondu whatsisname 2009-10-26 21:48:38
la source

pour les types de collection je retournerais une Collection vide, pour tous les autres types je préfère utiliser les motifs NullObject pour retourner un objet qui implémente la même interface que celle du type de retour. pour plus de détails sur le modèle, consultez lien texte

en utilisant le schéma NullObject ce serait: -

public UserEntity GetUserById(Guid userId)

{ // Imaginez un peu de code ici pour accéder à la base de données.....

 //Check if data was returned and return a null if none found
 if (!DataExists)
    return new NullUserEntity(); //Should I be doing this here instead? return new UserEntity();  
 else
    return existingUserEntity;

}

class NullUserEntity: IUserEntity { public string getFirstName(){ return ""; } ...} 
2
répondu vikram nayak 2009-10-26 23:01:38
la source

pour mettre ce que d'autres ont dit d'une manière pithier...

sont des Exceptions pour des circonstances Exceptionnelles

si cette méthode est la couche pure d'accès aux données, je dirais que compte tenu d'un paramètre qui est inclus dans une instruction select, il s'attend à ce que je ne puisse pas trouver de lignes à partir desquelles construire un objet, et donc retourner null serait acceptable car c'est la logique d'accès aux données.

On d'un autre côté, si je m'attendais à ce que mon paramètre reflète une clé primaire et que je n'obtienne que la rangée une , si j'obtiens plus d'une réponse, je lancerai une exception. 0 est ok pour retourner null, 2 n'est pas.

maintenant, si j'avais un code de connexion qui vérifiait contre un fournisseur LDAP puis vérifié contre un DB pour obtenir plus de détails et je m'attendais à ce que ceux-ci devraient être synchronisés à tout moment, je pourrais jeter l'exception alors. Comme d'autres l'ont dit, ce sont les règles d'affaires.

maintenant je vais dire que c'est une règle générale . Il y a des moments où vous pouvez les diviser. Cependant, mon expérience et mes expériences avec C# (beaucoup de cela) et Java (un peu de cela) m'ont appris qu'il est beaucoup plus cher performance sage de traiter les exceptions que de traiter les questions prévisibles via la logique conditionnelle. Je parle de 2 ou 3 ordres de grandeur plus chers dans certains cas. Donc, si c'est possible votre code pourrait finir dans une boucle, alors je conseillerais de retourner null et de le tester.

2
répondu Jim L 2009-10-27 06:31:09
la source

pardonne mon pseudo-php / code.

je pense que ça dépend vraiment de l'utilisation prévue du résultat.

si vous avez l'intention d'éditer/modifier la valeur de retour et la sauvegarder, puis retourner un objet vide. De cette façon, vous pouvez utiliser la même fonction pour peupler des données sur un objet nouveau ou existant.

Dire que j'ai une fonction qui prend une clé primaire et d'un tableau de données, remplit la ligne avec des données, puis enregistre l'résultant enregistrement à la db. Puisque j'ai l'intention de peupler l'objet avec mes données de toute façon, il peut être un avantage énorme pour obtenir un objet vide de retour de la part du getter. De cette façon, je peux effectuer des opérations identiques dans les deux cas. Vous utilisez le résultat de la fonction get n'importe quoi.

exemple:

function saveTheRow($prim_key, $data) {
    $row = getRowByPrimKey($prim_key);

    // Populate the data here

    $row->save();
}

Ici, nous pouvons voir que la même série d'opérations manipule tous les enregistrements de ce type.

Toutefois, si l'intention ultime de l' return value est de lire et de faire quelque chose avec les données, puis je retournerais null. De cette façon, je peux très rapidement déterminer s'il n'y a pas eu de données retournées et afficher le message approprié à l'utilisateur.

Habituellement, je vais attraper des exceptions dans ma fonction qui récupère les données (afin que je puisse enregistrer des messages d'erreur, etc...) puis retourner null directement à partir de la capture. Il n'importe généralement pas à l'utilisateur final ce que le problème est, donc je trouve le meilleur pour encapsuler mon erreur enregistrement/traitement directement dans la fonction qui récupère les données. Si vous maintenez une base de codes partagée dans n'importe quelle grande entreprise, c'est particulièrement bénéfique car vous pouvez forcer la journalisation/manipulation d'erreur sur même le programmeur le plus paresseux.

exemple:

function displayData($row_id) {
    // Logging of the error would happen in this function
    $row = getRow($row_id);
    if($row === null) {
        // Handle the error here
    }

    // Do stuff here with data
}

function getRow($row_id) {
 $row = null;
 try{
     if(!$db->connected()) {
   throw excpetion("Couldn't Connect");
  }

  $result = $db->query($some_query_using_row_id);

  if(count($result) == 0 ) {
   throw new exception("Couldn't find a record!");
  }

  $row = $db->nextRow();

 } catch (db_exception) {
  //Log db conn error, alert admin, etc...
  return null; // This way I know that null means an error occurred
 }
 return $row;
}

C'est ma règle générale. Il a bien fonctionné jusqu'à présent.

2
répondu 2009-10-28 06:12:45
la source

question Intéressante et je pense qu'il n'y a pas de "bonne" réponse, puisqu'il dépend toujours de la responsabilité de votre code. Est-ce que votre méthode sait si aucune donnée trouvée est un problème ou pas? Dans la plupart des cas, la réponse est "non" et c'est pourquoi retourner null et laisser l'appelant gérer sa situation est parfait.

peut-être une bonne approche pour distinguer les méthodes de lancer De null-méthodes de retour est de trouver une convention dans votre équipe: les méthodes qui disent qu'ils " obtenir" quelque chose devrait jeter une exception s'il n'y a rien à obtenir. Les méthodes qui peuvent retourner null pourraient être nommées différemment, peut-être "trouver"..." plutôt.

2
répondu Marc Wittke 2009-10-28 14:25:32
la source

si l'objet retourné est quelque chose qui peut être itéré, je retournerais un objet vide, de sorte que je n'ai pas à tester null en premier.

exemple:

bool IsAdministrator(User user)
{
    var groupsOfUser = GetGroupsOfUser(user);

    // This foreach would cause a run time exception if groupsOfUser is null.
    foreach (var groupOfUser in groupsOfUser) 
    {
        if (groupOfUser.Name == "Administrators")
        {
            return true;
        }
    }

    return false;
}
2
répondu Jan Aagaard 2009-10-28 15:54:49
la source

j'aime ne pas retourner null d'une méthode, mais utiliser L'Option Type fonctionnel à la place. Les méthodes qui ne peuvent pas retourner aucun résultat retournent une Option vide, plutôt que null.

aussi, de telles méthodes qui ne peuvent retourner aucun résultat devrait indiquer que par leur nom. Je mets normalement Try, TryGet ou TryFind au début du nom de la méthode pour indiquer qu'elle peut retourner un résultat vide (par exemple TryFindCustomer, TryLoadFile, etc.).

qui permet au l'appelant applique différentes techniques, comme la tuyauterie de collecte (voir de Martin Fowler "Pipeline de collecte ) sur le résultat.

voici un autre exemple où l'Option de retour au lieu de null est utilisée pour réduire la complexité du code: comment réduire la complexité cyclomatique: Option Type fonctionnel

"
2
répondu Zoran Horvat 2015-06-02 15:28:15
la source

plus de viande à broyer: disons que mon DAL renvoie un NULL pour GetPersonByID comme conseillé par certains. Que devrait faire mon BLL (plutôt mince) s'il reçoit un NULL? Passer que NULL up et laisser le consommateur final s'inquiéter à ce sujet (dans ce cas, un ASP.Net page)? Et si le BLL faisait une exception?

la BLL peut être utilisée par ASP.Net et gagner App, ou une autre bibliothèque de classe - je pense qu'il est injuste d'attendre le consommateur final à intrinsèquement "savoir" que la méthode GetPersonByID renvoie un null (à moins que les types null ne soient utilisés, Je suppose).

mon avis (pour ce que ça vaut) est que mon DAL retourne nul si rien n'est trouvé. Pour certains objets, c'est ok - ça pourrait être une liste de choses 0:many, donc ne pas avoir de choses est très bien (par exemple une liste de livres préférés). Dans ce cas, mon BLL retourne une liste vide. Pour la plupart des choses d'entité simple (par exemple utilisateur, compte, facture) si je n'en ai pas un, alors c'est certainement un problème et un lancer une exception coûteuse. Cependant, si l'on voit qu'un utilisateur est retracé par un identifiant unique qui lui a été donné précédemment par l'application, il devrait toujours retourner un utilisateur, l'exception est une exception "correcte", comme dans c'est exceptionnel. Le consommateur final du BLL (ASP.Net par conséquent, un gestionnaire D'Exception non manipulé sera utilisé au lieu d'emballer chaque appel pour GetPersonByID dans un bloc try - catch.

S'il y a un problème flagrant dans mon approche, s'il vous plaît laissez-moi savoir que je suis toujours désireux d'apprendre. Comme l'ont dit d'autres affiches, les exceptions sont des choses coûteuses, et l'approche de la "vérification d'abord" est bonne, mais les exceptions devraient être tout simplement exceptionnelles.

je profite de ce post, beaucoup de bonnes suggestions pour "ça dépend" scénarios :-)

1
répondu Mike Kingscott 2009-10-28 14:11:16
la source

je pense que les fonctions ne devraient pas retourner null, pour la santé de votre base de code. Je peux penser à quelques raisons:

il y aura une grande quantité de clauses de garde traitant de la référence nulle if (f() != null) .

Qu'est-ce que null , est-ce une réponse acceptée ou un problème? Est null un état valide pour un objet spécifique? (imaginez que vous êtes un client pour le code). Tous les types de référence peuvent être nuls, mais devraient-ils l'être?

Avoir null dans les parages donnera presque toujours quelques exceptions NullRef inattendues de temps en temps à mesure que votre base de code grandit.

il y a des solutions, tester-doer pattern ou la mise en œuvre du option type de la programmation fonctionnelle.

1
répondu gavri 2017-05-17 13:00:25
la source

je suis perplexe devant le nombre de réponses (sur le web) qui disent que vous avez besoin de deux méthodes: une méthode" IsItThere () "et une méthode" GetItForMe () " et donc cela conduit à une condition de course. Qu'est-ce qui ne va pas avec une fonction qui renvoie null, l'assignant à une variable, et vérifiant la variable Pour Null tout dans un test? Mon ancien code C était peppered avec

si (NULL != (variable = fonction(arguments...))] {

donc vous obtenez la valeur (ou null) dans une variable, et le résultat tout à la fois. A cet idiome été oublié? Pourquoi?

0
répondu no comprende 2014-11-07 19:06:15
la source

je suis d'accord avec la plupart des messages ici, qui tendent vers null .

mon raisonnement est que générer un objet vide avec des propriétés non nulles peut causer des bugs. Par exemple, une entité avec un int ID bien aurait une valeur initiale de ID = 0 , qui est une valeur valide. Doit cet objet, dans certaines circonstances, être sauvés de la base de données, ce serait une mauvaise chose.

pour quoi que ce soit avec un itérateur je voudrais toujours utilisez la collection vide. Quelque chose comme

foreach (var eachValue in collection ?? new List<Type>(0))

est une odeur de code à mon avis. Les propriétés de Collection ne devraient pas être nulles, jamais.

un boîtier de bord est String . Beaucoup de gens disent, String.IsNullOrEmpty n'est pas vraiment nécessaire, mais vous ne pouvez pas toujours distinguer entre une chaîne vide et null. De plus, certains systèmes de bases de données (Oracle) ne feront aucune distinction entre eux ( '' est stocké comme DBNULL ), vous êtes donc forcé de les manipuler également. La raison en est que la plupart des valeurs de chaîne de caractères proviennent soit de l'entrée de l'utilisateur, soit de systèmes externes, alors que ni les boîtes de textes, ni la plupart des formats d'échange n'ont de représentations différentes pour '' et null . Donc, même si l'utilisateur veut supprimer une valeur, il ne peut rien faire de plus que la compensation de contrôle d'entrée. Aussi la distinction des champs de base de données nullables et non-nullables nvarchar est plus que discutable, si votre SGBD n'est pas oracle - un champ obligatoire qui autorise '' est bizarre, votre interface utilisateur ne le permettrait jamais, donc vos contraintes ne sont pas cartographiées. Donc, la réponse ici, à mon avis, est de les traiter également, toujours.

concernant votre question sur les exceptions et la performance: Si vous lancez une exception que vous ne pouvez pas gérer complètement dans votre logique de programme, vous devez abandonner, à un certain point, quoi que votre programme fasse, et demander à l'utilisateur de refaire tout ce qu'il vient de faire. Dans ce cas, la pénalité de performance d'un catch est vraiment le moindre de vos soucis - avoir à demander à l'utilisateur est l'éléphant dans la salle (ce qui signifie re-rendu L'interface utilisateur complète, ou envoyer un peu de HTML via l'internet). Donc, si vous ne suivez pas l'anti-modèle de " Program Flow with Exceptions ", ne vous embêtez pas, il suffit de jeter un si cela a du sens. Même dans les cas limites, comme "exception de Validation", la performance n'est vraiment pas un problème, puisque vous devez demander à l'utilisateur encore une fois, en tout cas.

0
répondu Oliver Schimmer 2017-05-23 15:26:23
la source

An Motif TryGet Asynchrone:

pour les méthodes synchrones, je crois que le de @Johann Gerell 151990920" réponse est le modèle à utiliser dans tous les cas.

cependant le motif TryGet avec le paramètre out ne fonctionne pas avec les méthodes Async.

Avec C# 7 n-uplet d'Littéraux vous pouvez désormais le faire:

async Task<(bool success, SomeObject o)> TryGetSomeObjectByIdAsync(Int32 id)
{
    if (InternalIdExists(id))
    {
        o = await InternalGetSomeObjectAsync(id);

        return (true, o);
    }
    else
    {
        return (false, default(SomeObject));
    }
}
0
répondu ttugates 2018-07-28 00:03:42
la source

Autres questions sur c# .net function return-value