问题
Something I find myself doing more and more is checking a string for empty (as in ""
or null) and a conditional operator.
A current example:
s.SiteNumber.IsNullOrEmpty() ? "No Number" : s.SiteNumber;
This is just an extension method, it's equivalent to:
string.IsNullOrEmpty(s.SiteNumber) ? "No Number" : s.SiteNumber;
Since it's empty and not null, ??
won't do the trick. A string.IsNullOrEmpty()
version of ??
would be the perfect solution. I'm thinking there has to be a cleaner way of doing this (I hope!), but I've been at a loss to find it.
Does anyone know of a better way to do this, even if it's only in .Net 4.0?
回答1:
There isn't a built-in way to do this. You could make your extension method return a string or null, however, which would allow the coalescing operator to work. This would be odd, however, and I personally prefer your current approach.
Since you're already using an extension method, why not just make one that returns the value or a default:
string result = s.SiteNumber.ConvertNullOrEmptyTo("No Number");
回答2:
C# already lets us substitute values for null
with ??
. So all we need is an extension that converts an empty string to null
, and then we use it like this:
s.SiteNumber.NullIfEmpty() ?? "No Number";
回答3:
I know this is an old question - but I was looking for an answer and none of the above fit my need as well as what I ended up using:
private static string Coalesce(params string[] strings)
{
return strings.FirstOrDefault(s => !string.IsNullOrEmpty(s));
}
Usage:
string result = Coalesce(s.SiteNumber, s.AltSiteNumber, "No Number");
EDIT: An even more compact way of writing this function would be:
static string Coalesce(params string[] strings) => strings.FirstOrDefault(s => !string.IsNullOrEmpty(s));
回答4:
I have a couple of utility extensions that I like to use:
public static string OrDefault(this string str, string @default = default(string))
{
return string.IsNullOrEmpty(str) ? @default : str;
}
public static object OrDefault(this string str, object @default)
{
return string.IsNullOrEmpty(str) ? @default : str;
}
Edit: Inspired by sfsr's answer, I'll be adding this variant to my toolbox from now on:
public static string Coalesce(this string str, params string[] strings)
{
return (new[] {str})
.Concat(strings)
.FirstOrDefault(s => !string.IsNullOrEmpty(s));
}
回答5:
A slightly faster extension method than proposed earlier perhaps:
public static string Fallback(this string @this, string @default = "")
{
return (@this == null || @this.Trim().Length == 0) ? @default : @this;
}
回答6:
One of the advantages of the null-coalescing operator is that it short-circuits. When the first part isn't null, the second part isn't evaluated. This can be useful when the fallback requires an expensive operation.
I ended up with:
public static string Coalesce(this string s, Func<string> func)
{
return String.IsNullOrEmpty(s) ? func() : s;
}
Usage:
string navigationTitle = model?.NavigationTitle.
Coalesce(() => RemoteTitleLookup(model?.ID)). // Expensive!
Coalesce(() => model?.DisplayName);
回答7:
I simply use a NullIfEmpty extension method which will always return null if the string is empty allowing ?? (Null Coalescing Operator) to be used as normal.
public static string NullIfEmpty(this string s)
{
return s.IsNullOrEmpty() ? null : s;
}
This then allows ?? to be used as normal and makes chaining easy to read.
string string1 = string2.NullIfEmpty() ?? string3.NullIfEmpty() ?? string4;
回答8:
how about a string extension method ValueOrDefault()
public static string ValueOrDefault(this string s, string sDefault)
{
if (string.IsNullOrEmpty(s))
return sDefault;
return s;
}
or return null if string is Empty:
public static string Value(this string s)
{
if (string.IsNullOrEmpty(s))
return null;
return s;
}
Didn't try these solutions though.
回答9:
I'm using a string Coalesce extension method of my own. Since those here are using LINQ, and absolutelly wasting resources for time intensive operations (I'm using it in tight loops), I'll share mine:
public static class StringCoalesceExtension
{
public static string Coalesce(this string s1, string s2)
{
return string.IsNullOrWhiteSpace(s1) ? s2 : s1;
}
}
I think it is quite simple, and you don't even need to bother with null string values. Use it like this:
string s1 = null;
string s2 = "";
string s3 = "loudenvier";
string s = s1.Coalesce(s2.Coalesce(s3));
Assert.AreEqual("loudenvier", s);
I use it a lot. One of those "utility" functions you can't live without after first using it :-)
回答10:
I like the brevity of the following extension method QQQ
for this, though of course an operator like? would be better. But we can 1 up this by allowing not just two but three string option values to be compared, which one encounters the need to handle every now and then (see second function below).
#region QQ
[DebuggerStepThrough]
public static string QQQ(this string str, string value2)
{
return (str != null && str.Length > 0)
? str
: value2;
}
[DebuggerStepThrough]
public static string QQQ(this string str, string value2, string value3)
{
return (str != null && str.Length > 0)
? str
: (value2 != null && value2.Length > 0)
? value2
: value3;
}
// Following is only two QQ, just checks null, but allows more than 1 string unlike ?? can do:
[DebuggerStepThrough]
public static string QQ(this string str, string value2, string value3)
{
return (str != null)
? str
: (value2 != null)
? value2
: value3;
}
#endregion
来源:https://stackoverflow.com/questions/2420125/coalesce-for-empty-string