如何解决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的现有引用。
还是有第三种选择?
您可以将字段设置为只读(除了对象构造时的初始赋值)。
有两种稍微不同的方法可以做到这一点。第一种也是最可靠的方法是使用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字段会导致内存泄漏,那么你的析构函数就在错误的类中。