tags:

views:

203

answers:

7

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
+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
+1 for extension coolness
stmax
Eh. S'kay, but not lazy-evaluated.
Will
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
@Will - Neither is FirstOrDefault@Jeffrey - Four function calls vs four delegate invokes, I don't see any particular advantage.
Robert Davis
@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
@Robert YEAH! Take that!
Will
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
@Will - LOL. Yay Terminology!
Robert Davis
@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
@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
@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
@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
+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
You don't need the Where, use http://msdn.microsoft.com/en-us/library/bb549039.aspx
Yuriy Faktorovich
`.FirstOrDefault(x=> !string.IsNullOrEmpty(x))` with an optional `?? string.Empty` if you don't want nulls.
Will
@Yuriy it's updated with the unnecessary Where removed..
dan
A: 

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

strings.First(s => !string.IsNullOrEmpty(s))
bruno conde
1) this answer was already given 2) `First` throws an IOE if all strings are null or empty
Will
@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
@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
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
`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
I find including the Where() makes it more readable. Why would it throw `InvalidOperationException`?
jrummell
@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
Right! You must have missed my update where I changed `First()` to `FirstOrDefault()` =).
jrummell
I changed the spacing so that it appears on two lines and is more readable.
jrummell
+1  A: 
var found = new[]{first, second, third, fourth, fifth}.FirstOrDefault(x =>!String.IsNullOrEmpty(x));
Matt Dearing
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
I feel bad for first year CS students who are kept safe from language features that make coding a joy.
Will
@Will: LINQ abuse is a serious issue affecting our community, lets all be part of the solution not the problem.
kervin
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
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
I like ice cream cake.
Will
@Will: Lol. Don't we all, Will?... Don't we all...
kervin