Why isn't the empty string an identity of concatenation? - c#

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.

Related

is string variable and string variable with string.empty same?

I have many scenarios in my application where I am declaring strings as string.empty and later dynamically adding values to it. In C#, Is
string status
and
string status = String.Empty;
same?
Those lines of code are not equivalent.
If you've declared string status outside of a method, it initializes to its default value of null.
If you've declared string status inside a method, it isn't initialized, and you can't use it until you explicitly give it a value.
Whether or not you need string status = String.Empty; depends on your situation, but it seems like a decent way of avoiding a NullReferenceException if you find your code sometimes throws.
No. It's not the same. String datataype allows null. And remember that it is encouraged that you always initialize all your variables/attributes/properties.
string status = String.Empty;
No, the default value of string variable is Null
string status;
when inside a method: it would stay uninitialized
when outside a method: it would create a string object with a Null value, because string is a reference type.
string status = String.Empty;
will create a string object with a value of the Empty constant which is a string of zero length

How are null values in C# string interpolation handled?

In C# 6.0, string interpolations are added.
string myString = $"Value is {someValue}";
How are null values handled in the above example? (if someValue is null)
EDIT:
Just to clarify, I have tested and am aware that it didn't fail, the question was opened to identify whether there are any cases to be aware of, where I'd have to check for nulls before using string interpolation.
That's just the same as string.Format("Value is {0}", someValue) which will check for a null reference and replace it with an empty string. It will however throw an exception if you actually pass null like this string.Format("Value is {0}", null). However in the case of $"Value is {null}" that null is set to an argument first and will not throw.
From TryRoslyn, it's decompiled as;
string arg = null;
string.Format("Value is {0}", arg);
and String.Format will use empty string for null values. In The Format method in brief section;
If the value of the argument is null, the format item is replaced with
String.Empty.
It seems that the behavior depends on which underlying formatting methods are called, and the implementation of these can change over time. If you get a null formated into the string such as "(null)", it is not sure this will stay the same over several years. In some newer version of .NET it can start throwing an exception.
So I think the most safe approach is to make some condition to avoid using the null. Write a simple ternary operation like:
int? someValue = 5;
var valueStr = (someValue is not null) ? someValue.ToString() : string.Empty;
var myString = $"Value is {valueStr}";
It is an extra line of code, but at least the behavior is controlled.

asp.net master property string, how to check in content page if string is empty

if i have a master property string for example:
public String SharedInfo
{
get { return (String)Session["SharedInfo"]; }
set { Session["SharedInfo"] = value; }
}
and a label in an content page, i check if the string is empty by doing:
if(Master.SharedInfo == null)
now my question is: why does if(Master.SharedInfo == "") not work, because the SharedInfo is a string right?
There is a handy method that "catches" both
if (String.IsNullOrEmpty(Master.SharedInfo)) {
...
}
null and "" are not equal. null means no string at all. "" is a string of length 0.
string s = null;
int i = s.Length; // <-- Throws null reference exception
But
string s = "";
int i = s.Length; // OK, i => 0
"" and String.Empty are equivalent. Some people state that you should always use String.Empty instead of "", but it makes really no difference.
UPDATE
Equal string constants are interned by the compiler, i.e. the compiler stores equal constants only once. You can make a simple test (in response to #BobTodd's comment),
string s = "";
Console.WriteLine(Object.ReferenceEquals(s, "")); // --> true
Console.WriteLine(Object.ReferenceEquals(s, String.Empty)); // --> true
For the sake of completeness (according to #JoelEtherton's comment). Starting from .NET Framework 4.0 you can test
if (String.IsNullOrWhitespace(Master.SharedInfo)) {
...
}
This will catch strings like " " or "\t" as well.
In c#, an empty string "" is not null. It's an actual string, with length equals to zero.
You can use string.IsNullOrEmpty(string stringToTest) to check both null and empty strings.
String.Empty ("") and null are quite different
It depends wholly on what has been written to Session["SharedInfo"].
If nothing has, then it will be null, otherwise its the value written, which could be an empty string or null.
To be sure use String.IsNullOrEmpty(string #string)

can this trim code ever fail?

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.

Does null-coalescence operator match empty string?

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.

Categories