Tipos de datos inmutables en C#, ¿cuales son?.

596 views
Skip to first unread message

Nestor

unread,
Apr 11, 2014, 10:09:19 AM4/11/14
to altnet-...@googlegroups.com
Que tal amigos de AltNet hispano.

Aquí estoy tratando de entender el tema de la Inmutabilidad de los tipos de datos.

Yo se y es relativamente fácil entender que los tipos String son inmutables porque por ejemplo al hacer un Trim() sobre una variable del tipo String el método no cambia la instancia original sino QUE CREA UNO NUEVO y lo asigna a la variable.
string nombre = "  Inmutable  ";
nombre = nombre.Trim(); //Aquí sobrescribe la instancia original

Console.WriteLIne(nombre) //  la salida es "Inmutable"

Lo mismo ocurre con el tipo DateTime, aunque se que DateTime es un Struct mientras que String es un Class.

Ahora bien me surgen las siguientes preguntas.
  • ¿Cuales son los tipos Inmutables aparte de String y DateTime?
  • ¿Se pudiera decir que la mayoría de los tipos POR VALOR son inmutable? y si es así ¿Cuales específicamente? 
Desde ya gracias por su ayuda.

Atte.
Nestor 

Juan María Hernández

unread,
Apr 11, 2014, 11:38:10 AM4/11/14
to altnet-...@googlegroups.com
Hola Nestor,

La inmutabilidad de un tipo es un concepto ortogonal a si es un tipo por valor (struct) o por referencia (clase).

Un objeto es inmutable si y solo si no puede ser modificado después de su construcción.

Puedes tener una clase inmutable si todos sus atributos están marcados como readonly y son a su vez inmutables. Puedes tener structs mutables, como por ejemplo Point o Size (ambas definidas en System.Drawing).

