I know that \"string\" in C# is a reference type. This is on MSDN. However, this code doesn\'t work as it should then:
class Test
{
public static void
"A picture is worth a thousand words".
I have a simple example here, it's similar to your case.
string s1 = "abc";
string s2 = s1;
s1 = "def";
Console.WriteLine(s2);
// Output: abc
This is what happened:
s1
and s2
variables reference to the same "abc"
string object."abc"
string object do not modify itself (to "def"
), but a new "def"
string object is created instead, and then s1
references to it.s2
still references to "abc"
string object, so that's the output.Try:
public static void TestI(ref string test)
{
test = "after passing";
}
Above answers are helpful, I'd just like to add an example that I think is demonstrating clearly what happens when we pass parameter without the ref keyword, even when that parameter is a reference type:
MyClass c = new MyClass(); c.MyProperty = "foo";
CNull(c); // only a copy of the reference is sent
Console.WriteLine(c.MyProperty); // still foo, we only made the copy null
CPropertyChange(c);
Console.WriteLine(c.MyProperty); // bar
private void CNull(MyClass c2)
{
c2 = null;
}
private void CPropertyChange(MyClass c2)
{
c2.MyProperty = "bar"; // c2 is a copy, but it refers to the same object that c does (on heap) and modified property would appear on c.MyProperty as well.
}
The reference to the string is passed by value. There's a big difference between passing a reference by value and passing an object by reference. It's unfortunate that the word "reference" is used in both cases.
If you do pass the string reference by reference, it will work as you expect:
using System;
class Test
{
public static void Main()
{
string test = "before passing";
Console.WriteLine(test);
TestI(ref test);
Console.WriteLine(test);
}
public static void TestI(ref string test)
{
test = "after passing";
}
}
Now you need to distinguish between making changes to the object which a reference refers to, and making a change to a variable (such as a parameter) to let it refer to a different object. We can't make changes to a string because strings are immutable, but we can demonstrate it with a StringBuilder
instead:
using System;
using System.Text;
class Test
{
public static void Main()
{
StringBuilder test = new StringBuilder();
Console.WriteLine(test);
TestI(test);
Console.WriteLine(test);
}
public static void TestI(StringBuilder test)
{
// Note that we're not changing the value
// of the "test" parameter - we're changing
// the data in the object it's referring to
test.Append("changing");
}
}
See my article on parameter passing for more details.
I believe your code is analogous to the following, and you should not have expected the value to have changed for the same reason it wouldn't here:
public static void Main()
{
StringWrapper testVariable = new StringWrapper("before passing");
Console.WriteLine(testVariable);
TestI(testVariable);
Console.WriteLine(testVariable);
}
public static void TestI(StringWrapper testParameter)
{
testParameter = new StringWrapper("after passing");
// this will change the object that testParameter is pointing/referring
// to but it doesn't change testVariable unless you use a reference
// parameter as indicated in other answers
}
Actually it would have been the same for any object for that matter i.e. being a reference type and passing by reference are 2 different things in c#.
This would work, but that applies regardless of the type:
public static void TestI(ref string test)
Also about string being a reference type, its also a special one. Its designed to be immutable, so all of its methods won't modify the instance (they return a new one). It also has some extra things in it for performance.