2

I understand the difference of assigning a value or not, what I would like to understand is how the assignment is handle in memory.

What will be stored in the HEAP and in the STACK? Which one is the most efficient?

For example is more efficient to have a method signature like

private Item GetItem(pageModel page, string clickableText = null);

Or

private Item GetItem(pageModel page, string clickableText = "");

Note:

The question is not about which one to use. It is about how their differ in memory. The proposed method might be called a few hundred times - therefore a different variable assignment might/could have an impact?

Alex Leo
  • 2,781
  • 2
  • 13
  • 29
  • 4
    Out of interest, why do you care which is more efficient? I expect neither would be measurably more efficient. – ProgrammingLlama Sep 18 '19 at 07:14
  • A string is a class while a null is a address pointer. So an empty string is a string class with no data in the string. A null a result that returned nothing. – jdweng Sep 18 '19 at 07:15
  • @Itay Not really. This is C#, not C++. The argument may be passed through a register, and empty strings are already interned, so they do not mean any new allocation on the heap. Fully generally, you cannot say anything about what this program will do in memory (or if it will use memory at all) - it all depends on the runtime. And while C# strings do end with `\0` (for compatibility), they rely on a length-prefix in .NET, not the null char. – Luaan Sep 18 '19 at 07:21
  • Possible duplicate of [string.Empty vs null.Which one do you use?](https://stackoverflow.com/questions/6689876/string-empty-vs-null-which-one-do-you-use) – Sinatr Sep 18 '19 at 07:29
  • 1
    There is no assignment. Default parameter values are dealt with at compile-time, necessary because the CLR doesn't have the concept. It alters the *call* to the method, just as if you would have written GetItem(foo, null) explicitly. Generating the null is very simple, as is the reference to String.Empty, that is done at just-in-time compile-time and requires no storage. It is technically possible that the reference to String.Empty can cause a page-fault, but odds are low and that will only happen once. Measuring it should show it makes no difference. – Hans Passant Sep 18 '19 at 07:55

3 Answers3

7

There's no difference. The compiler interns string literals, so you're not creating a new string with the call, just referencing an existing string.

The heap and the stack are implementation details in C#. There is some behaviour that depends on the runtime, but the only real contract is that the runtime provides as much memory as you ask for, and guarantees the memory is still there if you access it in the future.

If you do care about the implementation details of the current desktop .NET runtimes, reference types are never passed on the stack. String is a reference type, so it is always passed by reference, and never by value. However, arguments aren't even required to be on the stack in the first place - the reference can also be passed in a register.

In general, in a managed language like C#, you should only care about what exactly happens in memory if you have a good reason it affects the characteristics of your program. The default case should always be thinking about the semantics. Should an empty string mean "no value"? Should a null string mean "no value"? That depends on the semantics of your program. Until you have a good reason to believe the decision is e.g. performance critical, just go with the most clear option, least prone to mistakes, and easiest to read and modify.

Luaan
  • 62,244
  • 7
  • 97
  • 116
2

A null string is a string that has not been initialized. It is a string variable that hasn't even been given some memory to store data. This will create a null string:

string myString; //Without initializing it, will create a null string.

An empty string is a string that has been initialized and given some memory, but it just doesn't contain any characters (except a null terminator at the end, but you don't see that) so as far as the compiler and you are concerned, it is a string with a length of 0.

string myString = String.Empty; //Will create an empty string.

In terms of efficiency, there shouldn't be a difference at all, but it would good to keep in mind that NULL's can cause projects to crash more than empty strings, unless you are using the NULL pattern in your code.

  • `string myString;` will only be a null string reference in a field. As a local, it is unassigned, and shouldn't be treated as a value, null or otherwise. As for nulls crashing, presumably if a null would crash your application, `string.Empty` might just allow it to silently continue in an unexpected state. NREs are awful exceptions, but it's better than not realising your code is doing something it isn't supposed to do. – Luaan Sep 18 '19 at 07:22
-1

We have four main types of things we'll be putting in the Stack and Heap as our code is executing: Value Types, Reference Types, Pointers, and Instructions.

Rules

  1. A Reference Type always goes on the Heap.

  2. Value Types and Pointers always go where they were declared. This is a little more complex and needs a bit more understanding of how the Stack works to figure out where "things" are declared.

The Stack, as we mentioned earlier, is responsible for keeping track of where each thread is during the execution of our code (or what's been called). You can think of it as a thread "state" and each thread has its own stack. When our code makes a call to execute a method the thread starts executing the instructions that have been JIT compiled and and live on the method table, it also puts the method's parameters on the thread stack. Then, as we go through the code and run into variables within the method they are placed on top of the stack.

String.Empty and "" are almost the same, both refer to an existing string that has no content.

Said almost because, "" creates a temporary string in memory (to have something to compare against) while String.Empty is a language constant.

On the other hand, null means nothing, no object at all.

In more familiar terms, String.Empty is like having an empty drawer while null means no drawer at all!

Mahesh Waghmare
  • 726
  • 9
  • 27