web-dev-qa-db-fra.com

Comment faire ToString pour un objet éventuellement nul?

Existe-t-il un moyen simple de procéder comme suit:

String s = myObj == null ? "" : myObj.ToString();

Je sais que je peux faire ce qui suit, mais je le considère vraiment comme un hack:

String s = "" + myObj;

Ce serait génial si Convert.ToString () avait une surcharge adéquate pour cela.

76
codymanix

C # 6.0 Modifier:

Avec C # 6.0, nous pouvons maintenant avoir une version succincte et sans casting de la méthode orignal:

string s = myObj?.ToString() ?? "";

Ou même:

string s = $"{myObj}";

Réponse originale:

String s = (myObj ?? String.Empty).ToString();

ou 

String s = (myObjc ?? "").ToString()

être encore plus concis.

Malheureusement, comme cela a été souligné, vous aurez souvent besoin d'un casting de chaque côté pour que cela fonctionne avec des types non String ou Object:

String s = (myObjc ?? (Object)"").ToString()
String s = ((Object)myObjc ?? "").ToString()

Par conséquent, même s’il semble élégant, le casting est presque toujours nécessaire et n’est pas si succinct en pratique.

Comme suggéré ailleurs, je recommande peut-être d'utiliser une méthode d'extension pour rendre ce nettoyeur:

public static string ToStringNullSafe(this object value)
{
    return (value ?? string.Empty).ToString();
}
140
Andrew Hanlon
string.Format("{0}", myObj);

string.Format formatera null en tant que chaîne vide et appellera ToString () sur des objets non nuls. Si je comprends bien, c’est ce que vous cherchiez.

39
Holstebroe

Ce serait génial si Convert.ToString () avait une surcharge adéquate pour cela.

Il y a eu un Convert.ToString(Object value) depuis .Net 2.0 (environ 5 ans avant que ce Q ne soit posé), qui semble faire exactement ce que vous voulez:

http://msdn.Microsoft.com/en-us/library/astxcyeh(v=vs.80).aspx

Est-ce que je manque/interprète mal quelque chose de vraiment évident ici? 

12
Rob Gilliam

Avec une méthode d'extension, vous pouvez accomplir ceci:

public static class Extension
{
    public static string ToStringOrEmpty(this Object value)
    {
        return value == null ? "" : value.ToString();
    }
}

Ce qui suit n’écrirait rien à l’écran et ne lève pas une exception:

        string value = null;

        Console.WriteLine(value.ToStringOrEmpty());
12
Pieter van Ginkel

Je ne suis pas d'accord avec ça:

String s = myObj == null ? "" : myObj.ToString();

est un hack en aucune façon. Je pense que c'est un bon exemple de code clair. Ce que vous voulez réaliser et ce que vous attendez de null est absolument évident.

METTRE À JOUR:  

Je vois maintenant que vous ne disiez pas que c'était un bidouillage. Mais il est implicite dans la question que vous pensez que cette façon n'est pas la voie à suivre. Dans mon esprit, c'est définitivement la solution la plus claire.

7
steinar
string s = String.Concat(myObj);

serait le moyen le plus court je suppose et aussi avoir des frais généraux de performance négligeables. N'oubliez pas que l'intention du lecteur de code ne serait pas tout à fait claire.

4
herzmeister

en fait je n'ai pas compris ce que tu veux faire. Si je comprends bien, vous pouvez écrire ce code d’une autre manière. Demandez-vous ceci ou non? Pouvez-vous expliquer plus? 

string s = string.Empty;
    if(!string.IsNullOrEmpty(myObj))
    {
    s = myObj.ToString();
    }
2
Serkan Hekimoglu

Je pourrais me faire tabasser pour ma réponse, mais voici quand même:

J'écrirais simplement 

chaîne s = "" if (myObj! = null) { x = myObj.toString (); }

Existe-t-il un avantage en termes de performances pour l’utilisation de l’opérateur ternaire? Je ne sais pas par coeur.

Et clairement, comme mentionné ci-dessus, vous pouvez intégrer ce comportement à une méthode telle que safeString (myObj) permettant la réutilisation.

2
jaydel

Le commentaire de Holstebroe serait votre meilleure réponse:

string s = string.Format("{0}", myObj);

