Take the following example:
string me = "Ibraheem"开发者_StackOverflow社区;
string copy = me;
me = "Empty";
Console.WriteLine(me);
Console.WriteLine(copy);
The output is:
Empty
Ibraheem
Since it is class type (i.e. not a struct), String copy
should also contain Empty
because the = operator
in C# assigns reference of objects rather than the object itself (as in C++)??
While the accepted answer addresses this (as do some others), I wanted to give an answer dedicated to what it seems like you're actually asking, which is about the semantics of variable assignment.
Variables in C# are simply pieces of memory that are set aside to hold a single value. It's important to note that there's no such thing as a "value variable" and a "reference variable", because variables only hold values.
The distinction between "value" and "reference" comes with the type. A Value Type (VT) means that the entire piece of data is stored within the variable.
If I have an integer variable named abc
that holds the value 100
, then that means that I have a four-byte block of memory within my application that stores the literal value 100
inside it. This is because int
is a value type, and thus all of the data is stored within the variable.
On the other hand, if I have a string
variable named foo
that holds the value "Adam"
, then there are two actual memory locations involved. The first is the piece of memory that stores the actual characters "Adam"
, as well as other information about my string (its length, etc.). A reference to this location is then stored within my variable. References are very similar to pointers in C/C++; while they are not the same, the analogy is sufficient for this explanation.
So, to sum it up, the value for a reference type is a reference to another location in memory, where the value for a value type is the data itself.
When you assign something to a variable, all you're changing is that variable's value. If I have this:
string str1 = "foo";
string str2 = str1;
Then I have two string variables that hold the same value (in this case, they each hold a reference to the same string, "foo"
.) If then do this:
str1 = "bar";
Then I have changed the value of str1
to a reference to the string "bar"
. This doesn't change str2
at all, since its value is still a reference to the string "foo"
.
System.String
is not a value type. It exhibits some behaviors that are similar to value types, but the behavior you have come across is not one of them. Consider the following code.
class Foo
{
public string SomeProperty { get; private set; }
public Foo(string bar) { SomeProperty = bar }
}
Foo someOtherFoo = new Foo("B");
Foo foo = someOtherFoo;
someOtherFoo = new Foo("C");
If you checked the output of foo.SomeProperty
, do you expect it to be the same as someOtherFoo.SomeProperty
? If so, you have a flawed understanding of the language.
In your example, you have assigned a string a value. That's it. It has nothing to do with value types, reference types, classes or structs. It's simple assignment, and it's true whether you're talking about strings, longs, or Foos. Your variables temporarily contained the same value (a reference to the string "Ibraheem"), but then you reassigned one of them. Those variables were not inextricably linked for all time, they just held something temporarily in common.
It isn't a value type. When you use a string literal, its actually a reference stored when compiled. So when you assign a string, you are basically changing the pointer like in C++.
Strings behave the same as any other class. Consider:
class Test {
public int SomeValue { get; set; }
public Test(int someValue) { this.SomeValue = someValue; }
}
Test x = new Test(42);
Test y = x;
x = new Test(23);
Console.WriteLine(x.SomeValue + " " + y.SomeValue);
Output:
23 42
– exactly the same behaviour as in your string
example.
What your example shows is the classic behavior of a reference type which string is.
string copy = me;
means that copy
reference will point to same memory location where me
is pointing.
Later me
can point to other memory location but it won't affect copy
.
Your code would do the same if you used value types as well. Consider using integers:
int me = 1;
int copy = me;
me = 2;
Console.WriteLine(me);
Console.WriteLine(copy);
This will print out the following:
2
1
While the other answers said exactly what the solution to your answer was, to get a better fundamental understanding of why you will want to have a read up on heap and stack memory allocation and when data is removed from memory by the garbage collector.
Here is a good page that describes the stack and heap memory and the garbage collector. At the bottom of the article there are links to the other parts of the explanation: http://www.c-sharpcorner.com/UploadFile/rmcochran/csharp_memory01122006130034PM/csharp_memory.aspx?ArticleID=9adb0e3c-b3f6-40b5-98b5-413b6d348b91
Hopefully this should give you a better understanding of why
Answering the original question:
Strings in C# are the reference type with value type semantics.
They are being stored on the heap because storing them on the stack might be unsafe due to the limited size of the stack.
精彩评论