Eso sí, tener structs mutables puede dar lugar a algunas situaciones confusas (http://blog.koalite.com/2012/02/curiosidades-con-structs-en-c/), así que mi consejo es que si vas a crear un struct (cosa que ya requiere una buena justificación), al menos la definas como inmutable.

Un saludo,

Juanma



--
Has recibido este mensaje porque estás suscrito al grupo "AltNet-Hispano" de Grupos de Google.
Para anular la suscripción a este grupo y dejar de recibir sus mensajes, envía un correo electrónico a altnet-hispan...@googlegroups.com.
Para publicar en este grupo, envía un correo electrónico a altnet-...@googlegroups.com.
Visita este grupo en http://groups.google.com/group/altnet-hispano.
Para acceder a más opciones, visita https://groups.google.com/d/optout.



--
Blog: http://blog.koalite.com



Gabriel Osorio

unread,
Apr 11, 2014, 11:47:32 AM4/11/14
to altnet-hispano
Hola Nestor

De la wikipedia: "Las Cadena de caracteres y otros objetos suelen ser expresados como objetos inmutables para mejorar su rendimiento en tiempo de ejecución en lenguajes de programación orientada a objetos".
Seguramente una razón similar llevó a definir DateTime como inmutable. La más obvia que se me ocurre es que es mejor obtener el tiempo del reloj del sistema a tratar de calcularlo por nuestra cuenta.

La alternativa mutable de los strings en puntonet es StringBuilder.

Para profundizar un poco.
Un string se define como una serie de posiciones de memoria consecutivas. La primera posición es guardada en un puntero y el tamaño se guarda como un offset, es decir, como la cantidad de espacio en memoria requerido.
Ampliar un string definido como así es muy costoso, pues la memoria adyacente puede estar ocupada. Para lograr esta ampliación, StringBuilder se comporta como un array de Strings, al que se le pueden agregar nuevos strings al final. Como los arrays también tienen la limitación de memoria de la clase String, cada vez que a StringBuilder se le acaban las posiciones pide nuevas usando Array.Realoc (no me acuerdo bien, estoy escribiendo de memoria), usualmente en pasos de 10.
Cuando se solicita el String resultante a StringBuilder, este hace un join del array, creando un String nuevo en memoria.

Por esas razones los strings son inmutables y no hay que abusar de ellos en OOP.

Espero haber sido útil.









--

Nestor

unread,
Apr 11, 2014, 4:49:01 PM4/11/14
to altnet-...@googlegroups.com
Gracias por sus respuestas, aunque no me queda del todo claro, voy a investigar los enlaces que me dieron a ver si logro captar.
Yo tenia la idea de que había un listado de los tipos que son inmutables, pero veo que no es así, se que los tipos String y DateTime son inmutables, pero que sucede con los int, long, float, bool, char son inmutables?

Desde ya gracias por su tiempo.

Atte.
Nestor

Carlos Peix

unread,
Apr 11, 2014, 7:06:14 PM4/11/14
to altnet-hispano
Hola Nestor,

DDD aporta una visión mas a las cuestiones tecnologicas. DDD define los value types (los objetos que se definen por su valor) y las entidades (los objetos que tienen identidad, independientemente de los valores que contengan).

El motivo por el cual los value types se hacen inmutables (obligatoriamente en diseño) es que, dado que es lo mismo que instancia tengas, mientras conserves el valor, entonces el valor de una instancia no puede cambiar nunca, por eso, se hace inmutable.

Ejemplo, si una persona pesa 70kg, no importa que instancia de int tengas, siempre y cuando su valor sea 70. Imaginate lo que pasaria si a esa instancia le cambias el valor a 75! el objeto que la referencia nunca se enteraria...

Que yo sepa no hay un listado de los objetos inmutables pero, si son subclases de struct, lo mas probable es que lo sean. String es un caso particular en el cual un reference type pero tiene algunas cuestiones. Ver el método Internalize (o algo asi).

La pregunta mágica es: ¿por qué queres saber esto con tantas ganas?

Un saludo

----------------------------------
Carlos Peix

Nestor Rodriguez

unread,
Apr 14, 2014, 11:30:37 AM4/14/14
to altnet-...@googlegroups.com

Lo que pasa es que estoy con .NET MVC hace ya como 3 años y estoy adentrándome al uso de Angularjs y actualmente estoy utilizando mini spa para realizar mis proyectos, pero como tengo metido en la cabeza de que nunca voy a ser un profesional de verdad “si no enseño” si no todo, la mayor parte de lo que se, me estoy preparando para ser profesor.

Por lo tanto comencé (de nuevo) aprendiendo minuciosamente C# y quiero llegar  saber todo lo fundamental y un poco más. Me doy cuenta (desde mi punto de vista) de que es cierto que el enseñar te hace más profesional. Ahora  leo las cosas con la idea de que otros me van a preguntar “cualquier cosa” por esa razón me preocupa aún más saberlo.

Es mi opinión puedo estar equivocado, no sé.

 

Atte.

Nestor

Alejandro Miralles

unread,
Apr 14, 2014, 11:37:33 AM4/14/14
to altnet-...@googlegroups.com

Muy buena la explicación de Carlos.

Fernando Pelliccioni

unread,
Apr 25, 2014, 8:09:26 PM4/25/14
to altnet-...@googlegroups.com
Hola Nestor,

Me parece que tengo una ayuda concreta a tu pregunta.

Lo mejor que pude encontrar está en los estándares ECMA-335 o ISO/IEC 23271


"Partition IV: Profiles and Libraries – Provides an overview of the CLI Libraries, and a 
specification of their factoring into Profiles and Libraries. A companion file, 
CLILibrary.xml, considered to be part of this Partition, but distributed in XML format, 
provides details of each class, value type, and interface in the CLI Libraries. "


El archivo que menciona "CLILibrary.xml" está dentro del Zip.

... y no se llama "CLILibrary.xml" sino "CLILibraryTypes.xml", pero bueh!

El contenido del Xml es difícil de leer, pero tenés toda la documentación estándar de la BCL. 
Si no me equivoco el último estándar es acorde al .Net Framework 2.0.

No sé si vas a encontrar lo que querés buscando por "immutable". Por ejemplo, en Datetime no dice nada de inmutabilidad, pero si en String.
Te recomiendo buscar variaciones de "safe for multithreaded".

Creo que con eso vas a poder armar tu lista.

Creo que si te bajas todo lo que está acá podés generar la documentación en un formato más legible.
No lo probé, pero si lo llegás a generar, compartilo porfa!


Con respecto a definiciones como Objects (nada que ver con OOP), Values, etc..., recomiendo leer la clasificación que hace Alexander Stepanov en su libro Elements of Programming.


Por último, comparto algunos pensamientos que suelo tener seguido... da para una interesante charla.
- Creo que la especificación de la BCL es *muy* pobre. 
- ¡Y pensar que la mayoría de los desarrolladores .Net confiamos en MSDN! No deja de ser una página web.

Un abrazo,
Fernando.

Nestor Rodriguez

unread,
Apr 28, 2014, 12:25:43 PM4/28/14
to altnet-...@googlegroups.com

Gracias voy a echarle una hojeada.

 

Atte.

Nestor

Julian Dominguez

unread,
Apr 28, 2014, 11:28:04 PM4/28/14
to altnet-...@googlegroups.com
Cabe destacar que para ciertas tareas parallelizables, evitar mutar objectos que otros threads pueden estar tocando, hace que necesites menos sincronización (como locks que pueden ser un cuello de botella).

En NuGet podés encontrar varias librerías con clases inmutables. Un ejemplo es Microsoft Immutable Collections. Similar al string, todos los métodos en estas clases son puros; es decir, no mutan estado, sino que devuelven una instancia con el estado que buscas, pero otros threads referenciando al objeto original pueden estar tranquilos que nadie les puede cambiar el objeto inadvertidamente.

Afortunadamente, como se pudo ver en la conferencia //Build, C# en el futuro va a traer mejoras para que crear objetos inmutables no sea tan dificil como es ahora. Hoy es muy fácil crear objetos mutables usando autoproperties, pero si querés que todo sea readonly, tenés que agregar muuuchas lineas de código, especialmente si querés seguir algo como la clase string, en el que expones formas de devolver un objeto que es casi un clon del otro, pero con alguna propiedad cambiada.

Saludos,
Julian

Carlos Peix

unread,
Apr 29, 2014, 10:18:46 AM4/29/14
to altnet-hispano
A lo que dice Julian agrego: otra opción a usar autoproperties es diseñar tus objetos de manera que no expongan libremente su estado y decidir que es lo que haces en los métodos (tell, don't ask).

En ese caso es trivial hacer que el método devuelva otro objeto en lugar de mutar el actual.

En otras palabras, creo que evitar objetos mutables con otra sintaxis mágica de manera que puedas tener auto-properties read-only (si esa fuera la solución) es seguir pateando la pelota (del diseño orientado a objetos) afuera de la cancha.

(disculpas Julian por el rant sobre tu respuesta, no estoy respondiendo solo a vos :-))

----------------------------------
Carlos Peix

Julian Dominguez

unread,
May 1, 2014, 1:44:59 PM5/1/14
to altnet-...@googlegroups.com
Carlos, no es problema, no lo tomo como una crítica a mi... es una oportunidad de discutir ideas :)

