Strings are reference types so if I use them in structs just the reference will be stored in the stack.
But why this code gives me foo1.Bar different from foo2.Bar?
var foo1 = new Foo();
foo1.Bar = "test";
var foo2 = foo1;
foo2.Bar = "test2";
Console.WriteLine($"foo1 -> {foo1.Bar}");
Console.WriteLine($"foo2 -> {foo2.Bar}");
struct Foo
{
public string Bar;
}
Shouldn’t foo1.Bar and foo2.Bar store the same reference and in this case show the same result at the end?
I’m using .NET 6, C# 10.0
>Solution :
This is really an interesting phenomenon. The = operator does a shallow copy of a struct and your expectation that the reference to the string should have been maintained is understandable. (The Struct.Clone() method does a deep copy)
But your expectation holds good for other primitive types, but not string. Remember, String derives from System.Object and not from System.ValueType. System.String is one of the few classes in the .NET Framework Base Class Library that is given special treatment by the CLR. It behaves much like a value type at runtime. String copy and compare operations result in value semantics rather than reference semantics.
So when you assign a struct to another with the = operator, the shallow copy creates a copy of the string instead of referring to the same string in memory.
The CLR optimizes string management by maintaining an internal pool of string values known as an intern pool for each .NET application. If the value being assigned to a string variable is the same as one of the strings already in the intern pool, no new string is created and the variable points to the address of the string in the pool. The compiler is capable of using the intern pool to optimize string initialization and have two string variables pointing to the same String object in memory. This optimization step is done only at compile time and isn’t performed at run time, though, because the search in the pool takes time and can even fail, adding overhead to the application.
Source: https://thedeveloperspace.com/back-to-basics-string-type-in-net/