我设计了一个类,其中包含有关将在SQL Server数据库中注册的给定对象的一些信息。我想使这个对象(深度)不可变,但我也必须保证它只被注册一次。如果此对象实现以下模式,它仍然可以被视为不可变吗?
public class NewClass
{
private bool registered;
public string SomeProperty { get; private set; }
public NewClass Register()
{
if (registered)
{
throw new NotImplementedException(/*arguments*/);
}
/* Register on DB here... */
registered = true;
return new NewClass(somePropertyFromDB);
}
public NewClass(string someProperty)
{
registered = false;
SomePropery = someproperty;
}
}
我会说,除了布尔字段registered
之外,对象是不可变的,但是这个字段让我有些怀疑,因为它会在第一次执行Register
方法时实际发生变化...任何人都可以告诉我如何解决这个问题仍然使对象不可变?
答案 0 :(得分:3)
不,它肯定是不不可变的。 registered
值会在对象的生命周期内发生变化。
要使其不可变,您不能允许registered
字段更改对象的生命周期 - 而是让Register
返回一个值true
的新对象registered
我还会移除SomeProperty
的私有设置器,只有一个getter和一个只读变量。
这样的事情:
public class NewClass
{
private readonly bool registered;
private readonly string someProperty;
public bool Registered { get { return registered; } }
public string SomeProperty { get { return someProperty; } }
public NewClass Register()
{
// Note the change of exception here
if (registered)
{
throw new InvalidOperationException("Already registered");
}
return new NewClass(somePropertyFromDB, true);
}
// You may want to have a public constructor with just someProperty
// which calls this one, which you could make private
public NewClass(string someProperty, bool registered)
{
this.registered = registered.;
this.someProperty = someproperty;
}
}
一些注意事项:
RegisteredFoo
和UnregisteredFoo
;这可能会使用这个类更容易理解代码Register
,所以使这种不可变性在幂等性方面并没有真正帮助。由于存在一种自然的副作用(与数据库交谈),因此很难使其真正发挥作用。