Estoy de acuerdo en usar "tell, don't ask" cuando es posible, especialmente cuando tus clases representan funcionalidad (de hecho últimamente estoy haciendo muchas cosas en Project Orleans, que es un actor model distribuido, por lo que sería imposible preguntar por el estado de otro actor cada vez).
Sin embargo, estos objetos con behavior, se tienen que comunicar pasandose "datos" (mensajes). Estos datos (y otros value objects) son los que en mi opinión deberíamos apuntar a hacer inmutables, ya que son los que se comparten. La sintaxis "mágica" de la que hablo es justamente para que devolver un objeto nuevo (inmutable) actualizado sea muy fácil de hacer. Entonces podés usar el data object como quieras, actualizarlo (pero sin mutar el objeto original por si alguien lo está usando), y pasarlo a otros threads o serializarlo y mandarlo a otro proceso remoto.

Si lo que proponés es que todo objeto que encapsula funcionalidad también sea inmutable, creo que es un poco extremo para hacerlo en c#, para eso usá algun lenguaje funcional como F#. En c# el solo hecho de no tener tail recursion te limitaría en seguida (o al menos eso creo en base a mis limitados intentos de seguir esa filosofía hace unos años), y ni hablar de que si bien se puede y c# es considerado multiparadigma, igual es luchar un poco contra el paradigma principal del lenguaje. Nuevamente, "tell don't ask" me parece perfecto usar, pero es completamente ortogonal a la discusión sobre la sintaxis para inmutabilidad.

