2010-05-17 12 views
14

J'ai un tas de chaînes dont j'ai besoin pour utiliser .Trim(), mais elles peuvent être nulles. Il serait beaucoup plus concise si je pouvais faire quelque chose comme:Annule l'opérateur null-coalescing

string endString = startString !?? startString.Trim(); 

retour Fondamentalement, la partie à droite si la partie à gauche est non nul, sinon juste retourner la valeur nulle. Je viens de finir par utiliser l'opérateur ternaire, mais est-il possible d'utiliser l'opérateur null-coalescing à cette fin?

+3

Je ne pense pas, tbh ce qui ne va pas avec '! String.IsNullOrEmpty (startString)? startString.Trim(): null; ' – flq

+1

Comme je comprends votre question, vous voulez propager null c'est-à-dire Si la chaîne est null, retourner null. Sinon, renvoyez la chaîne tronquée. Est-ce exact? Si tel est le cas, il n'y a pas d'opérateur intégré ou de méthode pour le faire. Vous pouvez utiliser un opérateur ternaire (comme vous l'avez fait) ou écrire une méthode. –

+0

J'attends toujours que cet opérateur fasse partie de la langue :( – PedroC88

Répondre

12

Vous pourrait créer une méthode d'extension qui renvoie null lorsqu'il essaie d'ajuster la valeur.

public String TrimIfNotNull(this string item) 
{ 
    if(String.IsNullOrEmpty(item)) 
    return item; 
    else 
    return item.Trim(); 
} 

Remarquez que vous ne pouvez pas le nommer Rogner car les méthodes d'extension ne peuvent pas remplacer les méthodes d'instance.

+0

Il se sent tellement mal que cela fonctionne quand 'item' est nul ... Mais, j'ai confirmé que cela fonctionne. 'chaîne s = null; s.TrimIfNotNull(); 'No' NullReferenceException' comme vous obtiendriez avec une méthode d'instance normale (même une qui ne fait référence à aucun membre). –

+0

Il est parfaitement logique pourquoi cela fonctionne. Les méthodes d'extension ne sont rien de plus que des méthodes statiques qui sont ajoutées à un objet. Vraiment, il n'y a aucune raison pour laquelle ils ne devraient pas travailler. La classe ne peut pas dépendre de ce qu'elle fait puisqu'elle n'a pas été créée lorsque la classe d'origine l'était, et elle ne peut accéder à aucune des méthodes ou objets privés. Il serait gênant de ne pas permettre l'utilisation sur un objet nul (bien que j'admette que c'est un peu bizarre au début). – kemiller2002

+1

Oui, le point culminant de cette fonctionnalité est la méthode d'extension IfNotNull: 'public V IfNotNull (cet accès T @in, Func )' – flq

4
string endString = string.IsNullOrEmpty(startString) ? startString : startString.Trim(); 

Bien que je suis aussi allé la voie d'écrire une méthode d'extension de chaîne appelée « safeTrim » qui fait ce que vous décrivez dans une méthode au lieu d'avoir à utiliser cette recette à chaque fois. Découvrez Kevin's respone pour le code. Wow J'ai eu toutes sortes de backward, de variables mal nommées et d'opérateurs ternaires inversés, raison de plus d'écrire une méthode d'extension et le code vérifie mieux que moi!

+1

Ninja-edit grâce au commentaire de Frank me rappelant que c'est 'string.IsNullOrEmpty (foo)' et non 'foo.IsNullOrEmpty()' –

+2

Vérifications Ce n'est pas ce qu'il demande –

+0

Ah, oui, au début je pensais que "le chèque vide est un no-op efficace" parce que le cas d'utilisation normal est juste de retourner "end String' à la fin au lieu de 'null', mais j'avais explicitement mis' null' à la fin. Modifié dans le cas d'utilisation normale, il rend la vérification null nulle et efficace. –

1

Utilisez

string endString = (startString ?? "").Trim(); 

Il utilise une chaîne vide si débutChaîne est nulle. Cela, cependant, pas renvoie null lorsque endString est null.

+0

Si startString est nul, il veut que endString soit nul.Votre échantillon va retourner string.Empty –

+0

Il est indiqué dans le post ... – AxelEckenberger

12

Non SPEC: Non pas que je l'aime, mais vous pouvez utiliser:

string endString = (startString ?? String.Empty).Trim(); 

SPEC, mieux comme méthode d'extension comme @ Kevin:

string endString = (startString == null ? null : startString.Trim()); 
+2

Genius. Merci! – rossipedia

+5

Ne propage null comme il a demandé –

+3

cela ne retourne pas null si startString est null. –

0

Ce qui suit ne propage pas null, mais accepte null comme un paramètre et renvoie une chaîne vide dans ce cas.

using Microsoft.VisualBasic; // you need to add a reference to Microsoft.VisualBasic.dll 

    ... 
    string endString = Strings.Trim(startString); 
    ... 

canard & course ...

0

Créer une méthode telle que:

string MyTrim(string a) { 
    if (a != null) { 
     a = a.Trim(); 
    } 
    return a; 
} 
0

Comme en note côté, si vous utilisez .NET 4, il y a une nouvelle pratique méthode String.IsNullOrWhiteSpace que vous pouvez utiliser.

+0

Méthode intéressante, mais semble orthogonal au problème de l'OP. – Brian

+0

Ouais, désolé, j'ai mal lu la question ... –

1

Désolé pour la nécromancie, mais j'avais ce même problème et j'ai résolu cela en utilisant une opération lambda. Ce n'est pas le plus joli, mais il garde mon code succinct.

Il est dommage C# ne supporte pas les importations statiques ou les importations de fonction individuelles, mais de toute façon:

Définir cette fonction quelque part:

private static TResult N<TParent,TResult>(TParent parent, Func<TParent,TResult> operation) { 
    if(parent == null) return default(TResult); 
    return operation(parent); 
} 

ensuite l'utiliser dans votre exemple:

String endString = N(startString, s => s.Trim()); 

La fonction N renvoie null si le premier argument est null, sinon il évaluera la fonction lambda spécifiée. avec la valeur comme argument.

Vous pouvez l'imbriquer, bien sûr, comme ça. Par exemple, pour déréférencer en toute sécurité une longue chaîne, par ex.

String someValue = someObject.SomeProperty.SomeOtherProperty.SomeMethod().SomeFinalProperty; 

si l'une de ces propriétés ou méthodes renvoie NULL alors vous devez insérer des chèques nuls partout, ou vous pouvez le faire:

String someValue = N(N(N(N(someObject, o => o.SomeProperty), o => o.SomeOtherProperty), o => o.SomeMethod()), o => o.SomeFinalProperty); 

Comme je l'ai dit, ce n'est pas la plus jolie :)

Vous pouvez simplifier cela en faisant N une méthode d'extension de System.Object, comme ceci:

String someValue = someObject.N(o => o.SomeProperty).N(o => o.SomeOtherProperty).N(o => o.SomeMethod()).N(o => o.SomeFinalProperty); 

... qui je pense est beaucoup plus ordonné.

+0

Un générique contraint par classe semblerait meilleur que 'System.Object', et je pense qu'il serait bon d'avoir quelques variations qui acceptent différents nombres de paramètres" supplémentaires ". Il peut y avoir une énorme différence de performance entre un lambda qui doit capturer quoi que ce soit (y compris 'this') et un qui ne le fait pas, donc permettre aux paramètres d'être passés explicitement plutôt que capturés peut être une grande victoire. – supercat