Si myObj est null, Format place une valeur de chaîne vide à cet emplacement.

Il répond également à vos besoins en une ligne et est facile à lire.

1
jp2code

Certains tests de performance (rapides) résument les différentes options, sans que cela soit vraiment important #microoptimization (en utilisant une extension linqpad )

Les options

void Main()
{
    object objValue = null;
    test(objValue);
    string strValue = null;
    test(strValue);
}

// Define other methods and classes here
void test(string value) {
    new Perf<string> {
        { "coallesce", n => (value ?? string.Empty).ToString() },
        { "nullcheck", n => value == null ? string.Empty : value.ToString() },
        { "str.Format", n => string.Format("{0}", value) },
        { "str.Concat", n => string.Concat(value) },
        { "string +", n => "" + value },
        { "Convert", n => Convert.ToString(value) },
    }.Vs();
}

void test(object value) {
    new Perf<string> {
        { "coallesce", n => (value ?? string.Empty).ToString() },
        { "nullcheck", n => value == null ? string.Empty : value.ToString() },
        { "str.Format", n => string.Format("{0}", value) },
        { "str.Concat", n => string.Concat(value) },
        { "string +", n => "" + value },
        { "Convert", n => Convert.ToString(value) },
    }.Vs();
}

Il est probablement important de souligner que Convert.ToString(...) conservera une chaîne nulle.

Résultats

Objet

  • nullcheck 1,00x1212 ticks écoulés (0,1221 ms) [en répétition 10K, 1,221E-05 ms par] 
  • coallesce 1,14x 1387 ticks écoulés (0,1387 ms) [en répétition 10K, 1,387E-05 ms par] 
  • chaîne + 1,16 x 1415 ticks écoulés (0,1415 ms) [en répétitions 10K, 1,415E-05 ms par] 
  • str.Concat 1,16 x 1420 ticks écoulés (0,142 ms) [en répétition 10K, 1,42E-05 ms par] 
  • Convertir 1,58x 1931 ticks écoulés (0,1931 ms) [en répétitions 10K, 1,931E-05 ms par] 
  • str.Format 5,45x 6655 ticks écoulés (0,6655 ms) [en répétitions 10K, 6,655E-05 ms par]

Chaîne

  • nullcheck 1,00x 1190 ticks écoulés (0,119 ms) [en répétitions 10K, 1,19E-05 ms par] 
  • Conversion de 1,01 x 1 200 ticks écoulés (0,12 ms) [en répétitions 10K, 1,2E-05 ms par] 
  • chaîne + 1.04x 1239 ticks écoulés (0,1239 ms) [en répétitions 10K, 1,239E-05 ms par] 
  • coallesce 1,20x 1423 ticks écoulés (0,1423 ms) [en répétition 10K, 1,423E-05 ms par] 
  • str.Concat 4,57x 5444 ticks écoulés (0,5444 ms) [en répétition 10K, 5,444E-05 ms par] 
  • str.Format 5,67x 6750 ticks écoulés (0,675 ms) [en répétitions 10K, 6,75E-05 ms par] 
1
drzaus

J'ai eu le même problème et je l'ai résolu en convertissant simplement l'objet en chaîne. Cela fonctionne aussi pour les objets nuls, car les chaînes peuvent être nuls. À moins que vous ne vouliez absolument pas avoir une chaîne nulle, cela devrait fonctionner correctement:

string myStr = (string)myObj; // string in a object disguise or a null
1
jahu

Même s'il s'agit d'une vieille question et que le PO a demandé C #, j'aimerais partager une solution VB.Net pour ceux qui travaillent avec VB.Net plutôt que C #:

Dim myObj As Object = Nothing
Dim s As String = If(myObj, "").ToString()

myObj = 42
s = If(myObj, "").ToString()

Malheureusement, VB.Net n'autorise pas l'opérateur? Après une variable, donc myObj? .ToString n'est pas valide (du moins pas dans .Net 4.5, que j'ai utilisé pour tester la solution). Au lieu de cela, j'utilise If pour renvoyer une chaîne vide au cas où myObj ne contient rien. Ainsi, le premier Tostring-Call renvoie une chaîne vide, tandis que le second (où myObj n'est pas Nothing) renvoie "42".

0
Sascha