Saludos,
Julian

Angel Java Lopez

unread,
May 1, 2014, 1:50:49 PM5/1/14
to altnet-...@googlegroups.com
Perdon, vi luz y subi....

Jajaja.... lo mas parecido a Aktores que vi en mi vida ;-)

Nos leemos!

Angel "Java" Lopez
@ajlopez

Carlos Peix

unread,
May 1, 2014, 2:31:11 PM5/1/14
to altnet-hispano
Hola Julian,

No propongo que todos los objetos sean inmutables. Solo me pareció que agregaba valor decir que no es tan dificil hacer un objeto inmutable, ni siquiera en C# 1.0.

Quería contrarrestar la tendencia (de la cual se que no sos cultor) de pensar que las autoproperties son la salvación. En otras palabras, hacer un objeto inmutable es dificil si usas autoproperties. Si solo usas getters y backing fields no lo es.

Sacar un objeto inmutable, tampoco es dificil con un constructor (cosa rara hoy en día entre los cultores de las autoproperties), algo asi:

public DateRange Intersect(DateRange dr) {
   return new DateRange(...); // los backing fields se setean en el constructor...
}

Estoy seguro de que estamos de acuerdo en todo, solo quise aclarar, remar un poco contra la corriente :-)

----------------------------------
Carlos Peix

Julian Dominguez

unread,
May 1, 2014, 3:11:45 PM5/1/14
to altnet-...@googlegroups.com
100% de acuerdo, y justamente las auto-properties van un poco en contra de objetos inmutables. Como decís, hoy en c# se puede crear objetos inmutables, pero ya de por si es muy verbose (tenés que escribir muchas lineas de código, en algo que en F# te llevaría 1 por ejemplo).
Sí, tenés que escribir el backing field, la property con el getter solo, y el constructor que reciba el parámetro y lo asigne al field. Ya eso de por si son muchas cosas innecesarias, siendo que es muy straightforward lo que estás queriendo escribir. La sintaxis "mágica" que proponen en C# vNext es hacer justamente lo mismo, pero con una sintaxis muy reducida (pero mismo output a nivel de la clase generada en IL, es solo syntactic sugar).
Después ni hablar lo verbose que se hace a la hora de empezar a agregar metodos que devuelve un clon del original pero con una property actualizada. F# sigue siendo muy superior ahi.

Carlos Peix

unread,
May 1, 2014, 5:45:46 PM5/1/14
to altnet-hispano
Bien Julian, convergemos al acuerdo absoluto entonces :-)

De todas formas dejo el mensaje, de puro terco nomas: no nos acostumbremos a las autoproperties, brindan acceso a detalles de implementación de los objetos, lo cual aumenta el acoplamiento, en general el setter sale automático aunque no sea necesario, atentando contra el acoplamiento, dificultan el mantenimiento de la integridad del objeto, etc.

Todo lo anterior, es para objetos del dominio, con logica. Quedan fuera de ese consejo los DTOs, objetos commands, view models y demás objetos periféricos o de frontera (de nuestro dominio).

#ListoLoDijeUnaVezMas :-)

Abrazo

----------------------------------
Carlos Peix

Carlos Admirador

unread,
May 10, 2014, 10:10:48 AM5/10/14
to altnet-...@googlegroups.com

Cuál es la conclusión con los objetos inmutables?

Las ventajas sólo es para paralelismo , threading y evitar acoplamiento (por eso huir de auto-properties, métodos setter) ?

Mutable o inmutables, hay alguna consideración en performance-rendimiento de aplicaciones?

Saludos.
Carlos.

Carlos Admirador

unread,
May 18, 2021, 4:48:41 AMMay 18
to AltNet-Hispano
Es eso lo que mejorar el tipo Record de C# 9 ?
Reply all
Reply to author
Forward
0 new messages