有什么方法可以使C#中的不可变对象派生出一个可变对象?

时间:2009-11-19 21:52:08

标签: c# immutability mutable

我有兴趣创建一个具有无法修改的属性的不可变类,以及一个从中派生的可变类。这些对象将是表示数据库记录的简单数据对象,因此它们只具有属性的不可变值。

我的目标是让我的数据访问层正常创建对象的可变版本,方法是根据数据库值设置属性,但将这些对象的只读版本传递回应用程序。 (我很好,如果开发人员真的想要,代码可以显式地将不可变对象强制转换为可变对象。)

我可以这样做(这是一个单词吗?),使用getter和setter的方法,并为可变类提供一个公共的新setter:

public class ImmutableClient {
    private int _clientId;
    public int getClientId() { return _clientId; }
    protected void setClientId(int clientId) { _clientId = clientId; }
}

public class Client : ImmutableClient {
    public new void setClientId(int clientId) { base.setClientId(clientId); }
}

如果可能的话,我更喜欢使用自动属性 ​​- 它们在调试时更好。除此之外,我并不关心代码的外观,因为它只是来自代码生成器而且永远不会被看到。

有什么想法吗?

4 个答案:

答案 0 :(得分:3)

我会使用一个界面。有一个只读的接口返回给客户端,一个完全可写的类实现它,但只用在数据访问层。

interface IReadOnlyObject
{
    int Property { get; }
}

class DALObject : IReadOnlyObject
{
    public int Property { get; set; }
}

答案 1 :(得分:2)

您可以让数据层返回只读界面:

interface IClient
{
     int getClientId();
}

然后你不需要关心你的具体实现是否有一个setter - 你的调用者只会使用getter。

作为旁注 - 您的代码看起来更像Java而不是C#,所以我实际上会使用:

interface IClient
{
     int ClientId { get; }
}

答案 2 :(得分:0)

不可变意味着不可改变。当我看到一个类型是不可变的时,我知道我可以缓存它并多次操作它而不会改变它。可变状态使得这种假设毫无价值。

class Foo
{
    // I'm immutable
}

class Bar : Foo
{
    // I add mutable properties
}

...

void F(Foo foo)
{
    // foo is immutable - therefore Bar (mutable) *cannot* be derived from Foo.
}

答案 3 :(得分:0)

有一个基类,它不提供任何mutator但不提供不变性的承诺。有一个派生的不可变类和一个单独派生的可变类。所有类都应该有一个接受基类的构造函数,以及一个可重载/重载的“AsImmutable”属性,该属性将返回一个不可变派生类的对象,可以通过调用构造函数或(如果对象已经是不可变类)返回本身。