如何解决c#缺少赋值操作符重载的问题?

本文关键字:赋值操作符 重载 问题 何解决 解决 | 更新日期: 2023-09-27 18:12:10

我知道在c#中重载赋值操作符是不可能的…但是有可能阻止默认操作符吗?

情境:我正在开发一个复杂的结构编辑器。它将允许组合大量的类对象并将它们链接在一起。

为了能够在许多类的实例之间保存这些链接和引用,我需要每个实例在所有类中具有唯一的ID。我已经创建了一个ID类(包括对容器对象的引用)来处理这个问题。为了确保ID是唯一的,我让类在静态list<idClass> IDRegister中注册自己的所有实例,并在静态list<idClass> IDReferenceList中注册对任何ID实例的所有引用。

问题:在主分配/创建要使用的新ID-instance时,我在IDRegister中注册了ID,有效地创建了对对象的两个引用。在使用任何类实例的过程中,现在很容易用另一个id字段(现有的或新的)覆盖id字段。对未注册对象的正常覆盖将使实例不被引用,垃圾收集将负责内存清理。在这种情况下,对IDRegister中的实例的引用(可能在IDReferenceList中多次引用)将使ID-instance保持活动状态,并使它引用可能过时的容器对象,从而防止清除这些对象。所有这些都将在我的库中留下巨大的内存泄漏。

解决方案吗?

我不能接受库中可能存在的内存泄漏。我有两个选择:使用c++或找到一种方法来防止默认赋值覆盖对ID-instance的现有引用。

还是有第三种选择?

如何解决c#缺少赋值操作符重载的问题?

您可以将字段设置为只读(除了对象构造时的初始赋值)。

有两种稍微不同的方法可以做到这一点。第一种也是最可靠的方法是使用readonly字段,带有公共getter而没有setter。那么id只能在构造函数中设置。

private readonly int id;
public int Id
{
    get
    {
        return id;
    }
}

第二种是使用setter为私有的属性:

public int Id { get; private set; }

这允许id在构造后被更改,因此它与readonly不完全相同。但是由于setter是私有的,它仍然可以防止代码的客户端意外地更改值。

首先,您可以将ID字段设置为只读属性,只能通过初始分配来设置。

第二,如果你的应用程序可能有内存泄漏,那么你没有正确地进行清理。如果不在GC堆上进行分配,则需要有一个析构函数(通常还需要一个dispose())来确保清理。这应该在一个无法规避的地方进行。例如,如果你担心覆盖某个ID字段会导致内存泄漏,那么你的析构函数就在错误的类中。