Pregunta

¿Cómo puedo saber si una clase es inmutable en C #?

¿Fue útil?

Solución

Hay ImmutableObjectAttribute, pero esto rara vez se usa y es poco compatible, y por supuesto no se aplica (podría marcar un objeto mutable con [ImmutableObject(true)]. AFAIK, lo único que esto afecta es la forma en que el IDE maneja los atributos (es decir, mostrar / no mostrar las opciones de propiedades con nombre).

En realidad, tendría que verificar FieldInfo.IsInitOnly, pero esto solo se aplica a tipos verdaderamente 100% inmutables (suponiendo que no haya abuso de reflejos, etc.); no ayuda con la inmutabilidad de paletas, ni con cosas que son inmutables en la práctica, pero no en su implementación; es decir, no se puede hacer que sean mutables públicamente, pero en teoría el objeto lo admite.

Un ejemplo clásico aquí sería una cadena ... todos & "; saben &"; que string es inmutable ... por supuesto, StringBuilder muta una cadena debajo del capó. No, en serio ...

Es muy difícil definir la inmutabilidad dado esto, y mucho menos detectarlo de forma robusta ...

Otros consejos

No puedes, solo puedes adivinar. Si todos los campos son de solo lectura, las instancias serán inmutables una vez que finalice el constructor. Esto es importante, si tuviera lo siguiente, parecería mutable a la barra de instancia.

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);
    }
}

Sin embargo, si un campo en la clase supuestamente inmutable era una colección (y no era de solo lectura), llamar a la clase inmutable probablemente sería incorrecto (ya que su estado puede cambiar)

Tenga en cuenta que incluso si todos los campos son de solo lectura, la reflexión puede modificar los campos.

Comprobar si no hay definidores en las propiedades será una heurística muy pobre.

Parte del problema es que " inmutable " puede tener múltiples significados. Tomemos, por ejemplo, ReadOnlyCollection & Lt; T & Gt ;.

Tendemos a considerar que es inmutable. Pero, ¿y si es una ReadOnlyCollection & Lt; SomethingChangeable & Gt ;? Además, dado que en realidad es solo una envoltura alrededor de una IList que paso al constructor, ¿qué pasa si cambio la IList original?

Un buen enfoque podría ser crear un atributo con un nombre como ReadOnlyAttribute y marcar las clases que considere de solo lectura. Para las clases que no controlas, también puedes mantener una lista de tipos conocidos que consideras inmutables.

EDITAR: Para algunos buenos ejemplos de diferentes tipos de inmutabilidad, lea esta serie de publicaciones de Eric Lippert: http://blogs.msdn.com/ericlippert/archive/2007/11/13/immutability-in-c- parte-uno-tipos-de-inmutabilidad.aspx

Que yo sepa, a menos que esté explícitamente documentado, no hay forma de determinar si una clase es inmutable o no en C #.

Sin embargo, puede usar Reflection para verificar la existencia de Setters en las propiedades; sin embargo, la falta de establecedores no garantiza la inmutabilidad ya que el estado interno puede cambiar los valores de estas propiedades, ya sea que pueda establecerlas explícitamente o no.

Además, verificar el indicador 'IsInitOnly' para todos los campos de la clase, nuevamente usando Reflection, puede indicar inmutabilidad, pero no lo garantiza.

Editar: Aquí hay una pregunta similar , con respecto a el lenguaje Java, cuya respuesta también se aplica aquí.

A través del código, no estoy seguro, pero afaik si observa el IL de otro tipo inmutable, como una cadena, no verá una instrucción newobj IL (verá ver ldstr para cadenas), quizás inspeccionar el IL de la creación puede ser una forma de saberlo, solo una suposición ...

La única ayuda que puede obtener del tiempo de ejecución es si todos los campos de la clase están anotados con " readonly " ;. [Editar, vea @ShuggyCoUk] Y aun así, el CLR le permitirá escribir sobre él. Lo acabo de verificar. Ugh.

Puede obtener los objetos FieldInfo de la clase a través de la reflexión y verificar IsInitOnly.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top