为什么不可变类在C#中没有被密封

时间:2016-10-16 12:56:59

标签: c# immutability

我问的是关于不可变对象模式的问题并实现它。我不是在谈论像.Net这样的.Net库中的现有类。

我理解不可变对象是一旦加载的对象,任何外部或内部组件都无法修改。如果我派生出不可变类,因为它不是密封类,该怎么办?然后将对象分配给基类,并调用基类中的方法。我已经有效地改变了基本不可变类的状态,因为它的状态是派生类对象的状态。

public class Person
{
    private readonly string name;

    public Person(string myName)
    {
        this.name = myName;
    }

    public string Name
    {
        get { return this.name; }
    }

    public void DisplayName()
    {
        Console.WriteLine(string.Format("Person's name is {0}", this.name));
    }
}

public class AnotherPerson : Person
{
    private string name1;

    public AnotherPerson (string myName) : base(myName)
    {
        this.name1 = myName;
    }
}

class Program
{
    static void Main(string[] args)
    {
        Person me = new Prasanth("MyName");
        me.DisplayName();
        me = new AnotherPerson("AnotherName"); ;
        me.DisplayName();
        Console.ReadLine();
    }
}

输出:

人名是MyName

人名是AnotherName

2 个答案:

答案 0 :(得分:5)

让我们忘记你的例子中的缺陷(评论已经说明了一切)并回答你的问题:"为什么不可变类没有用C#封装。"

问题在于,不变性不是C#语言的一个特征。有些语言支持不可变性作为一个特性(在这种情况下,你的观点是有效的),但C#并不是。最后,您只是使用现有的通用功能构建不可变类。因此,可能会出现限制。

此外,不变性是一种预防措施,而非保护措施。关键是要防止任何人通过"正常"来改变数据。手段。如果有人真的想要更改数据,他们总是可以,例如通过反射(或如你所提到的子分类)。但是如果开发人员这样做,那么他就不会忽视他应该是只读的变异数据,我们可以假设他有充分的理由这样做。不变性的目的是防止开发人员在不知不觉中将自己射入脚中,而不是将他锁定。

答案 1 :(得分:0)

您只能分配readonly string name一次。我目前还不确定这是否只能在构造函数中使用。

您在第一次运行"MyName"中分配它,在第二次运行中,您将"AnotherName"分配给使用new AnotherPerson(...)

创建的完全不同的对象
static void Main(string[] args)
{
    Person me = new Prasanth("MyName");
    me.DisplayName();
    // vvvvvv   here you lose the reference to the old object
    me = new AnotherPerson("AnotherName"); ;
    me.DisplayName();
    Console.ReadLine();
}