l按值和按参考传递

Lij*_*ijo 5 .net c# string pass-by-reference

你能解释一下C#Class的以下行为吗?我希望classResult为"Class Lijo"; 但实际值是"已更改".

我们正在复制参考文献.虽然副本指向同一地址,但接收参数的方法不能更改原始地址.

仍然为什么价值会发生变化?

public partial class _Default : Page 
{
    protected void Page_Load(object sender, EventArgs e)
    {
        String nameString = "string Lijo";

        Person p = new Person();
        p.Name = "Class Lijo";

        Utilityclass.TestMethod(nameString, p);
        string classResult = p.Name;
        Response.Write(nameString + "....." + classResult);
    }
}

public class Utilityclass
{
    public static void TestMethod(String nameString, Person k)
    {
        nameString = "Changed";
        k.Name = "Changed";
    }
}

public class Person
{
    public string Name
    {
        get; set;
    }
}
Run Code Online (Sandbox Code Playgroud)

更新:当我传递一个字符串时,它实际上没有被更改.

Jon*_*eet 22

最简单的答案是:阅读我关于参数传递的文章,其中详细介绍了这一点.

稍长的答案是比较这两个方法,两个方法都使用参数:

public void ChangeMe(string x)
{
    x = "changed";
}

public void ChangeMe(Person x)
{
    x.Name = "changed";
}
Run Code Online (Sandbox Code Playgroud)

在第一种情况下,您正在更改参数.这与原始论点完全隔离.您无法更改字符串本身的内容,因为字符串是不可变的.

在第二种情况下,您正在更改参数值所引用的对象内容.这并没有改变参数本身的价值 - 它将是相同的参考.举一个现实世界的例子,如果有人向你的房子提供改变房子内容的东西,但它不会改变你房子的地址.

如果您将第二种方法更改为:

public void ChangeMe(Person x)
{
    x = new Person("Fred");
}
Run Code Online (Sandbox Code Playgroud)

然后调用者不会看到任何变化.这更接近您使用字符串所做的事情 - 您正在使参数引用不同的对象,而不是更改现有对象的内容.

现在,当您使用ref参数时,调用者用作参数的变量是带参数的"别名" - 因此,如果您更改参数的值,那么也会更改参数的值.所以,如果我们改变最后一个方法:

public void ChangeMe(ref Person x)
{
    x = new Person("Fred");
}
Run Code Online (Sandbox Code Playgroud)

然后:

Person y = new Person("Eric");
ChangeMe(ref y);
Console.WriteLine(y.Name);
Run Code Online (Sandbox Code Playgroud)

这将打印出"弗雷德".

要理解的关键概念是变量的值永远不是对象 - 它可以是值类型值或引用.如果更改了对象的数据,则通过其他引用可以看到该更改.一旦您了解复制引用与复制对象不同,其余部分就可以轻松地复制到位.

  • 是的,你绝对可以创建自己的不可变类.只是不提供任何改变它的方法.2.您可以创建自己的自定义值类型,但它们不是类 - 它们将是结构.3.我不确定我是否真的理解这个问题 - 但是值类型值类似于"数字3"或"字母A",而引用是一种解决对象的方式,基本上 - 它是一个额外的级别间接. (2认同)

Dar*_*rov 7

Person是引用类型,所以无论是否使用ref,out或没有,你随时都可以修改它的方法内.您永远不会将真人对象传递给方法,您将指针作为参考而不是实际传递Person.该ref关键字对于值类型(例如,structs,int,float,DateTime,...)非常有用.它也可以与引用类型一起使用,但仅用于指示行为但不能强制执行.如果将它与引用类型一起使用,则允许您更改此引用指向的对象.

  • 我不确定你为什么说"`ref`关键字只对值类型有用".如果将它与引用类型一起使用,它允许您更改参数指向的对象,这在某些情况下非常有用. (4认同)