【问题标题】:C# Object property modified in the called function affect caller value在被调用函数中修改的 C# 对象属性影响调用者值
【发布时间】:2015-01-29 07:08:04
【问题描述】:

我用以下定义定义了一个简单的类。 在这个示例中,我定义了一个带有单个字符串参数的简单类。然后我实例化了这个类并为参数赋值。我将该实例传递给另一个函数而没有指定“ref”关键字。这意味着它应该通过值而不是引用传递。但我不明白的是输出结果显示“第二次修改”值而不是“第一次修改”的原因。

更新 1:

我认为我的问题令人困惑。我知道“参考”和“通过参考”是如何工作的。我需要知道为什么当我“按值传递”时,运行时仍然会更改原始实例的值。顺便说一句,我在建议的链接中找不到我的答案。

更新 2:

两年前我问过这个问题。现在我了解对象(类的实例)的所有属性都是引用类型。这意味着当我将一个类的实例传递给另一个方法时,它们都表现为对该类原始成员的引用。


public class MyClass
{
    public String TestProperty { get; set; }
}

public class TestClass
{
    public TestClass()
    {
        var myClass = new MyClass();
        myClass.TestProperty = "First Modification";
        MyFunction(myClass);
        Console.WriteLine(myClass.TestProperty); // Output: "Second Modification"
    }
    void MyFunction(MyClass myClass)
    {
        myClass.TestProperty = "Second Modification";
    }
}

【问题讨论】:

  • 是的。对实例的reference 是按值传递的。这完全是意料之中的行为。
  • 谢谢@J.Steen。您发布的链接是我正在寻找的答案。
  • 引用类型总是按引用传递,即使按值传递(因为值是引用)-stackoverflow.com/questions/264609/…
  • 原始类型,如 int、float、bool 是“按值”传递的,但对象(例如您的类实例)是通过引用传递的。至少,这是大多数人的想法。想象一下,如果您的类包含 1000 个变量。在每个函数调用中传递类实例的副本(以及它包含的所有值)既低效又不可取。您的 myClass 变量是对您的 MyClass 对象实例的引用。当您将它传递给函数时,您将按值传递该变量(这是一个参考)。然后您的 fn 正在使用 ref 更新道具

标签: c# class pass-by-reference pass-by-value


【解决方案1】:

你可以改变传递给方法的对象,但是你不能改变引用本身没有ref关键字

public class MyClass
{
    public String TestProperty { get; set; }
}

public class TestClass
{
    public TestClass()
    {
        var myClass = new MyClass();
        myClass.TestProperty = "First Modification";

        MyFunction(myClass);
        Console.WriteLine(myClass.TestProperty); // Output: "First Modification"

        MyRefFunction(ref myClass);
        Console.WriteLine(myClass.TestProperty); // Output: "Third Modification"
    }
    void MyFunction(MyClass myClass)
    {
        myClass = new MyClass() { TestProperty = "Second Modification"};
    }

    void MyRefFunction (ref MyClass myClass)
    {
        myClass = new MyClass() { TestProperty = "Third Modification"};
    }
}

如果你想防止属性被改变,你可以将 setter 设为非公开:

public String TestProperty { get; private set; }

【讨论】:

  • 很好的解释,但没有回答我的问题。为什么在“MyFunction”调用中,如果我们不重新实例化参数,我们可以修改属性的原始值?我需要了解背后的逻辑。我知道如何解决这个问题。提前致谢。
  • 因为对象是可变的。它应该能够改变(因为它有一个 setter),并且它应该可以被不同的对象改变(因为它被声明为 public)。您可以通过将设置器设为非公开来防止它被更改:public String TestProperty { get; private set; }
【解决方案2】:

这是预期的行为。 ref 允许您做的是在 MyFunction 中创建一个新对象并将其分配给 myClass 参数,并使新对象在方法之外可用。

   void MyFunction(ref MyClass myClass)
   {
     myClass = new MyClass(); //this new instance will be accessible outside the current method
   }

查看http://msdn.microsoft.com/en-us/library/14akc2c7.aspx了解更多详情。

【讨论】:

    猜你喜欢
    • 2011-12-26
    • 2019-10-11
    • 2018-02-06
    • 1970-01-01
    • 2019-10-18
    • 1970-01-01
    • 2012-01-29
    • 2012-05-06
    • 1970-01-01
    相关资源
    最近更新 更多