Is string.Empty actually better than "" in C#?
Vložit
- čas přidán 12. 05. 2021
- Become a Patreon and get source code access: / nickchapsas
Check out my courses: dometrain.com
Hello everybody I'm Nick and in this video I am going to answer one of the questions I see floating around time and time again and that is, is string.Empty the same as empty string in C#. There are multiple assumptions about this and even stackoverflow answers that state completely wrong stuff so hopefully in this video I will teach you how you can answer those questions on your own.
Don't forget to comment, like and subscribe :)
Social Media:
Follow me on GitHub: bit.ly/ChapsasGitHub
Follow me on Twitter: bit.ly/ChapsasTwitter
Connect on LinkedIn: bit.ly/ChapsasLinkedIn
Keep coding merch: keepcoding.shop
#csharp #strings
That intro is quite cool. Usually youtubes get out of their way to keep you watching for as long as possible. Breath of fresh air.
I've seen quite a lot of your videos, and every one does a stupendous job at explaining things that I didn't know about C#. I've always enjoyed each video, but this video is the one that made me decide to subscribe. Thanks for not wasting the average viewer's time by giving us the answer right away, but also thanks for teaching the people who do want to stick around about all the nuances and reasons for why that answer is the answer.
When he gave the answer in the intro I straight up subscribed and stayed for more information.
Thanks for the video.
Code wise, In my opinion string.Empty is safer, I experienced that I or someone else by mistake put white space between "", So it took us long time to figure out what went wrong.
Agree, I've had the same experience several time, and with a large monitor sometimes its harder to see the space.
If for some reason there were to be an environment where empty string was not "", not sure how that could ever be but seemed like using string.Empty would be similar to using Environment.NewLine versus a literal "
".
This is very nice and interesting learning how to utilise the IL to inspect and dig into what's actually happening. Nice!
Excellent video Nick, short and to the point.
Upvoted and subscribed for giving the answer straight off and not making us wait to the end.
Great content,
I would like to see more videos like this exploring the IL, Jit and what is happing at behind
The main reason to prefer string.Empty where possible over "", is that the first shows intend. "" could be an empty string, or it could be a string you forgot to fill in.
Great point. There's also a (very small) risk of "" containing zero-width characters.
@@lightandtheheat That reasoning is so odd though, for the same reason any string literal can contain zero-width characters. Does that mean avoid ALL string literals? Don't get me wrong, I'm just trying to express the absurdity of the whole situation, because zero-width characters are the weirdest inventions ever. I personally never needed to use them. At least in an IDE, one should be able to turn on a switch that makes them visible.
saw your comment after typing mine. Have the same attitude!
100% agree with this, and this is the reason I use string.Empty - I've debugged older code where other developers simply forgot to put a value in, and not knowing the code in detail took ages to debug. So string.Empty to show intent!
@@SirWolf2018 I've seen them in a competitors software that used them to try and prevent people writing external software to interact with their software. It was a weird protective method that was easy to negate.
Brilliant demonstration. Many thanks.
I admire straightforward conclusion at the beginning on the video. Like & subscription for you mate!
I love your channel! Thanks for answering the question in the first few seconds and not force me to watch the whole. Btw i did watch it through even tho i was only interested in the result
I appreciate that you answered the question immediately. Nick for president!
Thanks for your content!
Another insightful video. Keep it up!
It was a VERY diplomatic way of saying that you think "" is the cleanest. .. in which I totally agree.
Just watched a video with a _very_ similar premise for C++, and the answer was wildly different. string::clear() is a method, so it can dodge deallocation/length checks/etc; assigning an empty string is slower. Interesting how different languages have different approaches like that
I subbed because you told me the answer in the first 1 minute - I watched the rest, I wanted to know why - but thanks for not wasting our time.
1:55 "Assumption is the mother of all f*ckups" - Thank you for answering this question. - Have you made a "string vs String" video? - I can't find it.
I haven't because I don't think that there is so much misunderstanding on that front but if you think there is I'm happy to create one.
@@nickchapsas Would love it if you did!
They are compiler aliases so there is no real difference. It's not like java boxing/unboxing
I've read somewhere that she uppercase datatypes naming was to have some Java typing syntax and attract Java programmers to C#
to add to @deidian 's answer, .NET languages ultimately compile down to the under .NET types. However, various languages have aliases for representing these types in a language consistent way. For instance System.Int32 is int in C# and Integer in VB.NET; System.Int64 is long in C#...
It's brilliant to show how you investigate this. it's "learn a man to fish..." I prefer "string. Empty" as it tells the intent clearly, but that's a different story. Thanx Nick
When it comes to string.Empty vs "", it is more about coding convention than about performance
Appreciate for quick answer.
You spit the answer right in the beginning of the video, thats pretty cool.
Left the video playing until the end instead of leaving 👍
Great work explaining it deeply.
We rather use String.Empty, just because it looks cleaner.
So great video!
Great video!
Thank you for answerig the question at the begining
string.Empty for me. It's safer as you can't accidentally add/remove characters as you could with "". It's more explicit as to the intent. You can search for references to string.Empty without having to rely on a text search.
Yes unless. U r the kind 2 write code like x = singingemptyheaded = stingingemptyhanded
@@henrychoy2764 Your message hurt me to read. I have no idea what you were trying to say either
You can really easily search for "". It's just ""... Alternatively "[a-zA-Z0-9]" if you want to cover any character-containing (ascii) string.
"" is way faster to read, smaller, looks nicer and conveys meaning just fine. Alternatively '\0', but I don't know if that's in C#...
@@casperes0912 yes you can search for "" but that would pick it up in places where you might not want to find it. A reference lookup on string.Empty will find exactly that, true references to it. Being smaller isn't necessarily a good thing, that makes it easier to miss when glancing over code.
@@casperes0912 don't worry b happy just put it 2 compiler
I came in expecting to be indoctrinated into one or the other, instead learned about interning and no longer care, and my opinion says the same as your turned out to be. Thank you!
Great as always. That settles it!
Subscribed because of your video LINQ test.
Thanks man!
I believe that what makes people have this kind of question is thinking that compilers are still only a 1:1 "translator" from what we write to IL, bytecode, Op code or what ever lenguage your programming lenguage transpiles to... Compilers are now a days way smarter than that.
P.S: Since this os my first comment here I Just would like to say thanks you for the efford tou put on this Channel, Nick! :D
If I'm not wrong on optimization phase compiler make a literal table (or maybe exe/dll .data section) and use same code literals from same address, since it's immutable, and in your code variables do not changed through entire code except init, so vars are considered as consts or literals. I think it will be different story if you use verbatim strings.
So basically, string.Empty and "" reference the same address in ram.
Correct and that is true for any other string literal that is allocated in the intern pool
@@nickchapsas I'm assuming it only creates string literals in memory for what will appear in the code. Does it intern new dynamically built strings when toString() is called, or is interning only for string literals? What about string templates?
@@user-qq6si7zv3t: No, only compile time string constants are interned automatically. And for dynamically allocated strings you can still use the Intern method. Though it is not quite recommended, especially if the number of the possible strings is unbounded.
I used to use "", and I'll tell you a story about why I switched to string.Empty.
Years ago, I was investigating a bug and found a place that was comparing a string to "0". I couldn't figure out why it was doing this, when it seemed like it should be comparing to "". I dug into the system documentation to find out if "0" had some special meaning but couldn't find anything. I checked the source history and work items hoping to find some helpful comments, but nothing. I was beginning to think it might be a mistake, but then I searched the program for "0" and found two other places doing the same comparison.
I was baffled, but deciding to look into the source history of those other comparisons. What I found was that the oldest version of the oldest comparison was comparing to "", NOT "0". At some point, someone must have fat-fingered a 0 into the middle of it and committed without realizing it. Later, someone else took that block of code and copied it into two other places.
That's the point where I decided to stop using "", because string.Emp0ty doesn't compile.
Thank you for that concise explanation. The difference between 2 string values is relevant during the early versions of .NET but glad that Microsoft fixed that.
Great video. Good succinct length, too. Easy to watch.
Nice video 👌🏼
It would be interesting to know if this behavior of using the same address was before in C#, in a previous version, thinking that this could be a Microsoft improvement at some point. 👀
I'm pretty sure the idea of string being reference type that mostly acts like value type has been there since the very beggining of the language and not much has changed in terms of memory allocation but it's just me rambling, don't quote me on that, hah.
Hey Nick, I wish to point out that not all of the C# developers are .Net developers. Some of your followers, like me, are actually Unity developers. Which constitute a fairly large sum of the C# community (1.5 million monthly accounts 2020 - google). And in Unity, C# eventually ends up as c++ or some other deviation like Mono. So its interesting if in such cases the String.empty and "" are different. Either way, your content is very productive.
that's very interested
I liked string.Empty because it looks more like a constant than a programmer/user defined string-value inside the code. But I have returned back to "" for shortness (at least when initializing strings). In Linq-Expressions I still prefer string.Empty because of the first mentioned reason - and maybe there was something between the quotation marks (like an asterics[*]) and you pressed the DEL-Button on it ("" is very different to "*";) and I find string.Empty inside a Linq-Expr. better readable/understandable (because it's a constant)
i knew the answer before I clicked, but I wanted to know how deep you will proof it and ye xD I'm impressed. Good Video
Great video on string interning! I feel sorry for anyone that assumes "" is an empty string though. They've never copy and paste from a website and gotten a non-printable character hiding in there before lol if it looks empty, check it anyway. Lots of tools for non printable highlighting.
Just use editor that doesn't suck.
so what is better nullable or empty string
I'm pretty sure they weren't always the same. String.empty was better but the have changed the compiler to simplify people's lives.
I believe that's true. I remember reading it on msdn, but it was probably pre-.net 2.0.
ocurrences of "any string here" could be considered a code smell as magic-string spaghetti, so better to define all strings in one common master definition module (and just one place to change rather than have to refactor or do a fragile global rip&replace edit), so I favour string.Empty rather than "" but good to educate the research thinking.
I've never used Rider before, but if I do the same thing in LINQPad (which can now show generated IL and ASM), my results do not seem to look quite like yours. It looks like I'm getting extra calls in mine. I wonder if this is just some overhead LINQPad is adding to the code to do all the cool things it can do. Either way, great video! Thank you for all you do... I really enjoy your videos!
Are you in Debug mode? It needs to be on release
@@nickchapsas Tried that... still has a few extra calls in my constructor in the ASM code. Oddly enough, the IL code is exactly the same as yours.
@@brianm1864 LINQPad might be using an outdated version of the jitter then
I only use string.Empty because "" is hard to see but generally speaking string.Empty is absolutely unnecessary
Two pluses for actually going to the assembly language code to find the definitive answer.
CZcams does not like Urls, but I re-try my comment:
- It is a Clean Code issue also, if you search for empty strings in C# code, it will also Json- and Xml stuff and other uninteresting stuff where "" is used as well.
- Quote: string.Empty wins in a really corner case, which can lead to some magical bug and really hard to debug:
If there is a zero width space in "".
The video could include the topic of creating strings from char arrays (as pointers). Constructor string(char* c) is very weird, but it helps creating strings without allocations (stackalloc). I always ask myself if I should include '\0' at the end.
It needs a null terminator if you don't provide a start pos and length; C# strings are not null terminated by default, so they presumably need the explicit '\0'. (Dunno if that actually helps cause I'm not actually too experienced with C# unsafe, but that's how I understand the docs)
I personally think that a developer should always use string.Empty over "" if it is possible. This is because string.Empty shows the developer's intention in an explicit manner, where as "" could be a string that the developer forgot to initialize.
Or a whitespace which the IDE cannot display, and there are a lot of these
I prefer string.Empty personally.
It does look cleaner but it takes a millisecond longer to write
I = personally 😇
"" is so overwhelmingly engrained in most language ecosystems that it really does convey the same intention. And it does so with less mental overhead and doesn't give a simple concept more attention than it deserves. I'm very against over abbreviation. I tried to switch to string.Empty and it was a small speed bump. I could get used to it, but I think that's less pragmatic in the current programming world. It's a nitpick either way I bet.
Beginner: ""
Professional: String.Empty
No one: $"{String.Empty}"
Marry me.
I use string.empty hover "" just because for me "" leaves a gap of intention, depending where you are in the code, "" could give you this impression or work in progress of the doubt of is this "" correct? With string.empty there is not doubt that it was the intention to put empty string inthere. Again, that is how it works for me and my brain.
Or can be demonstrated with object. ReferenceEquals(emptyString1, emptyString2) rather than looking through IL.
That's true but it doesn't paint the full picture. You wouldn't know about the allocation itself and you wouldn't know about the intern pool
@@nickchapsas string interning was heavily discussed in the community, books etc when .NET 1.0 came out, but granted, it is somewhat arcane knowledge now (and was almost 20 years ago!)
myString.IsNullOrEmpty() vs (myString == null || myString == "") are the same too, I suppose.
But I'm worried about a more interesting question: (someValue == null) vs (someValue is null).
They are the same too
Beware! (someValue == null) IS NOT the same as (someValue is null). It is possible to overload the == operator while it is NOT possible to overload 'is'. 'is' always checks the reference of the variable while == calls any overload. A prime example of this happening is in Unity. If you destroy any unity-object the object will get a 'fake null' reference because the GC has not yet cleaned up the object. (unityObject == null) will then already return true because of a custom overload, while (unityObject is null) will still return false.
@@mindstyler We are talking about the string type here. You cannot overload that so it is the same. I've addressed all this in my null checks video already.
@@mindstyler Thanks, I forgot about operator overloading.
In fact, if you’re going to do a null check via ==, it’s safer to swap the order, and check null == someValue. That way, if someone comes along and accidentally uses = instead of ==, you get a compile error, rather than a bug.
Lol I was pretty sure the answer was No. Thanks for telling me in 36 seconds.
I like to use string.Empty because it's clear that the empty string was in there intentionally. If "" is used, then there is the question of did the dev forget to put a value in there or not.
I always use both:
var x = string.Empty + "";
👍🏽
String.empty is best! "" Could be mistaken for a string left unintentionally empty!
That IL is quite annoying. LLVM IR looks way nicer. Not that it's really meant for readability or anything. And I'm talking from a perspective of having experience with LLVM IR and x86-64 assembly, not C#/F#/VB IL.
Who cares?? Most important is how good IL can be *effectively* translated into target platform.
I prefer the quotes since a default function requires it.
Now I'm really curious why string.Empty is static readonly instead of const.
The usual recommendation to prefer readonly over const is that const inserts the value directly into the code, while readonly inserts into the code a read from the runtime constant. This has the advantage of potentially allowing you to change the readonly runtime constant in a future version of your library assembly, without needing to recompile every assembly that references your assembly as you would if you changed something that was const.
That said... I'm not sure why that would matter for string.Empty, which would be absurd to change in a future version.
The real problem is when you need String.Empty to be a constant value, but it's just a static read-only field.
when you use "", you rely on compiler optimizations to do the job for you, and when you apply string.Empty you are beeing explicit in reusing the same string over and over again. I'm not 100 sure that exactly the same machine code will be for all platforms and all complier versions
It will be exactly the same in both cases. String interning has been a CLR feature since forever. Both "" and string.Empty will reuse the exact same string literal over and over again.
@@nickchapsas yep, string interning, now for me it 's clear why
@@nickchapsas, is strong interning an explicitly required language feature, or just a common implementation detail?
@@Vessekx It's by no means required, but the people who made the CLR are smart and they knew that an immutable reference type will cause memory issues so they added it.
I kind of hate that string are internalized even in (ref) structs. It should be way more explicit, I didn't actually know that until a few years ago.
tell about String.Empty vs string.Empty
...and "" vs @""
I'd rather ask, why do we even have String.Empty in .NET and why isn't it equal to null?
It's supposed to represent an empty string. There are many characters that aren't visible and would appear as an empty string when you did "" so to prevent that we have this common point. It wouldn't be equal to null because it is an empty string not a null string.
String.empty and null are two different things.
"" is for true ogs
In Forth : ""= dup 0= ; ( a n -- f) \ Is.Empty
: "" 0 dup ; ( -- a 0) \ string.Empty
My brain hurts
Sometimes I need to code in Java ..I prefer ""
I like using string.empty because then I know and the person reading my code knows, I 100% mean an empty string there.
Often in our pull request we just see an initialization method where a string gots initializied with this "". In fact, if the developer had used string.Empty, we would knew he want an empty string, insted we commented that because maybe he forgot to set the correct value. String.Empty is just more clear in terms of how people interpret your code i think.
string.Empty is there to be compatible cross-platform, nothing to do with performance.
string.Empty was added when .NET was windows exclusive. Nothing to do with cross platform (or performance for that matter)
The string empty vs empty literal is more about the philosophy of the code than style.
Same as with null vs empty string on databases, string.empty indicates an explicit empty string, while the literal is more like a wrong value
With null vs empty string on database tables, things are more clear: setting an entry to null means it is left empty deliberately
Empty means there is no value set,
Couple of comments: (1) there is more than one JITter (at least one for each platform). I don't know if they'll all give the same result as you saw here. They might... or might not. (2) It seems plausible that the JITter itself (or whatever it is that's responsible for string interning) might be faster to identify that both strings are equal if they are equal by reference, i.e. using string.Empty, rather than have to do a string compare to confirm it, as it would have to with "". So, it seems plausible that the JITter might take longer to perform the compilation, even if the resulting assembly is identical. Again, I don't know that for sure.
In any case the difference (if there even is any) is likely to be vanishingly small, so I don't disagree with your conclusion. But a claim that "there is no difference at all" should consider those things too.
This isn't about the Jitter but rather string interning, which has been in the CLR since .NET Framework 1.0. The JIT ASM doens't mean that this is what the jit will optimize necessarily but rather that it will ultimately run. So yeah, this has nothing to do with the JITter directly but rather the string interning feature of the CLR. The only time this wasn't true was between .NET Framework 2.0 Service Pack 1 and .NET Framework 3.0 where two string variables created with string.Empty would not have the same reference, which was a regression from the original behavior and was changed back to it's original string interning version that was in place in 1.0. You can read all about that here: docs.microsoft.com/en-us/dotnet/api/system.string.intern?view=net-5.0#version-considerations
I don't wanna watch trivial video. WHAT is better? (and hell, why?)
OMG, i need another 23 byte memory upgrade in addition to my 128GB memory, then :/
They're not the same, "" is a constant, while string.empty is not, and that distinction does make a difference.
That distinction mostly matters to the compiler (not the JIT so much)
Consider the following 2 assignments, one compiles to a constant, the other to a string.concat.
var a = "abc" + string.Empty + "def";
var b = "abc" + "" + "def";
a will intern "abc", and "def", and allocate "abcdef" on the heap
b will intern "abcdef".
The main benefit of String.Empty is to avoid typo. "" is not so easily differentiated from " " in a glance.
There is no performance difference. I don't understand why so many people keep talking that performance is related to such trivial code convention differences. If performance tuning is that easy, why doesn't the complier do it? It is almost an insult to the developers of the compilers.
I use `string.Empty` for two reasons;
1. It's more explanatory then ""
2. The value "" might not be empty, it could contain some char that is not visible.
I do have a question which I'm not sure anyone can answe.. Why is `string.Empty` declared as readonly and not const? That would allow us to use it as default value for arguments and still result in the same compile time optimization 🤷♂️
It’s due to its original use with unmanaged code. There used to be a blog talking about that very thing but I can’t find it anymore
@@nickchapsas Ah interesting, if you do find that blog post, please share it with me as I would very much appreciate it!
I was going to comment to point out #2, so thank you for already doing that. I’ve seen too many instances where someone copies and pasted something into code and their code does not work. Then they manually type it in and it works, and they don’t understand why. I’ve had to copy and paste into notepad and show them that when I press the over arrow, it doesn’t “move”, meaning there’s an “invisible” character. So I prefer string.Empty as well.
Are you Greek I can tell by your accent
string.empty is useful in cross platform.
IMO: if one is searching for performance in "" vs string.Empty, then C#/.net is wrong environment for the task.
It's like trying to save pennies while loosing millions in the runtime/garbage collector.
One warm tip. Talk a little slower. It will be even more effective.
Regards