126

Is there a simple way of doing the following:

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

I know I can do the following, but I really consider it as a hack:

String s = "" + myObj;

It would be great if Convert.ToString() had a proper overload for this.

codymanix
  • 28,510
  • 21
  • 92
  • 151
  • 3
    I don't see anything wrong with the first one. If you consider the second to be a hack, you're best bet is to just write a utility function which performs the null check. – Nick Larsen Oct 21 '10 at 12:55
  • plz can you be more precise about your question – FosterZ Oct 21 '10 at 12:57
  • 3
    string.Format("{0}", myObj) accepts null values. – Holstebroe Oct 21 '10 at 13:04
  • 3
    With C# 6.0 we can now use null-conditional operators, like theText?.ToString() or theText?.Trim() – Santosh Aug 06 '16 at 11:36
  • 2
    Per [this answer](https://stackoverflow.com/a/21238974/1037948) `Convert.ToString()` does exactly the first thing you wrote underneath. – drzaus Dec 01 '17 at 18:05
  • For completion, I'd note that the question and answers only refer to reference types, but not to "plain" Nullable - which is a struct, and methods can be called on empty structs just fine. These 2 other questions are related: [1](https://stackoverflow.com/questions/75651559/why-c-sharp-string-isnullorwhitespacedatatimenull-tostring-do-not-throw) & [2](https://stackoverflow.com/questions/11446838/why-does-tostring-on-a-null-string-cause-a-null-error-when-tostring-works). – OfirD Jun 25 '23 at 14:38

12 Answers12

229

C# 6.0 Edit:

With C# 6.0 we can now have a succinct, cast-free version of the orignal method:

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

Or even using interpolation:

string s = $"{myObj}";

Original Answer:

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

or

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

to be even more concise.

Unfortunately, as has been pointed out you'll often need a cast on either side to make this work with non String or Object types:

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

Therefore, while it maybe appears elegant, the cast is almost always necessary and is not that succinct in practice.

As suggested elsewhere, I recommend maybe using an extension method to make this cleaner:

public static string ToStringNullSafe(this object value)
{
    return (value ?? string.Empty).ToString();
}
Andrew Hanlon
  • 7,271
  • 4
  • 33
  • 53
  • Will this compile? Doesn't the coalescing operator check types? – Nick Larsen Oct 21 '10 at 13:33
  • 1
    It works since (object??string) returns object, because coalesce uses the least common type. But I think this wont work for interfaces because it cannot decide which interface to chose (since multiple interfaces are allowed per class). – codymanix Oct 21 '10 at 13:39
  • 4
    Downvoting as that object cast is terribly ugly and involves boxing. – steinar Oct 09 '11 at 15:16
43
string.Format("{0}", myObj);

string.Format will format null as an empty string and call ToString() on non-null objects. As I understand it, this is what you were looking for.

Holstebroe
  • 4,993
  • 4
  • 29
  • 45
  • 3
    I personally don´t like this. The code may be insignificantly shorter than String s = myObj == null ? "" : myObj.ToString(), but you totally conceal the reasoning behind your method. – AGuyCalledGerald Aug 07 '14 at 11:46
  • Granted this is microoptimization, but it takes about 5x longer than just `"" + myObj`. But I've read that creates extra strings. `str.Concat(myObj)` seems to work just fine and is "even faster". – drzaus Dec 01 '17 at 17:48
25

It would be great if Convert.ToString() had a proper overload for this.

There's been a Convert.ToString(Object value) since .Net 2.0 (approx. 5 years before this Q was asked), which appears to do exactly what you want:

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

Am I missing/misinterpreting something really obvious here?

Rob Gilliam
  • 2,680
  • 4
  • 26
  • 29
16

With an extension method, you can accomplish this:

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

The following would write nothing to the screen and would not thrown an exception:

        string value = null;

        Console.WriteLine(value.ToStringOrEmpty());
Pieter van Ginkel
  • 29,160
  • 8
  • 71
  • 111
  • Do extension method calls omit the usual check for nulls...? – Matti Virkkunen Oct 21 '10 at 12:56
  • Well, here, inside the extension method I check for null. The example runs without exception. – Pieter van Ginkel Oct 21 '10 at 12:57
  • I don't think there could be anything more "hack-ish" then this. You have created a situation where it is perfectly legal to call a function on a null object... This is better implemented as a non extension utility function. – Nick Larsen Oct 21 '10 at 12:57
  • That's the beauty of extension methods. This is completely allowed, and exactly does what codymanix is requesting in the question. – Pieter van Ginkel Oct 21 '10 at 12:58
  • +1 The fact that extension methods _can_ work with null references doesn't make this _hackish_, [I think](http://codecrafter.blogspot.com/2008/07/c-extension-methods-and-null-references.html). – Jordão Oct 21 '10 at 12:59
  • This extension doesn't add anything that string.Format doesn't already do. – Holstebroe Oct 21 '10 at 13:00
  • 2
    It adds that you don't have to type "{0}" and that you can choose a method name that describes what you're doing. This is especially useful when you're doing this many times. You could even name the method ToStringOrEmptyWhenNull. – Pieter van Ginkel Oct 21 '10 at 13:03
  • 2
    If the OP thinks that `string s = "" + myObj;` is hackish, calling a function on a null object should fall into that same boat. I would downvote this, but it does solve the problem at hand, I just disagree with the usage. Null objects should throw `NullReferenceException`, even in extension methods. – Nick Larsen Oct 21 '10 at 13:03
  • Also, this should take object as its parameter, not string. – Nick Larsen Oct 21 '10 at 13:05
  • Ah, yes, but they don't. Maybe we should Anders Hejlsberg why it doesn't throw? – Pieter van Ginkel Oct 21 '10 at 13:06
  • 2
    @NickLarsen: I agree with you on most occasions, but sometimes you just want the convenience of a simple method call. The method name should give you a hint that null references are OK, like with the proposal for `ToStringOrEmptyWhenNull`. – Jordão Oct 21 '10 at 13:06
  • Absolutely right about the object as parameter. Updated the answer. – Pieter van Ginkel Oct 21 '10 at 13:08
  • I was going to suggest something similar. – jimplode Oct 21 '10 at 13:09
  • @codymanix - Extension methods do not throw on null. Run the fragment in Visual Studio and you'll see that it does what you want. – Pieter van Ginkel Oct 21 '10 at 13:57
  • 3
    Extension methods do not throw when the "first" parameter (the `this` parameter) because they are just syntactic sugar. That is `x.SomeExtensionMethod()` is syntactic sugar for `SomeStaticClass.SomeExtensionMethod(x);` Thus, when `x` is `null` we are not attempting to invoke a method on a `null` object but rather passing a `null` object to a static method. If and only if that method checks for a `null` parameter and throws when encountering such will an extension method "invoked" on a `null` object throw. – jason Oct 21 '10 at 14:13
8

I disagree with that this:

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

is a hack in any way. I think it's a good example of clear code. It's absolutely obvious what you want to achieve and that you're expecting null.

UPDATE:

I see now that you were not saying that this was a hack. But it's implied in the question that you think this way is not the way to go. In my mind it's definitely the clearest solution.

steinar
  • 9,383
  • 1
  • 23
  • 37
  • He didn't say that this method was hack. In fact he didn't say what was wrong with it except perhaps implying that it wasn't simple. I don't think there is anything wrong with this method. +1 because I would do it this way. – Mark Byers Oct 21 '10 at 12:59
  • I agree with OP... there's already a null coalescing operator in c# - see my post below. – Andrew Hanlon Oct 21 '10 at 13:06
  • I think the null coalescing operator is a little bit less clear in this case, however I would be just as fine with using that. – steinar Oct 21 '10 at 13:08
  • @Pieter Fair enough. But it does. The question is "Is there a simple way of doing the following:...". That exact way is simple! – steinar Oct 21 '10 at 13:15
  • I never said, that *this* method is a hack. Please reread my question. I only miss a little function in the Framework which has this functionality. – codymanix Oct 21 '10 at 13:18
  • @steinar ... this case IS the reason why null-coalesce exists. – Andrew Hanlon Oct 21 '10 at 13:19
  • @ach I know. I mean that I don't really like as much when it's used in the parameters being sent down to the function as when assigned. I.e. f(something ?? "") versus s = something ?? "". That's just my taste. – steinar Oct 21 '10 at 13:21
  • @codymanix that's why I though the extension method ToStringOrEmpty was a nice idea :). – Pieter van Ginkel Oct 21 '10 at 13:23
4
string s = String.Concat(myObj);

would be the shortest way I guess and also have neglible performance overhead. Keep in mind though it wouldn't be quite clear for the reader of the code what the intention is.

herzmeister
  • 11,101
  • 2
  • 41
  • 51
  • 2
    This is the explicit form of ""+myObj but even worse in telling what is going on here. Interesting anyway. – codymanix Oct 21 '10 at 21:35
  • @codymanix i don't think it's the same -- `Concat` actually does a null check underneath and returns `string.Empty` or `arg0.ToString()`, which seems to be slightly more performant (I mean, we're talking ms here). – drzaus Dec 01 '17 at 17:54
2

I had the same problem and solved it by simply casting the object to string. This works for null objects too because strings can be nulls. Unless you absolutely don't want to have a null string, this should work just fine:

string myStr = (string)myObj; // string in a object disguise or a null
jahu
  • 5,427
  • 3
  • 37
  • 64
2

actually I didnt understand what do you want to do. As I understand, you can write this code another way like this. Are you asking this or not? Can you explain more?

string s = string.Empty;
    if(!string.IsNullOrEmpty(myObj))
    {
    s = myObj.ToString();
    }
Serkan Hekimoglu
  • 4,234
  • 5
  • 40
  • 64
  • Sure I can write it like this but I want a simple small function call, I was wondering why there is nothing like this in the .NET BCL – codymanix Oct 21 '10 at 12:55
  • 1
    Do you really need a function while we having IsNullOrEmpty() method? – Serkan Hekimoglu Oct 21 '10 at 12:59
  • On that note, I have always wanted the coalescing operator to fail next once it hits a null reference in your fluent expression, but I completely understand why that is a terrible idea. An override that allows you to do that would be nice too. – Nick Larsen Oct 21 '10 at 12:59
  • 1
    `string s = string.IsNullOrEmpty(myObj) ? string.Empty : myObj.ToString();` – Nick Larsen Oct 21 '10 at 13:00
2

I might get beat up for my answer but here goes anyway:

I would simply write

string s = ""
if (myObj != null) {
   x = myObj.toString();
}

Is there a payoff in terms of performance for using the ternary operator? I don't know off the top of my head.

And clearly, as someone above mentioned, you can put this behavior into a method such as safeString(myObj) that allows for reuse.

Pang
  • 9,564
  • 146
  • 81
  • 122
jaydel
  • 14,389
  • 14
  • 62
  • 98
2

Some (speed) performance tests summarizing the various options, not that it really matters #microoptimization (using a linqpad extension)

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();
}

Probably important to point out that Convert.ToString(...) will retain a null string.

Results

Object

  • nullcheck 1.00x 1221 ticks elapsed (0.1221 ms) [in 10K reps, 1.221E-05 ms per]
  • coallesce 1.14x 1387 ticks elapsed (0.1387 ms) [in 10K reps, 1.387E-05 ms per]
  • string + 1.16x 1415 ticks elapsed (0.1415 ms) [in 10K reps, 1.415E-05 ms per]
  • str.Concat 1.16x 1420 ticks elapsed (0.142 ms) [in 10K reps, 1.42E-05 ms per]
  • Convert 1.58x 1931 ticks elapsed (0.1931 ms) [in 10K reps, 1.931E-05 ms per]
  • str.Format 5.45x 6655 ticks elapsed (0.6655 ms) [in 10K reps, 6.655E-05 ms per]

String

  • nullcheck 1.00x 1190 ticks elapsed (0.119 ms) [in 10K reps, 1.19E-05 ms per]
  • Convert 1.01x 1200 ticks elapsed (0.12 ms) [in 10K reps, 1.2E-05 ms per]
  • string + 1.04x 1239 ticks elapsed (0.1239 ms) [in 10K reps, 1.239E-05 ms per]
  • coallesce 1.20x 1423 ticks elapsed (0.1423 ms) [in 10K reps, 1.423E-05 ms per]
  • str.Concat 4.57x 5444 ticks elapsed (0.5444 ms) [in 10K reps, 5.444E-05 ms per]
  • str.Format 5.67x 6750 ticks elapsed (0.675 ms) [in 10K reps, 6.75E-05 ms per]
drzaus
  • 24,171
  • 16
  • 142
  • 201
1

Holstebroe's comment would be your best answer:

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

If myObj is null, Format places an Empty String value there.

It also satisfies your one line requirement and is easy to read.

0

Even though this is an old question and the OP asked for C# I would like to share a VB.Net solution for those, who work with VB.Net rather than C#:

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

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

Unfortunatly VB.Net doesn't allow the ?-operator after a variable so myObj?.ToString isn't valid (at least not in .Net 4.5, which I used for testing the solution). Instead I use the If to return an empty string in case myObj ist Nothing. So the first Tostring-Call return an an empty string, while the second (where myObj is not Nothing) returns "42".

Sascha
  • 1,210
  • 1
  • 17
  • 33