将对象作为构造函数参数传递似乎是通过引用而不是值传递

Passing an object as a constructor parameter seems to be passing by reference instead of value

我在创建一个新对象时遇到奇怪的问题,该对象包含我在函数中使用的另一个对象 (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 class 只是清除 Fileset class 中包含的 allFiles 列表。如果 C# 按值传递,为什么它会出现在构造函数之后?

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

你说得对 .NET 中的一切都是按值传递的。甚至 references - 这就是 fs actually 是按值传递的。因此,当您在方法周围传递 fs 时,您的方法将具有该引用的 副本 。但是,此引用引用完全相同的 object,对该引用进行任何更改也会修改支持 object

所以在你的构造函数中你有一个 second reference to FileSet-instance referenced by fs .

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

没有简单的方法可以避免这种情况。这取决于您为什么要 修改 构造函数中该对象上的任何内容。您可以尝试在构造函数中复制 fs 引用的提供的对象,例如通过在 FileSet 中实现 IClonable 或在 class 中提供 copy-constructor 或其他方式。但是,根据 FileSet 及其成员的不同,您将需要所提供实例的一些 deep 副本。

要进一步阅读如何制作对象的深拷贝,请看这里:Deep cloning objects