在实例化上提供类唯一ID:.Net
每次实例化一个新的ID时,我都想给它一个唯一的ID。例如,对于名为Foo的类,我希望能够执行以下操作
dim a as New Foo() dim b as New Foo()
并且a将获得唯一的ID,b将获得唯一的ID。这些ID仅在运行时是唯一的,所以我只想使用一个整数。我找到了一种方法来执行此操作(但请注意),我不想从任何地方更改ID。我目前对实现此方法的想法如下:
Public Class test Private Shared ReadOnly _nextId As Integer Private ReadOnly _id As Integer Public Sub New() _nextId = _nextId + 1 _id = _nextId End Sub End Class
但是,这不会编译,因为它会引发错误
_nextId = _nextId +1
我不明白为什么这会是一个错误(因为_Id也是只读的,因此我们应该能够在构造函数中更改只读变量。)我认为这也与共享有关。任何解决方案(希望不是kludgy呵呵)或者对此无效的解释都可以接受。重要的是,在对象初始化之后,我希望两个变量(或者是否只有一种方法甚至更好,但我认为这是不可能的)是不可变的。谢谢!
解决方案
回答
可能会引发错误,因为我们从未将_nextId初始化为任何东西。必须先设置一个初始值,然后才能安全地添加1.
回答
因为_nextId为ReadOnly,它会引发错误。删除那个。
编辑:
如我们所说,ReadOnly变量可以在构造函数中更改,但如果是Shared则不能更改。这些只能在共享构造函数中进行更改。例子:
Shared Sub New() _nextId = 0 End Sub
回答
这种设计容易受到多线程问题的影响。我强烈建议对ID(Guid.NewGuid())使用Guids。如果我们绝对必须使用int,请签出Interlocked类。我们可以将所有递增和Id逻辑包装在一个基类中,以便仅在一个位置访问ID生成器。
回答
ReadOnly变量必须在对象构造期间初始化,然后不能再进行更新。这不会编译,因为由于这个原因我们不能增加_nextId。 (Shared ReadOnly变量只能在Shared构造函数中分配。)
这样,如果删除_nextId定义上的ReadOnly修饰符,则应该没问题。
回答
我会这样
Public MustInherit Class Unique Private _UID As Guid = Guid.NewGuid() Public ReadOnly Property UID() As Guid Get Return _UID End Get End Property End Class
回答
共享整数不应为只读。标记为"只读"的字段只能分配一次,并且必须在构造函数退出之前分配。
由于共享字段是私有的,因此无论如何外部都不会更改该字段。
回答
考虑以下代码:
Public Class Foo Private ReadOnly _fooId As FooId Public Sub New() _fooId = New FooId() End Sub Public ReadOnly Property Id() As Integer Get Return _fooId.Id End Get End Property End Class Public NotInheritable Class FooId Private Shared _nextId As Integer Private ReadOnly _id As Integer Shared Sub New() _nextId = 0 End Sub Public Sub New() SyncLock GetType(FooId) _id = System.Math.Max(System.Threading.Interlocked.Increment(_nextId),_nextId - 1) End SyncLock End Sub Public ReadOnly Property Id() As Integer Get Return _id End Get End Property End Class
而不是在Foo中存储int,而是存储FooId类型的对象。这样,我们就可以完全控制ID可以做什么和不能做什么。
为了保护我们的FooId不被操纵,它不能被继承,并且除了构造函数和int的getter之外,没有其他方法。此外,变量_nextId是FooId专用的,不能从外部进行更改。最后,FooId的构造函数内部的SyncLock确保它永远不会并行执行,从而确保进程内的所有ID都是唯一的(直到我们击中MaxInt为止)。
回答
我们说过"这不会编译,因为它会引发错误",但从未说过该错误是什么。
共享变量是静态的,因此内存中只有一个副本可供所有实例访问。我们只能从静态(Shared)构造函数(New())修改静态只读(Shared ReadOnly),因此我们可能需要这样的东西:
Public Class test Private Shared ReadOnly _nextId As Integer Private ReadOnly _id As Integer Public Shared Sub New() _nextId = _nextId + 1 End Sub Public Sub New() _id = _nextId End Sub End Class
(我认为这是VB中正确的语法。)在Cit中如下所示:
public class Test { private static readonly int _nextId; private readonly int _id; static Test() { _nextId++; } public Test() { _id = _nextId; }
}
这里唯一的问题是静态构造函数将只被调用一次,因此_nextId仅将被递增一次。由于它是一个静态只读变量,因此我们只能使用静态构造函数对其进行初始化,因此新实例将不会像我们想要的那样获得递增的_id字段。
我们要在这种情况下解决的问题是什么?这些唯一ID是否必须为整数值?如果没有,我们可以使用Guid,并在构造函数中调用Guid。
回答
我发布了一个类似的问题,该问题集中在设置唯一实例ID的多线程问题上。我们可以查看它以获取详细信息。