I have a very simple C# question: aren't the following statements equal when dealing with an empty string?
s ?? "default";
or
(!string.IsNullOrEmpty(s)) ? s : "default";
I think: since string.Empty!=null, the coalescence operator may set the result of the first statement to an empty value when what I really want is the second. Since string is someway special (== and != are overloaded to value-compare) I just wanted to ask to C# experts to make sure.
Thank you.
Yes, you're right - they're not the same, and in the way that you specified.
If you're not happy with the first form, you could write an extension of:
public static string DefaultIfNullOrEmpty(this string x, string defaultValue)
{
return string.IsNullOrEmpty(x) ? defaultValue : x;
}
then you can just write:
s.DefaultIfNullOrEmpty("default")
in your main code.
Related
I'm taking a value from a textbox and converting it to decimal. But, the textbox value could be empty. So, how could I handle empty strings from the textbox?
Unfortunately I have around 50 textboxes to deal with, so answers like 'check for null with IF condition' won't help me. My code will look ugly if I use all those IF conditions.
I have this
Convert.ToDecimal(txtSample.Text)
To handle nulls, I did this
Convert.ToDecimal(txtSample.Text = string.IsNullOrEmpty(txtSample.Text) ? "0" : txtSample.Text)
But, the above code is displaying '0' in the textbox. User does not want to see '0'. Another solution is to take text box value into a variable and convert the variable like below.
string variable = txtSample.Text;
Convert.ToDecimal(variable = string.IsNullOrEmpty(variable) ? "0" : variable)
But again, I do not want to define around 50 variables. I am looking for some piece of code that handles null values during conversion without adding the extra line of code.
But, the above code is displaying '0' in the textbox. User does not want to see '0'.
This is because your statement is assigning the new value to txtSample.Text (when you do txtSample.Text = ...). Just remove the assignment:
Convert.ToDecimal(string.IsNullOrEmpty(txtSample.Text) ? "0" : txtSample.Text)
To make things easier if you have many text fields to handle, you can define an extension method :
public static string ZeroIfEmpty(this string s)
{
return string.IsNullOrEmpty(s) ? "0" : s;
}
And use it like this:
Convert.ToDecimal(txtSample.Text.ZeroIfEmpty())
You could make a function to keep from copying the code all over the place.
decimal GetTextboxValue(string textboxText)
{
return Convert.ToDecimal(string.IsNullOrEmpty(textboxText) ? "0" : textboxText);
}
and then use it like this:
GetTextboxValue(txtSample.Text);
You can create an extension method for the string as below
public static decimal ToDecimal(this string strValue)
{
decimal d;
if (decimal.TryParse(strValue, out d))
return d;
return 0;
}
Then you can just txtSample.Text.ToDecimal() in every place.
I was reading this blog post by Eric Lippert http://ericlippert.com/2013/06/17/string-concatenation-behind-the-scenes-part-one/#more-1228 and became aware that the empty string is not an identity of concatenation in C#. I haven't run into a situation that made me aware this was the case and always just assumed it was an identity. I assume there is some good reason why
string NullString = null;
NullString = NullString + String.Empty; // results in and empty string, not null
results in an empty string rather than null, what is that reason? Why is there no identity of string concatenation? Was it made that way for convenience or practicality?
The documentation for String.Concat explains this behavior:
An Empty string is used in place of any null argument.
Basically, the String.Concat method was designed to exhibit this behavior.
Was it made that way for convenience or practicality?
While only the framework design team could directly answer this, this behavior does has some practical benefits. This behavior allows you to concatenate strings with null and not create null results, which reduces the number of explicit null checks required in most code. Without this behavior, someString + "abc" would require null checking, wheras with it, a non-null value is guaranteed.
I must admit that i don't understand "the identity of string concatenation". However, the reason why null + string.Empty is not null but string.Empty is:
because it was implemented in this way.
Have a look:
public static string Concat(string str0, string str1)
{
if (string.IsNullOrEmpty(str0))
{
if (string.IsNullOrEmpty(str1))
{
return string.Empty;
}
return str1;
}
else
{
if (string.IsNullOrEmpty(str1))
{
return str0;
}
int length = str0.Length;
string text = string.FastAllocateString(length + str1.Length);
string.FillStringChecked(text, 0, str0);
string.FillStringChecked(text, length, str1);
return text;
}
}
This is also documented:
The method concatenates str0 and str1; it does not add any delimiters.
An Empty string is used in place of any null argument.
If you ask for the why. I assume because it's safer this way. If you want to concat two strings and one of both is null, why should null be favored instead of string.Empty?
Because it uses a contract, the purpose of which is described at Code Contracts.
From String.Concat:
Contract.Ensures(Contract.Result<string>() != null);
Note that NullString + NullString also returns an empty string.
I recently bumped into an exception in my code because I was trimming a null string.
I replaced it with the following:
SomeValue = (SomeString ?? "").Trim();
Can this code ever fail?
Thanks.
Note: I know I can add a try/catch; I'm just looking to make this line fail-proof without using a try/catch.
This will not fail (ie. throw a NullReferenceException), assuming SomeString is indeed a string.
You could achieve the same in many ways:
SomeValue = (SomeString == null)?string.Empty:SomeString.Trim();
It's not the way I would have done it, but no, this shouldn't ever fail now.
I'd probably write an extension method that calls trim after checking for null. Something like this:
public static string NullTrim(this String str) {
if(str == null) {
return string.Empty;
}
return str.Trim();
}
This allows all of the following to compile and execute without error:
"".NullTrim();
" test ".NullTrim();
((string)null).NullTrim();
Well if it was failing because of NullReferenceException, then now it will definitely not fail because of that. As for the rest, I cannot say without context.
Is there an operator or built in function to simplyfy this:
myVal = object1.object2.something(a,b).dataColumn.toString()==""?object1.object2.something(a,b).dataColumn.toString():"-";
I know i can do something like:
string str = object1.object2.something(a,b).dataColumn.toString();
myVal =str==""?"-":str;
but I have many objects and I want to avoid it:
string str1 = object1.object2.something(a,b).dataColumn1.toString();
myVal1==""?str1:"-"
string str2 = object1.object2.something(a,b).dataColumn2.toString();
myVal2==""?str2:"-"
:
string strN = object1.object2.something(a,b).dataColumnN.toString();
myValN==""?strN:"-"
I can also create a function:
private string CheckNull(object dataColumn){
return dataColumn == System.DBNull?"-":dataColumn.toString();
}
myVal1 = CheckNull(object1.object2.something1(a,b).dataColumn.toString())
myVal2 = CheckNull(object1.object2.something2(a,b).dataColumn.toString())
myVal3 = CheckNull(object1.object2.something3(a,b).dataColumn.toString())
The easiest way is to use the ?? operator but the problem is that 'dataColumn' is not compatible with ?? because sometimes returns a system.DBNull instead of a null. Look at the immediate window output:
System.DBNull??"-"
'System.DBNull' is a 'type', which is not valid in the given context
null??"-"
"-"
I wonder if there is some (string) function or operator that can return "-" if dataColumn.toString()=="" without an if..then (because I would have to make many if..then for all of them. Otherwise I rather use the function approach shown above.
string str = object1.object2.something(a,b).dataColumn.toString().if("","-");
How about:
public static class StringHelper {
public static string ValueOrDash(this string value) {
return string.IsNullOrEmpty(value) ? "-" : value;
}
}
Then you can just do:
myVal = object1.object2.something(a,b).DataColumn.ToString().ValueOrDash();
Or better yet:
public static class StringHelper {
public static string ValueOrWhatever(this string value, string defaultValue) {
return string.IsNullOrEmpty(value) ? defaultValue : value;
}
}
myVal = object1.object2.something(a,b).DataColumn.ToString().ValueOrWhatever("-");
If the underlying object is always either a string or DbNull, you could use the as cast operator:
private string CheckNull(object dataColumn){
return dataColumn == (dataColumn as string)??"-":dataColumn;
}
This will also return "-" if the value is an integer for example or some other type.
It's not clear from your code, but if these values are coming from DataRows you could use the new (.NET 3.5) DataRowExtensions.Field function, which will return null instead of DbNull.
You could write an extension method to call on the dataColumn. It wouldn't functionally be much different than your CheckNull method, though.
Or in your first example with str1, str2, strN and such, is there a reason you can't reuse str1 for each? I see you have a method call in your long line of code, you wouldn't want to waste the time running that more often than you need to (especially if it's going to result in the same output every time).
What is needed to make String.IsNullOrEmpty() count whitespace strings as empty?
Eg. I want the following to return true instead of the usual false:
String.IsNullOrEmpty(" ");
Is there a better approach than:
String.IsNullOrEmpty(" ".Trim());
(Note that the original question asked what the return would be normally hence the unsympathetic comments, this has been replaced with a more sensible question).
.NET 4.0 will introduce the method String.IsNullOrWhiteSpace. Until then you'll need to use Trim if you want to deal with white space strings the same way you deal with empty strings.
For code not using .NET 4.0, a helper method to check for null or empty or whitespace strings can be implemented like this:
public static bool IsNullOrWhiteSpace(string value)
{
if (String.IsNullOrEmpty(value))
{
return true;
}
return String.IsNullOrEmpty(value.Trim());
}
The String.IsNullOrEmpty will not perform any trimming and will just check if the string is a null reference or an empty string.
String.IsNullOrEmpty(" ")
...Returns False
String foo = null;
String.IsNullOrEmpty( foo.Trim())
...Throws an exception as foo is Null.
String.IsNullOrEmpty( foo ) || foo.Trim() == String.Empty
...Returns true
Of course, you could implement it as an extension function:
static class StringExtensions
{
public static bool IsNullOrWhiteSpace(this string value)
{
return (String.IsNullOrEmpty(value) || String.IsNullOrEmpty(value.Trim()));
}
}