C# string reference type?

C# string reference type?

回答1

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.

 

回答2

If we have to answer the question: String is a reference type and it behaves as a reference. We pass a parameter that holds a reference to, not the actual string. The problem is in the function:

public static void TestI(string test)
{
    test = "after passing";
}

The parameter test holds a reference to the string but it is a copy. We have two variables pointing to the string. And because any operations with strings actually create a new object, we make our local copy to point to the new string. But the original test variable is not changed.

The suggested solutions to put ref in the function declaration and in the invocation work because we will not pass the value of the test variable but will pass just a reference to it. Thus any changes inside the function will reflect the original variable.

I want to repeat at the end: String is a reference type but since its immutable the line test = "after passing"; actually creates a new object and our copy of the variable test is changed to point to the new string.

 

回答3

As others have stated, the String type in .NET is immutable and it's reference is passed by value.

In the original code, as soon as this line executes:

test = "after passing";

then test is no longer referring to the original object. We've created a new String object and assigned test to reference that object on the managed heap.

I feel that many people get tripped up here since there's no visible formal constructor to remind them. In this case, it's happening behind the scenes since the String type has language support in how it is constructed.

Hence, this is why the change to test is not visible outside the scope of the TestI(string) method - we've passed the reference by value and now that value has changed! But if the String reference were passed by reference, then when the reference changed we will see it outside the scope of the TestI(string) method.

Either the ref or out keyword are needed in this case. I feel the out keyword might be slightly better suited for this particular situation.

class Program
{
    static void Main(string[] args)
    {
        string test = "before passing";
        Console.WriteLine(test);
        TestI(out test);
        Console.WriteLine(test);
        Console.ReadLine();
    }

    public static void TestI(out string test)
    {
        test = "after passing";
    }
}

 

回答4

"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:

  • Line 1 and 2: s1 and s2 variables reference to the same "abc" string object.
  • Line 3: Because strings are immutable, so the "abc" string object does not modify itself (to "def"), but a new "def" string object is created instead, and then s1 references to it.
  • Line 4: s2 still references to "abc" string object, so that's the output.

 

作者:Chuck Lu    GitHub    
posted @   ChuckLu  阅读(52)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 全程不用写代码,我用AI程序员写了一个飞机大战
· DeepSeek 开源周回顾「GitHub 热点速览」
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 记一次.NET内存居高不下排查解决与启示
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了
历史上的今天:
2019-07-04 shell script operate the date
2019-07-04 Running .sh scripts in Git bash
2019-07-04 What is the !! (not not) operator in JavaScript?
2019-07-04 JavaScript-Load-Image
2019-07-04 jquery .each
2019-07-04 JavaScript json loop item in array
2019-07-04 Make jQuery throw error when it doesn't match an element
点击右上角即可分享
微信分享提示