¿Imposible utilizar ref y out para el primer parámetro (“this”) en los métodos de extensión?

¿Por qué está prohibido llamar al Extension Method con el modificador de ref ?

Este es posible:

 public static void Change(ref TestClass testClass, TestClass testClass2) { testClass = testClass2; } 

Y este no:

 public static void ChangeWithExtensionMethod(this ref TestClass testClass, TestClass testClass2) { testClass = testClass2; } 

¿Pero por qué?

ref especificar ref y out explícitamente. ¿Cómo harías esto con un método de extensión ? Por otra parte, ¿realmente quieres ?

 TestClass x = new TestClass(); (ref x).ChangeWithExtensionMethod(otherTestClass); // And now x has changed? 

¿O no desea tener que especificar la parte de ref , solo para el primer parámetro en los métodos de extensión?

Simplemente me suena raro, para ser sincero, y una receta para código ilegible (o al menos difícil de predecir).

Estoy de acuerdo con las respuestas de Jon Skeet et al. acerca de cómo permitir métodos de extensión “ref. this” podría hacer que el código sea más oscuro. Pero si observa algunos espacios de nombres en .Net Framework, es común que un método invocado en una estructura lo altere.

Tomemos, por ejemplo, las estructuras del Sistema. Dibujar (Punto, Rectángulo, etc.). Cada uno de estos tiene métodos (por ejemplo, Offset, Inflate, etc.) que mutan la estructura en sí. No estoy diciendo que esto sea una buena idea, de hecho personalmente encuentro muy molesto que Offset, Inflate, etc. muten las estructuras mismas en lugar de devolver las nuevas, y sé que algunos de ustedes se oponen a la idea de estructuras mutables en general.

Dudo que haya ningún caso en el que invocar un método de un tipo de referencia cambie la referencia (a menos que sea con la clase String , donde puedo imaginar que podría haber alguna magia del comstackdor para cambiar las referencias para realizar prácticas, etc.). Por lo tanto, tiene sentido evitar que “esta referencia” se use con tipos de referencia, ya que cambiar una referencia sería un efecto secundario completamente no estándar de llamar a un método.

Pero en lo que respecta a las estructuras, permitir “este ref” no disminuiría significativamente la legibilidad del código más que Rectangle.Inflate, etc, y proporcionaría el único medio para “simular” ese tipo de comportamiento con una función de extensión.

Solo como una nota al margen, aquí hay un ejemplo en el que “esta referencia” podría ser útil, y en mi humilde opinión todavía legible:

 void SwapWith(this ref T x, ref T y) { T tmp = x; x = y; y = tmp; } 

Estoy de acuerdo que es útil para struct

Entonces quiero proponer eso para hacer un método de extensión para struct. esta palabra clave siempre debe pasar struct por referencia

clase siempre pasa por referencia de todos modos. Y cada vez que creamos un método de extensión queremos que se comporte como un método real. Entonces el método real de clase y estructura puede modificar su valor. El método de extensión debería poder también

Esto significaría que llamar a myObject.ChangeWithExtentionMethod(otherObject) realmente tendría el potencial de cambiar el valor de myObject.ChangeWithExtentionMethod(otherObject) . IMO, eso no daría lugar a un código muy legible cuando, en cambio, se puede lograr el efecto deseado utilizando un método regular sin extensión con una referencia.

EDITAR: Mi punto es que la llamada al método debería requerir que use la palabra clave ref en cualquier momento en que esté pasando algo por referencia. Usar ref con el parámetro ‘this’ de este método de extensión violaría ese comportamiento.