¿Por qué resharper sugiere "envolver la variable en la matriz" para acceder a las advertencias de cierre modificadas?
closures (2)
Esto es porque los 2 tipos son diferentes. La int es un tipo de valor y la matriz es un tipo de referencia. Esto significa que el int está en la pila y el puntero de la matriz está en la pila.
Cuando actualiza un tipo de Valor, actualiza esa parte de la memoria de pila. El tipo de referencia, por otro lado, deja solo ese pedazo de memoria de pila y modifica a qué apunta.
Resharper no se queja sobre la matriz porque los 2 métodos Lambda diferentes están creando un cierre alrededor de la memoria que apunta a dónde actualizar un valor. Ambos Lambdas obtienen la misma dirección y no cambian el original.
Dado el siguiente código (muy editado, pseudo-):
int count = 0;
thing.Stub(m => m.AddBlah()).WhenCalled(o => count++);
thing.Stub(m => m.RemoveBlah()).WhenCalled(o => count--);
DoStuff(thing);
Assert.AreEqual(1, count);
ReSharper proporciona una advertencia en el recuento: "Acceso al cierre modificado". Entiendo por qué recibo esta advertencia (la variable de conteo se está modificando en dos lambdas diferentes, y es probable que tenga una semántica no deseada), pero no entiendo el consejo de ReSharper: "Ajustar la variable local en una matriz". Si dejo que ReSharper haga esto, obtengo:
int count[] = { 0 };
thing.Stub(m => m.AddBlah()).WhenCalled(o => count[0]++);
thing.Stub(m => m.RemoveBlah()).WhenCalled(o => count[0]--);
DoStuff(thing);
Assert.AreEqual(1, count[0]);
Y ninguna advertencia.
¿Por qué es seguro usar una matriz?
Noté lo mismo en ReSharper, y también me pregunté por qué no avisa cuando el valor está envuelto en una matriz. La otra respuesta aquí es desafortunadamente errónea, y parece malinterpretar cómo se implementan los cierres, así que pensé que intentaría explicar (lo que creo que es) la razón detrás de esta refactorización.
Como ha visto, el resultado es el mismo, ya sea envuelto en matriz o no, por lo que la refactorización no "arregla" realmente nada y los mismos problemas que pueden surgir al acceder a un cierre modificado ordinario existen después de aplicar el cambio. Sin embargo, después del cambio, ya que la matriz de count
sí no se está modificando (solo su contenido), la advertencia "Acceso al cierre modificado" ya no es relevante.
El cambio realmente no hace que el problema sea más obvio (al menos en mi opinión), por lo que parece que esta sugerencia esencialmente le dice a ReSharper que ignore el problema, sin tener que recurrir al bastante desordenado // ReSharper disable AccessToModifiedClosure
Mecanismo para suprimir el error.