String concatenation/interpolation will be resolved in compile time, if strings are const. It is called constant folding. I.e. such code const string a = "a"; const string b = "b"; const string c = $"{a} and {b}"; const string d = $"{a} and {b}"; Console.WriteLine(ReferenceEquals(c, d)); will print "True".
That's true. In java it's called compile-time concatenation and runtime concatenation. I always found it a bit weird but once I properly learned it it made a lot of sense.
That doesn't seem like an April Fool's prank. An actual April Fool's prank would either be completely over the top or at least progressively become more and more obviously ridiculous. It's more likely that this person got called out and used April Fool's as an excuse after the fact.
THis is why hate the removal of dislike/down vote buttons accross the web. It makes it look like this other terrible information is good when it's really ass.
I've used string.Intern and made a ListIntern class for a deserializer of a mongoDB array. ONLY because the string values were common, but with some custom flexibility. Like "categories of x" type stuff. Basically if you ran a distinct on 100k rows, you would get less than 100 unique values, type stuff. My advice is only use intern when you see common strings live in memory for over several minutes, that aren't capable of being in just an enum (because they are dynamic/custom) I've also made a custom object.intern type class, because it allows me to completely reset the intern memory, or group chunks/categories. Think I've only used it on strings though, cant recall.
Do you know what I want to see someone try.... Do you remember when we all discovered that on googles homepage only one image file downloaded, and CSS would be use to crop sprites out and use those for all images displayed? Lets do that with strings in C#. Lets declare one massive string (that contains any possible character sequence we might need in our application). And then whenever we need something we can use Span to grab just the portion we need. 😆😆😆
Sounds like pi compression. You calculate pi to however many digits you need before you find a series of numbers that matches whatever data you're trying to compress. Then you just store the offset and length. The compression ratio is pretty good. Compression and decompression is a little resource intensive though.
Hey Nick, in my 12 yr .net swe life, I only used once the intern method, to be able to lock a method by a value of a string. If you lock using the string itself, it does object comparison and it does not actually lock as the string value was coming from the request. Then we needed to intern it...
Why did String.Intern break up with its garbage collector? Because every time it tried to be efficient with memory, the garbage collector said, "I don't see any future in this relationship. You keep holding onto things from the past!"
I didn't know about string.Intern. It's definitely good to know that this happens automatically from the compiler. I therefore also don't see, why I would ever use it manually in my own projects, since it's already happening where it makes sense. But just knowing that this happens is good, I think.
It might be useful in very VERY specific scenarios. For example when the strings are not necessarily known at compile time (or are known, but new instances come from deserialization for example), the possible set is limited and relatively small, you trust the source, and strings will be long lived (like long memory cache etc). Yes, all these conditions are an AND, combined. I actually did use interning in my project recently, although doing this as means for trying to find the cause of constantly increasing memory use (memory leaks gonna be the death of me). It is a tool, and it exists to be used - however if you know what you're doing and are sure you need it. This is definitely a rare case that you'll need manual string interning. In VAST MAJORITY of cases you do NOT need to even worry about it.
@@TehGM lets say i have a json with a branch for "colors" at the top, which contains a "red": "255 0 0 255", and then "elements" below it, which contains many other branches for different elements, such as "mainmenu" and all that, which contains all the elements and configurations for those, and those elements have colors set to them, such as "fgcolor" for a button which uses the "red" (to give an idea of why repeat values happen in this case) so if i got this right, i could intern the values from the element color configurations and other repeat cases in branches in deserialization to optimize it. (to make sure i understood this correct, found your mention of this interesting in stuff i may need it in as im dealing with something like this and there are tons of repeat values trough that, ill prolly benchmark this later) not that ill need to optimize though. but i could funky it up to make things nicer. generally see if ill add to this as a standard to future stuff if there's no harm in it when done right.
@@c.Orange I'd shy away from interning values, as values by nature can be very different. Keys on the other hand might make sense. I specifically use it for character stat IDs - all stats come from API, so they might change once game updates, but they're still finite and really frequent. So interning these might make sense. However, you say you don't need to optimize that yet. In that case, skip manual interning altogether. Only worry about it when you actually see memory issues, and believe this might be the cause. Don't optimize prematurely.
I agree, very bad advise! I would add that the compiler does also more magic if things are correctly declared! For example doing string concatenation of only consts and literals also the result is an intern (because it's still const). const string hello = "hello"; const string world = "world"; var all = "hello world"; var a = hello + " " + world; var b = $"{hello} {world}"; Debug.Assert(ReferenceEquals(all, a), "not intern"); Debug.Assert(ReferenceEquals(a, b), "not intern");
Maybe it's good to note that composed strings, either by concatenation or interpolation, can also be completely evaluated compile time and therefore interned. This happens in the cases where all parts which compose the string are either literals or const declared identifiers. This type of string composition also comes with absolutely zero runtime overhead, and decompiled code will just show the whole thing joined together.
It bothers me how much emphasis on [micro] performance people have with C#. If you __really__ need it (and you probably don't), then go use C++. C# is really fast on its own without much special attention. Its far more important to focus on readability and maintainability.
100% agree. Dont use string.intern manually unless you a have specific use-case for that. Btw i bought that clean code course on dometrain and are neither impressed nor disappointed. It is a good course for new programmers and i like it that it does not follow the "clean code" book from uncle bob. It uses good concepts, but if you are an experienced programmer you most likely know them already and may already use them. Also one important concept is missing -> Clean code on class/library/application level! You should add them as well, simply following the SOLID principles and decrease coupling and increase cohesion, but only when it makes sense. Oh and i am not a fan of introducing libraries into the mix, when normal C#/.NET is totally sufficient (e.g. Guard Clauses).
I saw the same post on X, and I wondered if it would make sense to mention you there. However, I took on the role of "Code Cop" and explained why this advice doesn't make sense.
Definitely agreeing with you that making april fools jokes like this is just extremely dumb. For sure someone actually thought this was real advice and will use it somewhere.
I think the StringBuilder class deserves mentioning. Isn't that the recommended way if you have to combine strings? I don't know how it compares in memory usage and performance.
Careful. You're falling precisely into the dogmatic fallacy these videos fight. Advice that, right or wrong, doesn't provide full context. SB is NOT free. It has to be brought into existence, an initial alloc must be made as it needs memory to work with, and then you MIGHT reap benefits. If you "macro" your code substituting every a+b with a StringBuilder, you're going to DEGRADE your performance. The key point is understanding what StringBuilder was made for. It was never to do a+b, they'd have changed String if that was the case. It was for "building content in a string form in an iterative manner". Something like out=string.Empty; foreach(string word in wordlist){ out+=word; }. Now the question becomes "when does a+b fall behind StringBuilder?". And the answer as usual is "Benchmark it" :) p.s. you can apply this to anything of the sort, say for example LINQ. LINQ is NOT free, and depending on your use case, you might be better of with a simple for loop.
Hahaha! I already saw the corresponding tip on linkedin and I told to myself : oh well, I know what will be the next episode of code cop... And it looks like I was right! 🙃
The main benefit of using intern is actually to save on equality checks on the same objects. The memory saving is a bonus but probably isn't worth the overhead.
As I know Roslyn (I mean code of the compiler itself, not the code it compiles) interns all the strings to gain large perf boost from always comparing strings by reference and never by value. Is that true or I misread smth several years ago?
Yes, there is place for potentially harmful jokes like ranking every programming language 🙂 About this advice, I would make mandatory to read Clr via C# for every C# developer. This should be so obvious. I was thinking doing an April's fool joke myself as well: that Microsoft solved it's longest running bug and now we can make lock() on a type itself, but I chickened out 🙂 I think the real problem is developing against clr without knowing how it works.
I feel like there is a decent sized subset of coders out there who don't actually understand that the compiler optimizes for you - more than once I've found code or inherited projects where the previous person was spending significant work to try to hand-optimize the code and wound up producing identical or near identical results post-compilation. It's like there is a tendency to assume that what you wrote is going to be strictly translated one for one to IL.
The sad thing is that the same day this post was created the author got a MVP award from Microsoft. You can tell that Microsoft gives MVP as candy to kids.
@@dariogriffo The Good old Griffo 😂 If you need a complete post with all the comments, I saved it for guys like you, ping me, will send it to you. :) Of course, I deleted the post, it's a joke. And yes, I could delete Nick's comment, but I know what I did on purpose. And I knew someone would tag him. I could have deleted the comment, but there's no need for you to. In the comment, I even allowed Nick to mention and use my post in the video because otherwise there could be problems. :) Ah yes, the famous MVP award. Well, if you have been told, it is not actually given for someone who posted 2,3 posts there, instead, for contributions all over the internet going back months and years. And since you are such a faithful follower of mine (thank you! :D), you know that where I am, I have not been since yesterday. One "joke" post (I still think it's sarcastic - my followers didn't take it for granted) will certainly not undo all the good I've done so far. Enjoy! :D
That would have been a good April fool's day joke. Improve your API performance by avoiding slow, inefficient JSON serialization and simply pass raw binary instead! Here's a benchmark showing how much more efficient it is, just don't try to read the output
Don't listen to advices (including this) Just do things your usual way until you find out there is a problem that needs an advanced or unusual way to solve.
Protip: Save memory on strings: stop respecting immutability on strings. If you have one string, you can create an unsafe block, create a pointer to a string, and just use the same string over and over again. You pretty much only ever need 1 string instance ever, if you keep changing that same string forever
I’m sorely tempted to write one of these horrific LinkedIn posts, but use the capital letters of each sentence to spell out “code cop” or “call Nick” 😂
I think this wasn't an April fool's joke to begin with. I think the person who posted this got a lot of critique and decided to try and save face by saying it an joke afterwards.
When you load into memory large chunks of data (i.e. files) that contain lots of identical strings (keys, identifiers, tags, keywords and so on). And you intend to keep and use these strings (especially compare them) for a long period of time.
There are, but generally speaking, 99.99% of what you could conceivably want interned is already interned anyway. I'd generally only recommend using it for Keys you don't know ahead of time, and only from trusted sources at that. If you're reading data with a lot of repeating Values, consider the High Performance Community Toolkit's StringPool instead.
I don't like April fool jokes. Verbal or practical jokes are often harmful coz many people don't think of the effect it has on others. Then when something bad happens they say "Oh I didn't mean it". Well it's too late by then. Use your brain even if you have very little of it.
Hi Nick! Thank you for commenting on the post and thank you for posting the video, which I myself agreed with in advance. As you realized yourself, as it was written in the comment (not sure why are u saying it's not, but ok :D ), this was an April Fool's joke. After a few hours, the post itself was updated to make it even more obvious. In the end, the post was deleted, of course. What I really liked, which you could see for yourself, was that people shouted at me in the comments that what I wrote was not true - which means that people already knew a lot about it, and even if they didn't, they saw more comments that confirm it. At the end of the day, the "advice" is pretty basic. I hope the video gets a good response and you get a good conversion! :D Enjoy the sunny day!
When you posted this, there was no hint about it being a joke, not even in the comments. I saw your post a few hours after it being posted. And you did not respond to people proving you wrong either.
String concatenation/interpolation will be resolved in compile time, if strings are const. It is called constant folding.
I.e. such code
const string a = "a";
const string b = "b";
const string c = $"{a} and {b}";
const string d = $"{a} and {b}";
Console.WriteLine(ReferenceEquals(c, d));
will print "True".
That's true. In java it's called compile-time concatenation and runtime concatenation. I always found it a bit weird but once I properly learned it it made a lot of sense.
That doesn't seem like an April Fool's prank. An actual April Fool's prank would either be completely over the top or at least progressively become more and more obviously ridiculous. It's more likely that this person got called out and used April Fool's as an excuse after the fact.
100%. Unless he can PROVE it was an April fools joke he just got caught
Every "clean code" guidebook should start with a chapter on how to delete your LinkedIn account
I am printing this out and pasting on my office door
rule 1: delete your linked in account
rule 2: never take advice from an "engineer" wielding an Apple product
... or don't even create one.
Intern was the one who actually probably wrote that advice.
😂
😂😂😂
THis is why hate the removal of dislike/down vote buttons accross the web. It makes it look like this other terrible information is good when it's really ass.
I've used string.Intern and made a ListIntern class for a deserializer of a mongoDB array.
ONLY because the string values were common, but with some custom flexibility. Like "categories of x" type stuff. Basically if you ran a distinct on 100k rows, you would get less than 100 unique values, type stuff.
My advice is only use intern when you see common strings live in memory for over several minutes, that aren't capable of being in just an enum (because they are dynamic/custom)
I've also made a custom object.intern type class, because it allows me to completely reset the intern memory, or group chunks/categories. Think I've only used it on strings though, cant recall.
Do you know what I want to see someone try....
Do you remember when we all discovered that on googles homepage only one image file downloaded, and CSS would be use to crop sprites out and use those for all images displayed?
Lets do that with strings in C#.
Lets declare one massive string (that contains any possible character sequence we might need in our application).
And then whenever we need something we can use Span to grab just the portion we need.
😆😆😆
Just specify the whole list of possible UTF-8 characters and pick from the string when building your string. Easy!
That massive string idea is pretty good. It's called the heap.
Sounds like pi compression. You calculate pi to however many digits you need before you find a series of numbers that matches whatever data you're trying to compress. Then you just store the offset and length. The compression ratio is pretty good. Compression and decompression is a little resource intensive though.
Hey Nick, in my 12 yr .net swe life, I only used once the intern method, to be able to lock a method by a value of a string. If you lock using the string itself, it does object comparison and it does not actually lock as the string value was coming from the request. Then we needed to intern it...
Why did String.Intern break up with its garbage collector?
Because every time it tried to be efficient with memory, the garbage collector said, "I don't see any future in this relationship. You keep holding onto things from the past!"
I didn't know about string.Intern. It's definitely good to know that this happens automatically from the compiler. I therefore also don't see, why I would ever use it manually in my own projects, since it's already happening where it makes sense. But just knowing that this happens is good, I think.
Nick has made a video on this already which you can check out for more examples
huh, thanks. I will check that out. I have found this channel only recently, so there is probably a lot that I haven't seen yet.
It might be useful in very VERY specific scenarios. For example when the strings are not necessarily known at compile time (or are known, but new instances come from deserialization for example), the possible set is limited and relatively small, you trust the source, and strings will be long lived (like long memory cache etc). Yes, all these conditions are an AND, combined.
I actually did use interning in my project recently, although doing this as means for trying to find the cause of constantly increasing memory use (memory leaks gonna be the death of me).
It is a tool, and it exists to be used - however if you know what you're doing and are sure you need it. This is definitely a rare case that you'll need manual string interning. In VAST MAJORITY of cases you do NOT need to even worry about it.
@@TehGM lets say i have a json with a branch for "colors" at the top, which contains a "red": "255 0 0 255", and then "elements" below it, which contains many other branches for different elements, such as "mainmenu" and all that, which contains all the elements and configurations for those, and those elements have colors set to them, such as "fgcolor" for a button which uses the "red" (to give an idea of why repeat values happen in this case)
so if i got this right, i could intern the values from the element color configurations and other repeat cases in branches in deserialization to optimize it.
(to make sure i understood this correct, found your mention of this interesting in stuff i may need it in as im dealing with something like this and there are tons of repeat values trough that, ill prolly benchmark this later)
not that ill need to optimize though. but i could funky it up to make things nicer. generally see if ill add to this as a standard to future stuff if there's no harm in it when done right.
@@c.Orange I'd shy away from interning values, as values by nature can be very different. Keys on the other hand might make sense.
I specifically use it for character stat IDs - all stats come from API, so they might change once game updates, but they're still finite and really frequent. So interning these might make sense.
However, you say you don't need to optimize that yet. In that case, skip manual interning altogether. Only worry about it when you actually see memory issues, and believe this might be the cause. Don't optimize prematurely.
I agree, very bad advise! I would add that the compiler does also more magic if things are correctly declared!
For example doing string concatenation of only consts and literals also the result is an intern (because it's still const).
const string hello = "hello";
const string world = "world";
var all = "hello world";
var a = hello + " " + world;
var b = $"{hello} {world}";
Debug.Assert(ReferenceEquals(all, a), "not intern");
Debug.Assert(ReferenceEquals(a, b), "not intern");
You can save memory by reducing the font size. Same trick can be used to lighten your laptop.
Now THAT would have been a good April fool's joke!
you can also save memory by switching to light mode in VS / VS Code
Maybe it's good to note that composed strings, either by concatenation or interpolation, can also be completely evaluated compile time and therefore interned.
This happens in the cases where all parts which compose the string are either literals or const declared identifiers.
This type of string composition also comes with absolutely zero runtime overhead, and decompiled code will just show the whole thing joined together.
I think the author just used the excuse of the april fool joke when he saw people pointing out he's wrong in the comments.
❌Stop using strings!
✅Instead, use char arrays!
just malloc a void pointer and make a mental note on the type and size.
It bothers me how much emphasis on [micro] performance people have with C#. If you __really__ need it (and you probably don't), then go use C++. C# is really fast on its own without much special attention. Its far more important to focus on readability and maintainability.
100% agree. Dont use string.intern manually unless you a have specific use-case for that.
Btw i bought that clean code course on dometrain and are neither impressed nor disappointed. It is a good course for new programmers and i like it that it does not follow the "clean code" book from uncle bob. It uses good concepts, but if you are an experienced programmer you most likely know them already and may already use them. Also one important concept is missing -> Clean code on class/library/application level! You should add them as well, simply following the SOLID principles and decrease coupling and increase cohesion, but only when it makes sense. Oh and i am not a fan of introducing libraries into the mix, when normal C#/.NET is totally sufficient (e.g. Guard Clauses).
I saw the same post on X, and I wondered if it would make sense to mention you there. However, I took on the role of "Code Cop" and explained why this advice doesn't make sense.
Definitely agreeing with you that making april fools jokes like this is just extremely dumb. For sure someone actually thought this was real advice and will use it somewhere.
I think the StringBuilder class deserves mentioning. Isn't that the recommended way if you have to combine strings? I don't know how it compares in memory usage and performance.
Careful. You're falling precisely into the dogmatic fallacy these videos fight. Advice that, right or wrong, doesn't provide full context. SB is NOT free. It has to be brought into existence, an initial alloc must be made as it needs memory to work with, and then you MIGHT reap benefits. If you "macro" your code substituting every a+b with a StringBuilder, you're going to DEGRADE your performance. The key point is understanding what StringBuilder was made for. It was never to do a+b, they'd have changed String if that was the case. It was for "building content in a string form in an iterative manner". Something like out=string.Empty; foreach(string word in wordlist){ out+=word; }.
Now the question becomes "when does a+b fall behind StringBuilder?". And the answer as usual is "Benchmark it" :)
p.s. you can apply this to anything of the sort, say for example LINQ. LINQ is NOT free, and depending on your use case, you might be better of with a simple for loop.
Hahaha! I already saw the corresponding tip on linkedin and I told to myself : oh well, I know what will be the next episode of code cop...
And it looks like I was right! 🙃
The main benefit of using intern is actually to save on equality checks on the same objects.
The memory saving is a bonus but probably isn't worth the overhead.
As I know Roslyn (I mean code of the compiler itself, not the code it compiles) interns all the strings to gain large perf boost from always comparing strings by reference and never by value. Is that true or I misread smth several years ago?
Maybe they post it on LinkedIn by intention and wait for senior developer to noticed that it is wrong.
This time I recognised the author of the post because I am following him and I saw the post recently
*nervous const string a = "Hello world" noises*
Yes, there is place for potentially harmful jokes like ranking every programming language 🙂 About this advice, I would make mandatory to read Clr via C# for every C# developer. This should be so obvious.
I was thinking doing an April's fool joke myself as well: that Microsoft solved it's longest running bug and now we can make lock() on a type itself, but I chickened out 🙂
I think the real problem is developing against clr without knowing how it works.
Have you done any tuning to your Rider setup? It it always so snappy. If so I would love a How to set up Rider walkthrough
I feel like there is a decent sized subset of coders out there who don't actually understand that the compiler optimizes for you - more than once I've found code or inherited projects where the previous person was spending significant work to try to hand-optimize the code and wound up producing identical or near identical results post-compilation.
It's like there is a tendency to assume that what you wrote is going to be strictly translated one for one to IL.
The sad thing is that the same day this post was created the author got a MVP award from Microsoft. You can tell that Microsoft gives MVP as candy to kids.
the post was deleted :P
@@dariogriffo The Good old Griffo 😂 If you need a complete post with all the comments, I saved it for guys like you, ping me, will send it to you. :) Of course, I deleted the post, it's a joke. And yes, I could delete Nick's comment, but I know what I did on purpose. And I knew someone would tag him. I could have deleted the comment, but there's no need for you to. In the comment, I even allowed Nick to mention and use my post in the video because otherwise there could be problems. :)
Ah yes, the famous MVP award. Well, if you have been told, it is not actually given for someone who posted 2,3 posts there, instead, for contributions all over the internet going back months and years. And since you are such a faithful follower of mine (thank you! :D), you know that where I am, I have not been since yesterday. One "joke" post (I still think it's sarcastic - my followers didn't take it for granted) will certainly not undo all the good I've done so far. Enjoy! :D
@@thecodeman_ I'm 41, that's not old...
@5:50 if you declared the hello and world variables as const instead, string a and b would then contain the same reference, right?
And then the AI uses the post to give advice.
can't wait until copilot gets inadvertently trained on april fools day jokes
Sort of makes me think this wasn't an April Fool's joke until the OP got called out for it and it became "just a prank, bro!"
Everything stupid enough can retroactively be an April fools joke. "Lol jk guyssss"
Thanks Nick ! Keep it real !
This is why i just stream binary to the user.
That would have been a good April fool's day joke. Improve your API performance by avoiding slow, inefficient JSON serialization and simply pass raw binary instead! Here's a benchmark showing how much more efficient it is, just don't try to read the output
Wait, is that mean HTML isn't the best programming language ever created??
Also need a string for intern, means memory already allocated
Don't try to outsmart the compiler.
The real way to have zero heap-allocated strings is to stack allocate a span of characters. Good luck finding APIs that don't take strings though!
I use string.intern for string which repeats thousand times and are created dynamically. The qain is hardly measurable.
Don't listen to advices (including this)
Just do things your usual way until you find out there is a problem that needs an advanced or unusual way to solve.
are there any comments under those posts? Can you show them at the end? Anonymized of course
My guess is their next "tip" would be to concatenate string literals with StringBuilder.
Protip: Save memory on strings: stop respecting immutability on strings. If you have one string, you can create an unsafe block, create a pointer to a string, and just use the same string over and over again. You pretty much only ever need 1 string instance ever, if you keep changing that same string forever
Unpaid String Interns are the worst!
I’m sorely tempted to write one of these horrific LinkedIn posts, but use the capital letters of each sentence to spell out “code cop” or “call Nick” 😂
I think this wasn't an April fool's joke to begin with. I think the person who posted this got a lot of critique and decided to try and save face by saying it an joke afterwards.
this makes sense. Jokes generally have humor.
This throws up the question: How do you decide when to use a string literal v a resource file string?
Good contant. Im agree with u
Are there cases where it makes sense to use string.Intern()?
When you load into memory large chunks of data (i.e. files) that contain lots of identical strings (keys, identifiers, tags, keywords and so on). And you intend to keep and use these strings (especially compare them) for a long period of time.
There are, but generally speaking, 99.99% of what you could conceivably want interned is already interned anyway.
I'd generally only recommend using it for Keys you don't know ahead of time, and only from trusted sources at that.
If you're reading data with a lot of repeating Values, consider the High Performance Community Toolkit's StringPool instead.
Why using "intern" when you can 1/ use const 2/ think "DRY" and never repeat literals...
I used string.Intern in 2007)))
Linkedin does need a dislike button. X has the same problem.
I follow you and only you Nick
It's just a prank, bruhh
I don't like April fool jokes. Verbal or practical jokes are often harmful coz many people don't think of the effect it has on others. Then when something bad happens they say "Oh I didn't mean it". Well it's too late by then. Use your brain even if you have very little of it.
I’m just going to keep using string because I am lazy and can’t be bothered typing more to knacker my code
Such posts aren't deleted after april 1. ...
Hi Nick!
Thank you for commenting on the post and thank you for posting the video, which I myself agreed with in advance.
As you realized yourself, as it was written in the comment (not sure why are u saying it's not, but ok :D ), this was an April Fool's joke.
After a few hours, the post itself was updated to make it even more obvious.
In the end, the post was deleted, of course.
What I really liked, which you could see for yourself, was that people shouted at me in the comments that what I wrote was not true - which means that people already knew a lot about it, and even if they didn't, they saw more comments that confirm it.
At the end of the day, the "advice" is pretty basic.
I hope the video gets a good response and you get a good conversion! :D
Enjoy the sunny day!
When you posted this, there was no hint about it being a joke, not even in the comments. I saw your post a few hours after it being posted. And you did not respond to people proving you wrong either.
@@bogdan.p Wrong. In the first comment "Be sure to repost the post = help others to learn something new." on the bottom I wrote exactly that. :)
@@thecodeman_ You're about as funny as a cancer diagnosis. I suggest you stop trying to post jokes on the internet.
why on earth do you want to have 2 identical strings declared in your code? I don't get it...