How do I return the first string variable that isn't null or empty
Asked Answered
J

8

33

If I have 5 String variables and between 0 and 5 of them are null or empty is there an easy/short way of returning the first one that is not null or empty? I am using .NET 3.5

Jaramillo answered 29/3, 2010 at 15:45 Comment(1)
Can you update your question to indicate what version of .NET you are using?Trunks
A
42
var myString = new string[]{first, second, third, fouth, fifth}
      .FirstOrDefault(s => !string.IsNullOrEmpty(s)) ?? "";

//if myString == "", then none of the strings contained a value  

edit: removed Where(), placed predicate in FirstOrDefault(), thanks Yuriy

Aftereffect answered 29/3, 2010 at 15:48 Comment(4)
You don't need the Where, use msdn.microsoft.com/en-us/library/bb549039.aspxGree
.FirstOrDefault(x=> !string.IsNullOrEmpty(x)) with an optional ?? string.Empty if you don't want nulls.Extravagate
What if first, second, third, .. were methods and I would want them to execute only until the first of them returned a not empty result. Then the other solution was better.Hellhound
they were only string variables which may have string values or they might be nullUrceolate
O
22

Define an extension method:

static string Or(this string value, string alternative) {
    return string.IsNullOrEmpty(value) ? alternative : value;
}

Now you can say the following:

string result = str1.Or(str2).Or(str3).Or(str4) …
Olden answered 29/3, 2010 at 15:48 Comment(10)
Eh. S'kay, but not lazy-evaluated.Extravagate
If the first value is not null or empty, this will still check all the rest of the values, except for the last one. Four function calls where one would suffice.Stroke
@Will - Neither is FirstOrDefault @Jeffrey - Four function calls vs four delegate invokes, I don't see any particular advantage.Maisonette
@Robert Davis: Will is actually right, he just used odd wording; this version does not use short-circuit evaluation, whereas the FirstOrDefault method will in fact stop after the first element is found. If you're only comparing 5 elements, though, I wouldn't worry about it.Landslide
BTW, I use an extension method like this (uses NullOrWhiteSpace, lol 4.0) for display purposes, not for returning the first non-empty string in a collection. I use it like: string.Format("Displaying item {0}", item.Name.Or("(no name given)"));Extravagate
@Will - LOL. Yay Terminology!Maisonette
@Jeffrey, @Will: that’s true and I almost considered not posting it. But truth be told, it doesn’t matter and I argue that this code is the most concise, most readable alternative. Would I use it myself? Not sure – but primarily because I oppose to generating lots of spurious, non-general extension methods, and not because it might be slow. Also consider that it might actually be more efficient than creating a list/array and iterating over it (using an iterator, which, once again, hast to be created). So, I remain unconvinced that performance is a reason against using this method.Olden
@Kon who said performance? I was just saying it was kinda lame (heh). And I think everybody here has claimed their answer is the most readable. Somebody's gotta be wrong!Extravagate
@Will About performance, that was more for Jeffrey’s benefit than yours. As for the claim of readability, who except kervin has made it? Anyway, I leave that up to the inclined reader to decide. I just stated my own opinion as the reason for posting the code in the first place.Olden
@Konrad "No expression trees, no LINQ abuse, no obscure language features [...] a first year CS student can figure out what you're doing." "I find including the Where() makes it more readable" There's two plus the voices I hear in my head makes everybody.Extravagate
S
13
    private static string FirstNonEmptyString(params string[] values)
    {
        return values.FirstOrDefault(x => !string.IsNullOrEmpty(x));
    }

Called like this:

        Console.WriteLine(FirstNonEmptyString(one, two, three, four, five) );
Stroke answered 29/3, 2010 at 15:47 Comment(1)
I'd suggest a tweak to the name to FirstOrDefaultNonEmptyString (as if there are no non empty strings you'll get a null right?)Asyllabic
V
9

If you have a fixed number of variables I would suggest to use the null coalescing operator to check for nulls. This is by far the easiest option.

