C#中字符串的行为

时间:2011-05-03 07:02:48

标签: c#

我是一名C ++程序员,现在正致力于C#项目。

我试图在下面的片段中理解为什么即使函数正在改变它的值,字符串的值也不会改变,我认为它是一个对象并且将作为参考传递。

public class TestClass
    {
        public TestClass(String passedStr)
        {
            passedStr = "Change me";
        }
    }
    class Program
    {
        static void Main(string[] args)
        {
            String aString="I am what i am";
            TestClass obj = new TestClass(aString);
            Console.WriteLine(aString);

        }
    }

但是用户定义的类的行为是不同的。

 public class TestClass
    {
        private int x;
        public int ID
        {
            get
            {
                return x;
            }
            set
            {
                x = value;
            }
        }
        public TestClass(int a)
        {
            x = a;
        }
    }
    public class Tester
    {
        public Tester(TestClass obj)
        {
            obj.ID = 999;
        }
    }

    class Program
    {
        static void Main(string[] args)
        {

            TestClass obj = new TestClass(555);
            Tester tester = new Tester(obj);
            Console.WriteLine(obj.ID);
        }
    }

7 个答案:

答案 0 :(得分:6)

让我们回到基础。

变量是存储位置。

string类型的变量是存储空间或对字符串的引用的存储位置。

“passedStr”和“aString”是不同的变量

当您调用“new TestClass(aString)”时,为“passStr”创建一个新的存储位置,并将“aString”的内容复制到其中。您现在有两个具有相同内容的变量:对字符串的引用。

在构造函数中,您可以更改存储在“passedStr”存储位置中的值。 “aString”保持不变。

C#中的“ref”和“out”关键字表示“使形式参数和参数别名彼此”。在这种情况下,您只有一个变量,其中两个不同的名称。当你改变其中一个时,另一个也会改变,因为它们是同一个变量。

答案 1 :(得分:5)

不,它是按价值传递的;没有ref关键字。

传递引用类型(此处为类)按值(无ref关键字),就像在C ++中传递指针的副本一样。你要重新分配指针,而不是实际数据(无论如何你都不能用字符串)。

如果您需要传递引用,请尝试:

    public TestClass(ref String passedStr)
    {
        passedStr = "Change me";
    }

    ...
    TestClass obj = new TestClass(ref aString);

答案 2 :(得分:1)

字符串通过引用传递,但指针在C#中通过值传递。如果您想通过引用传递字符串,则必须使用ref关键字。

例如:

public class TestClass
{
    public TestClass(ref string passedStr)
    {
        passedStr = "Change me";
    }
}

class Program
{
    static void Main(string[] args)
    {
        string aString="I am what i am";
        TestClass obj = new TestClass(ref aString);
        Console.WriteLine(aString); // "Change me"

    }
}

答案 3 :(得分:1)

passedStr不是字符串,而是包含对字符串的引用的构造函数参数。您的TestClass构造函数正在执行的是更改此参数引用的字符串。它在构造函数之外没有任何影响。

答案 4 :(得分:0)

您在构造函数中所做的是将 new 字符串文字分配给局部变量passedStr

在C中,等效函数看起来像这样:

Testclass constructor_testclass(char* passedStr) {
    passedStr = "Change me";
}

我认为很明显,这个函数不会改变调用函数中char*的值。

答案 5 :(得分:0)

对象I am what i am通过引用传递,但重新分配是局部变量。您不会更改原始对象,而是将新对象(Change me)分配给参数的位置。

答案 6 :(得分:0)

public class Employee
{
    public string ID { get; set; }
    public string Name { get; set; }

    public override string ToString()
    {
        return string.Format("ID = {0} Name = {1}", ID, Name);
    }
}

public class TestClass2
{
    public TestClass2(Employee e)
    {
        e.ID="007";
        e.Name="james";
    }
}  



static void Main()
{

    Employee e = new Employee();
    e.ID = "0";
    e.Name = "nobody";
    TestClass2 t = new TestClass2(e);
    Console.WriteLine(e); //Output ID = 007 Name = James 
}  

字符串通过引用传递,但指针在C#

中按值传递

Parameter passing in C# by Jon Skeet