En primer lugar, las respuestas de Jon, Michael y Jared son esencialmente correctas, pero tengo algunas cosas más que me gustaría agregarles.
¿Qué se entiende por método "impuro"?
Es más fácil caracterizar métodos puros. Un método "puro" tiene las siguientes características:
- Su salida está completamente determinada por su entrada; su salida no depende de factores externos como la hora del día o los bits de su disco duro. Su salida no depende de su historia; llamar al método con un argumento dado dos veces debería dar el mismo resultado.
- Un método puro no produce mutaciones observables en el mundo que lo rodea. Un método puro puede optar por mutar un estado privado en aras de la eficiencia, pero un método puro no, por ejemplo, muta un campo de su argumento.
Por ejemplo, Math.Cos
es un método puro. Su salida depende solo de su entrada y la entrada no se modifica con la llamada.
Un método impuro es un método que no es puro.
¿Cuáles son algunos de los peligros de pasar estructuras de solo lectura a métodos impuros?
Hay dos que me vienen a la mente. El primero es el señalado por Jon, Michael y Jared, y este es el que te advierte Resharper. Cuando llama a un método en una estructura, siempre pasamos una referencia a la variable que es el receptor, en caso de que el método desee mutar la variable.
Entonces, ¿qué pasa si llama a un método de este tipo en un valor, en lugar de una variable? En ese caso, creamos una variable temporal, copiamos el valor en ella y pasamos una referencia a la variable.
Una variable de solo lectura se considera un valor porque no se puede mutar fuera del constructor. Entonces, estamos copiando la variable a otra variable, y el método impuro posiblemente está mutando la copia, cuando usted tiene la intención de que mute la variable.
Ese es el peligro de pasar una estructura de solo lectura como receptor . También existe el peligro de pasar una estructura que contiene un campo de solo lectura. Una estructura que contiene un campo de solo lectura es una práctica común, pero esencialmente se trata de emitir un cheque que el sistema de tipos no tiene los fondos para cobrar; la "condición de sólo lectura" de una variable en particular la determina el propietario del almacenamiento. Una instancia de un tipo de referencia "posee" su propio almacenamiento, ¡pero una instancia de un tipo de valor no!
struct S
{
private readonly int x;
public S(int x) { this.x = x; }
public void Badness(ref S s)
{
Console.WriteLine(this.x);
s = new S(this.x + 1);
Console.WriteLine(this.x);
}
}
Uno piensa que eso this.x
no va a cambiar porque x es un campo de solo lectura y Badness
no es un constructor. Pero...
S s = new S(1);
s.Badness(ref s);
... demuestra claramente la falsedad de eso. this
y hacen s
referencia a la misma variable, ¡y esa variable no es de solo lectura!