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
+3
A:
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) );
Jeffrey L Whitledge
2010-03-29 15:47:57
+6
A:
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) …
Konrad Rudolph
2010-03-29 15:48:04
+1 for extension coolness
stmax
2010-03-29 15:51:01
Eh. S'kay, but not lazy-evaluated.
Will
2010-03-29 16:02:50
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.
Jeffrey L Whitledge
2010-03-29 16:12:05
@Will - Neither is FirstOrDefault@Jeffrey - Four function calls vs four delegate invokes, I don't see any particular advantage.
Robert Davis
2010-03-29 16:18:00
@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.
Aaronaught
2010-03-29 16:23:58
@Robert YEAH! Take that!
Will
2010-03-29 16:33:48
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)"));`
Will
2010-03-29 16:40:13
@Will - LOL. Yay Terminology!
Robert Davis
2010-03-29 16:56:27
@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.
Konrad Rudolph
2010-03-29 17:51:14
@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!
Will
2010-03-29 19:43:56
@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.
Konrad Rudolph
2010-03-29 21:09:56
@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.
Will
2010-03-30 12:23:14
+10
A:
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
dan
2010-03-29 15:48:15
You don't need the Where, use http://msdn.microsoft.com/en-us/library/bb549039.aspx
Yuriy Faktorovich
2010-03-29 15:52:03
`.FirstOrDefault(x=> !string.IsNullOrEmpty(x))` with an optional `?? string.Empty` if you don't want nulls.
Will
2010-03-29 15:57:16
A:
If your strings are in an IEnumerable
you can use First
or FirstOrDefault
:
strings.First(s => !string.IsNullOrEmpty(s))
bruno conde
2010-03-29 15:48:39
1) this answer was already given 2) `First` throws an IOE if all strings are null or empty
Will
2010-03-29 16:42:17
@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.
bruno conde
2010-03-29 16:55:54
@bruno 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.
Will
2010-03-29 19:46:57
A:
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();
jrummell
2010-03-29 15:49:12
`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.
Will
2010-03-29 16:02:12
I find including the Where() makes it more readable. Why would it throw `InvalidOperationException`?
jrummell
2010-03-29 16:12:13
@jrummel 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)`.
Will
2010-03-29 16:36:18
Right! You must have missed my update where I changed `First()` to `FirstOrDefault()` =).
jrummell
2010-03-29 16:48:54
I changed the spacing so that it appears on two lines and is more readable.
jrummell
2010-03-29 16:50:47
+1
A:
var found = new[]{first, second, third, fourth, fifth}.FirstOrDefault(x =>!String.IsNullOrEmpty(x));
Matt Dearing
2010-03-29 15:55:19
A:
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.
kervin
2010-03-29 16:35:44
I feel bad for first year CS students who are kept safe from language features that make coding a joy.
Will
2010-03-29 16:41:33
@Will: LINQ abuse is a serious issue affecting our community, lets all be part of the solution not the problem.
kervin
2010-03-29 16:51:19
BTW I love LINQ, I just converted a XPath based library to LINQ to XML last week, and EF is my ORM of choice.
kervin
2010-03-29 16:53:31
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?
Konrad Rudolph
2010-03-29 17:53:54