varios - no dejar escribir en un textbox c#
El método impuro se llama para el campo de solo lectura (5)
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 un 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 externalidades como la hora del día o los bits en 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 elegir mutar el estado privado por eficiencia, pero un método puro no cambia, digamos, 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 cambia por 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 vienen a la mente. El primero es el señalado por Jon, Michael y Jared, y este es el que Resharper te está advirtiendo. Cuando llamamos 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é ocurre si llamas a dicho método por un valor, en lugar de una variable? En ese caso, hacemos 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. Así que estamos copiando la variable a otra variable, y el método impuro posiblemente está mutando la copia, cuando pretendes mutar la variable.
Ese es el peligro de pasar una estructura de solo lectura como un receptor . También existe el peligro de pasar una estructura que contenga un campo de solo lectura. Una estructura que contiene un campo de solo lectura es una práctica común, pero básicamente está escribiendo una verificación de que el sistema de tipo no tiene los fondos para cobrar; el propietario del almacenamiento determina la "capacidad de solo lectura" de una variable en particular. Una instancia de un tipo de referencia "posee" su propio almacenamiento, pero una instancia de un tipo de valor no lo hace.
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);
// This should be the same, right?
Console.WriteLine(this.x);
}
}
Uno piensa que 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 s
refieren a la misma variable, ¡y esa variable no es solo de lectura!
Estoy usando Visual Studio 2010 + Resharper y muestra una advertencia en el siguiente código:
if (rect.Contains(point))
{
...
}
rect
es un campo readonly Rectangle
, y Resharper me muestra esta advertencia:
"El método Impure se llama para el campo de solo lectura del tipo de valor".
¿Qué son los métodos impuros y por qué se me muestra esta advertencia?
La respuesta corta es que este es un falso positivo, y puede ignorar la advertencia de forma segura.
La respuesta más larga es que al acceder a un tipo de valor de solo lectura se crea una copia , de modo que cualquier cambio en el valor realizado por un método solo afectaría a la copia. ReSharper no se da cuenta de que Contains
es un método puro (lo que significa que no tiene efectos secundarios). Eric Lippert habla de ello aquí: Mutating Readonly Structs
Parece que Reshaprer cree que el método Contains
puede mutar el valor rect
. Como rect
es una readonly struct
el compilador de C # hace copias defensivas del valor para evitar que el método mute un campo de readonly
. Esencialmente, el código final se ve así
Rectangle temp = rect;
if (temp.Contains(point)) {
...
}
Resharper te está advirtiendo aquí que Contains
puede mutar el rect
de una manera que se perdería inmediatamente porque ocurrió de manera temporal.
Un método Impure es un método que podría tener efectos secundarios. En este caso, Resharper parece pensar que podría cambiar rect
. Probablemente no, pero la cadena de evidencia está rota.
Un método impuro es aquel que no garantiza que deje el valor tal como estaba.
En .NET 4 puede decorar métodos y tipos con [Pure]
para declarar que son puros, y R # lo notará. Desafortunadamente, no se puede aplicar a los miembros de otra persona, y no se puede convencer a R # de que un tipo / miembro es puro en un proyecto .NET 3.5 por lo que sé. (Esto me muerde en Noda Time todo el tiempo).
La idea es que si estás llamando a un método que muta una variable, pero lo llamas en un campo de solo lectura, probablemente no esté haciendo lo que deseas, por lo que R # te advertirá sobre esto. Por ejemplo:
public struct Nasty
{
public int value;
public void SetValue()
{
value = 10;
}
}
class Test
{
static readonly Nasty first;
static Nasty second;
static void Main()
{
first.SetValue();
second.SetValue();
Console.WriteLine(first.value); // 0
Console.WriteLine(second.value); // 10
}
}
Esta sería una advertencia muy útil si cada método que en realidad era puro se declarara de esa manera. Desafortunadamente no lo son, entonces hay muchos falsos positivos :(