Как узнать, является ли класс неизменяемым в C#?

StackOverflow https://stackoverflow.com/questions/481909

  •  20-08-2019
  •  | 
  •  

Вопрос

Как узнать, является ли класс неизменяемым в C#?

Это было полезно?

Решение

Есть ImmutableObjectAttribute, но это редко используется и плохо поддерживается - и, конечно, не применяется (вы можете пометить изменяемый объект с помощью [ImmutableObject(true)].AFAIK, единственное, на что это влияет, это то, как IDE обрабатывает атрибуты (т.показывать/не показывать параметры именованных свойств).

На самом деле вам придется проверить FieldInfo.IsInitOnly, но это применимо только к действительно 100% неизменяемым типам (при условии отсутствия злоупотребления отражением и т. д.);это не помогает ни с неизменяемостью эскимо, ни с вещами, которые неизменны на практике, но не в их реализации;то естьих нельзя сделать публично изменяемыми, но теоретически объект поддерживает это.

Классическим примером здесь может быть строка...все это "знают" string является неизменным...конечно, StringBuilder делает изменить строку под капотом.Нет, серьезно...

Учитывая это, так сложно определить неизменность, не говоря уже о том, чтобы надежно ее обнаружить...

Другие советы

Вы не можете, вы можете только предполагать.Если все поля доступны только для чтения, экземпляры станут неизменяемыми после завершения конструктора.Это важно: если бы у вас было следующее, оно выглядело бы изменчивым на панели экземпляра.

class Foo
{
    public readonly int X
    public readonly int Y
    public Foo(int x, int y, Bar bar)
    {
        this.X = x; 
        bar.ShowYourself(this);
        this.Y = y;
        bar.ShowYourself(this);
    }
}

Однако если поле предположительно неизменяемого класса представляло собой коллекцию (и не было доступно только для чтения), то вызов неизменяемого класса, скорее всего, был бы неправильным (поскольку его состояние может измениться).

Обратите внимание: даже если все поля доступны только для чтения, отражению разрешено изменять поля.

Проверка отсутствия установщиков свойств действительно будет очень плохой эвристикой.

Частично проблема в том, что слово «неизменяемый» может иметь несколько значений.Возьмем, к примеру, ReadOnlyCollection<T>.

Мы склонны считать его неизменным.Но что, если это ReadOnlyCollection<SomethingChangeable>?Кроме того, поскольку на самом деле это просто оболочка вокруг IList, который я передаю конструктору, что, если я изменю исходный IList?

Хорошим подходом может быть создание атрибута с именем типа ReadOnlyAttribute и пометка им классов, которые вы считаете доступными только для чтения.Для классов, которые вы не контролируете, вы также можете вести список известных типов, которые вы считаете неизменяемыми.

РЕДАКТИРОВАТЬ:Несколько хороших примеров различных типов неизменяемости можно найти в этой серии публикаций Эрика Липперта: http://blogs.msdn.com/ericlippert/archive/2007/11/13/immutability-in-c-part-one-kinds-of-immutability.aspx

Насколько мне известно, если это явно не задокументировано, в C# невозможно определить, является ли класс неизменяемым или нет.

Однако вы можете использовать Reflection для проверки наличия сеттеров в свойствах;однако отсутствие установщиков не гарантирует неизменности, поскольку внутреннее состояние может изменить значения этих свойств независимо от того, можете ли вы установить их явно или нет.

Кроме того, проверка флага IsInitOnly для всех полей класса, опять же с использованием Reflection, может указывать на неизменность, но не гарантирует ее.

Редактировать: Вот аналогичный вопрос, спросили о языке Java, ответ которого также применим и здесь.

Через код, я не уверен, но если вы посмотрите на IL другого неизменяемого типа, например строки, вы увидите нет см newobj IL (для строк вы увидите ldstr), возможно, проверка IL созданного объекта может быть одним из способов определить это, просто догадайтесь...

Единственная помощь, которую вы получите от среды выполнения, — это если все поля в классе будут помечены как «только для чтения».[Изменить, см. @ShuggyCoUk] И даже тогда CLR позволит вам писать поверх него.Я только что это проверил.Фу.

Вы можете получить объекты FieldInfo из класса посредством отражения и проверить IsInitOnly.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top