【问题标题】:Passing an object as a constructor parameter seems to be passing by reference instead of value将对象作为构造函数参数传递似乎是通过引用而不是值传递
【发布时间】:2018-08-17 17:09:03
【问题描述】:

我有一个奇怪的问题,我正在创建一个新对象,其中包含我通过我的函数使用的另一个对象 (paramObj) 的参数。因此,在对象构造函数中使用了 paramObj,但在调用构造函数后它最终被更改。由于 C# 是按值传递的,我不确定为什么会这样。

我的代码:

void MyFunction(List<string> filesets)
{
    foreach(Fileset fs in filesets)
    {
        //At this point, fs.allFiles.Count is 30. The MyNewObject class
        //takes a Fileset as a parameters and eventually clears the 
        //Fileset.allFiles List, making the count 0.
        MyNewObject tmpObj = new MyNewObject(fs, null, "default");

        //At this point, fs.allFiles.Count is 0, but I expect it to be 30

    }
}

MyNewObject 类只是清除 Fileset 类中包含的 allFiles 列表。如果 C# 是传值,为什么会出现在构造函数之后?

【问题讨论】:

  • 引用fs是按值传递的。从逻辑上讲,内容是通过引用传递的。
  • 您是说 Fileset 对象的所有字段都是通过引用传递的 - 这与通过引用传递的整个对象不同吗?反正有这个吗?
  • 你读过那篇文章吗? stackoverflow.com/questions/8708632/…
  • 如果你想阻止构造函数改变它接收到的引用的对象,试试下面的方法:MyNewObject tmpObj = new MyNewObject((Fileset)fs.Copy(), null, "default");

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


【解决方案1】:

您说得对,.NET 中的所有内容都是按值传递的。甚至 references - 这就是 fs 实际上 - 是按值传递的。因此,当您在您的方法周围传递fs 时,将有一个该引用的副本。然而,此引用引用了完全相同的 object,对该引用进行任何更改,同时修改支持 object

因此,在您的构造函数中,您对FileSet-instance 引用 fs 有一个第二次引用

这或多或少得出结论,即对象有效地引用传递。

没有简单的方法可以规避这一点。这取决于您为什么在构造函数中甚至修改该对象上的任何内容。您可以尝试在构造函数中复制 fs 引用的提供的对象,例如通过在FileSet 中实现IClonable 或通过在该类中提供复制构造函数或其他方式。但是,根据 FileSet 和它的成员,您将需要提供的实例的一些 deep 副本。

如需进一步了解如何制作对象的深层副本,请查看此处:Deep cloning objects

【讨论】:

    【解决方案2】:

    通常,所有对象都通过引用作为参数传递给方法。另一方面,大多数原始数据类型,如整数、双精度、布尔值等都是按值传递的。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-09-16
      • 2012-07-05
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多