Почему неизменяемые классы не запечатаны в C#

#c# #immutability

#c# #неизменяемость

Вопрос:

Я задаю вопрос относительно неизменяемого шаблона объекта и его реализации. Я не говорю о существующих классах в .Чистая библиотека, подобная String.

Я понимаю, что неизменяемые объекты — это объекты, которые после загрузки не могут быть изменены каким-либо внешним или внутренним компонентом. Что, если я получу неизменяемый класс, поскольку он не является запечатанным классом. Затем назначьте объект базовому классу и вызовите метод в базовом классе. Я эффективно изменил состояние базового неизменяемого класса, поскольку его состояние соответствует состоянию объекта производного класса.

 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

Комментарии:

1. Вам даже не нужно AnotherPerson здесь, вы просто переназначили ссылку, исходный объект не был изменен.

2. Вы ничего не изменили. Вы создали другой объект с другими данными.

3. Во-первых: неизменяемость — это скорее «хорошая практика», чем языковая конструкция. Второе: вы переназначаете переменную «me». Даже если вы использовали запечатанный класс, результаты были бы такими же.

4. DisplayName Свойство не является неизменяемым, объект string, на который он первоначально указывал , является неизменяемым

5. Возможно, вы захотите проверить эту ссылку, это оказалось полезным для меня, когда у меня возникли вопросы о неизменяемых объектах blogs.msdn.microsoft.com/ericlippert/2007/11/13 /…

Ответ №1:

Давайте забудем о недостатках вашего примера (в комментариях уже все сказано) и ответим на ваш вопрос: «Почему неизменяемые классы не запечатаны в C #».

Дело в том, что неизменяемость не является особенностью языка C #. Некоторые языки поддерживают неизменяемость как функцию (в этом случае ваша точка зрения будет действительной), но C # этого не делает. В конце концов, вы просто создаете неизменяемый класс из существующих универсальных функций. И, следовательно, могут возникнуть ограничения.

Кроме того, неизменяемость — это мера предосторожности, а не защита. Дело в том, чтобы никто не мог изменять данные с помощью «обычных» средств. Если кто-то действительно хочет изменить данные, он всегда может, например, с помощью отражения (или подклассов, как вы упомянули). Но если разработчик делает это, то он никоим образом не игнорирует, что он изменяет данные, которые должны быть доступны только для чтения, и мы можем предположить, что у него есть веская причина для этого. Цель неизменяемости состоит в том, чтобы помешать разработчику неосознанно выстрелить себе в ногу, а не заблокировать его.

Комментарии:

1. Спасибо за ответ.

Ответ №2:

Вы можете назначить только 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();
}
 

Комментарии:

1. Спасибо за ответ, я думал об этом, потому что я читал, что неизменяемые классы можно использовать для хранения данных конфигурации (web.config / app, config). Я обычно использую статические поля для этой цели, и мне было интересно, как я могу применить неизменяемые объекты в этом сценарии. В случае конфигурационных данных я даже не должен позволять им быть кем-либо модифицированными, они считываются один раз из конфигурации и все. Поэтому я считаю, что мое понимание было неправильным, и в моем сценарии я не могу применить шаблон неизменяемого объекта, как описано во всех руководствах.