I have designed a class containing some information about a given object which will be registered in an SQL Server database. I would like to make this object (deeply) immutable, but I also must assure that it gets registered only once. If this object implements the following pattern, can it still be considered immutable?
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;
}
}
I would say that except for the boolean fi开发者_如何学Pythoneld registered
the object is immutable, but this fields leaves me some doubts because it will actually change on the first time the Register
method is executed... Can anyone please tell me how can I solve this problem and still make the object be immutable?
No, it's definitely not immutable. The registered
value changes over the lifetime of the object.
To make it immutable, you mustn't allow the registered
field to change over the lifetime of the object - instead, make Register
return a new object which has a true
value for registered
I'd also remove the private setter for SomeProperty
, just having a getter and a readonly variable.
So something like this:
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;
}
}
Some notes:
- Another option would be to have two separate classes,
RegisteredFoo
andUnregisteredFoo
; that might make it easier to understand code using this class - There's nothing to stop someone calling
Register
twice, so making this immutable doesn't really help in terms of idempotency. As there's a natural side-effect (talking to the database) it's hard to make this truly functional.
精彩评论