按值传递对象是否创建文件系统监视程序的两个实例



我有3个类。一个类是我的"Worker"类,它有一个文件系统监视器。主表单(类A)保存对List (_workerList)中每个实例化的Worker对象的引用。如果我将_workerList传递给类B(这是通过构造函数完成的),并在类B中保存该列表的副本,这是否意味着我有两个文件系统监视程序的实例同时运行?

public partial class A : Form
{
    private List<Worker> _workerList;
    public A()
    {
        InitializeComponent();
        _workerList = new List<Worker>();
    }
    private void button_Click(object sender, EventArgs e)
    {
        _workerList.Add(new Worker());  //the worker class contains a file system watcher
        using( B b = new B(_workerList))
        {
            b.ShowDialog();
        }
    }
}
public partial class B : Form
{ 
    private List<Worker> _workerListCopy;
    public B(List<Worker> originalWorkerList)
    {
        InitializeComponent();
        _workerListCopy = new List<Worker>(originalWorkerList)
    }
}

但也许不是你想的原因。您创建了一个名为"Worker"的class。这意味着它自动成为一个引用类型。引用类型按值传递,但作为引用传递(不生成副本)。

您可以更改对象本身,但是对参考点所在位置的更改不会反映在原始变量中。

这意味着由于您没有再次使用new操作符来创建新的Worker类,因此只创建了一个FileSystemWatcher

您正在创建两个List<Worker>实例,但它们共享相同的Worker引用。

这不会创建两组FileSystemWatcher实例

A类中创建了一个List<Worker>:

_workerList -> []  // empty list

然后添加一些Worker s:

_workerList -> [ worker1, worker2 ]
这里的问题是列表_workerList不包含对象worker1worker2,它包含对这些对象的引用:
                 worker1   worker2
_workerList ->  [   ↑     ,   ↑     ]

当你在B类中创建一个新的列表时,像这样:

_workerListCopy = new List<Worker>(originalWorkerList);

你要做的是对原始列表做一个副本。它将复制引用而不是这些引用所指向的对象。所以你会得到这样的结果:

_workerCopy ->  [   ↓         ↓     ]
                 worker1   worker2
_workerList ->  [   ↑     ,   ↑     ]
因此,尽管您有两个列表,每个列表中都有2个Worker对象,但它们在两个列表中都是相同的两个Worker对象。您总共只有2个Worker对象和一组FileSystemWatcher(每个Worker的唯一实例一个)。

你可以很容易地确认这一点,像这样做:

bool areTheSame = _workList[0] == _workerCopy[0];   // should be true

由于Worker是引用类型,默认的相等性是比较它们是否指向同一个对象。

但是,请注意,现在确实有两个单独的列表,它们恰好引用了相同的对象。如果通过添加或删除Worker来更改一个列表,则原始列表将不受影响,因为列表彼此独立。

最新更新