var result = s1 ?? s2 ?? s3 ?? s4 ?? s5 ?? "";

There is in my opinion no need to do a separate function for that anymore given there is a language construct for it already.

Edit: Empty strings are considered non-null and thus if one of them is empty it will return it.

so if you want to use this together:

public static string EmtpyToNull(string value)
{
  return string.IsNullOrEmpty(value) ? null : value;
}

var result = EmptyToNull(s1) 
  ?? EmptyToNull(s2) 
  ?? EmptyToNull(s3) 
  ?? EmptyToNull(s4) 
  ?? EmptyToNull(s5) 
  ?? "";
Victory answered 1/11, 2019 at 11:55 Comment(3)
This needs more upvotes! There is a language construct for doing precisely this task, and it doesn't just work with strings.Aphasic
You might take a note that ?? operator works only against null values, not an empty strings, as asked by the op. But it is still useful to mention an existence of such operator.Tsana
@Tsana good call-out. I edited the answer.Victory
B
1

If your strings are in an IEnumerable you can use First or FirstOrDefault:

strings.First(s => !string.IsNullOrEmpty(s))
Brachy answered 29/3, 2010 at 15:48 Comment(3)
1) this answer was already given 2) First throws an IOE if all strings are null or emptyExtravagate
@Will, 1) I think I was the first to suggest First/FirstOrDefault as an obvious alternative to Where. 2) The questioner doesn't specify the behavior he wants in the case that all strings are null/empty. That's why I suggested both.Brachy
hmmmm, was going on recollection about FOD. My bad. I don't believe he said anything in his question about throwing if all strings are null. You also didn't state that teensy little fact. First throwing is something people often don't realize and it ends up biting them in the ass. Thought it might be important for people reading to see that.Extravagate
B
1

If you're using .NET 3.5 this is very easy with Linq.

string[] strings = new[] {"", "a", "b", ""};

string firstNotNullOrEmpty = 
    strings.Where(s => !String.IsNullOrEmpty(s)).FirstOrDefault();
Basipetal answered 29/3, 2010 at 15:49 Comment(5)
First has an override which makes the Where pointless. Also, if all strings are null you'd throw an InvalidOperationException here. Which would suck ass.Extravagate
I find including the Where() makes it more readable. Why would it throw InvalidOperationException?Basipetal
open up LINQPad and try this: (new string[] { (string)null }).First(x=>!string.IsNullOrEmpty(x)) You'll see it throws an IOE, as First() is designed to do if there are no matching results. FirstOrDefault() never throws if no matching results are found; it just returns default(T).Extravagate
Right! You must have missed my update where I changed First() to FirstOrDefault() =).Basipetal
I changed the spacing so that it appears on two lines and is more readable.Basipetal
S
1
var found = new[]{first, second, third, fourth, fifth}.FirstOrDefault(x =>!String.IsNullOrEmpty(x));
Satiny answered 29/3, 2010 at 15:55 Comment(0)
F
-1

Yes.

string selected = null;
foreach(string currStr in strArray)
    if(String.IsNullOrEmpty(currStr)==false)
    {
        selected = currStr;
        break;
    }

No expression trees, no LINQ abuse, no obscure language features. Same runtime performance and a first year CS student can figure out what you're doing.

Forging answered 29/3, 2010 at 16:35 Comment(4)
I feel bad for first year CS students who are kept safe from language features that make coding a joy.Extravagate
@Will: LINQ abuse is a serious issue affecting our community, lets all be part of the solution not the problem.Forging
BTW I love LINQ, I just converted a XPath based library to LINQ to XML last week, and EF is my ORM of choice.Forging
How are the other codes “LINQ abuse”? How do you define that? And finally, how are six lines, one explicit loop, and a comparison to false (ugh!) any better than a concise, self-explanatory query that fits on one line?Olden

© 2022 - 2024 — McMap. All rights reserved.