2010-04-11 14 views
21

¿Por qué está prohibido llamar al Extension Method con el modificador ref?¿Imposible utilizar ref y out para el primer parámetro ("this") en los métodos de extensión?

Éste es posible:

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

Y esto no uno:

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

Pero por qué?

+1

¿Está seguro de que es necesario un 'ref' explícito? Esperaría que sea "autogenerado" por 'this': los métodos de extensión sin referencia no tendrían ningún sentido. –

+0

Pero no son referencias si no me equivoco. – Hun1Ahpu

+0

Los parámetros @MarcelJackwerth ref no son lo mismo que los parámetros de tipo de referencia. Un parámetro ref pasa la referencia (o puntero) de la persona que llama. Con ref, puede actualizar la referencia para señalar a otro objeto. Sin él (para los tipos de referencia) puede actualizar el objeto en sí, pero no la referencia a él. – xr280xr

Respuesta

19

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

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

O le gustaría no tener que especificar la parte ref, sólo para el primer parámetro en los métodos de extensión?

Suena extraño, para ser sincero, y una receta para código ilegible (o al menos difícil de predecir).

+2

Pero esa razón ya no se aplica para C# 4. De hecho, en VB usted * puede * ya utilizar métodos de extensión 'ByRef', si no recuerdo mal. –

+3

"Tiene que especificar ... explícitamente" es un requisito del compilador artificial que podría soltarse aquí. Eso lo haría aún más oscuro sin embargo. –

+0

@Konrad: solo no se aplica en C# 4 para los métodos COM. @Henk: Sí, es 'artificial', pero en aras de la legibilidad. Creo que es una restricción completamente razonable. –

1

Esto significa que llamar al myObject.ChangeWithExtentionMethod(otherObject) realmente podría cambiar el valor de myObject. 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 debe requerir el uso de la palabra clave ref cada vez que se pasa algo por referencia. Usar ref con el parámetro 'this' de este método de extensión violaría ese comportamiento.

4

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.

Tome, por ejemplo, las estructuras del Sistema.Dibujo (Punto, Rectángulo, etc.). Cada uno de estos tiene métodos (por ejemplo, desplazamiento, inflado, 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 donde invocar un método de un tipo de referencia cambiará la referencia (a menos que sea con la clase String, donde puedo imaginar que podría haber algún compilador mágico para cambiar las referencias para realizar el interinato, 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 "esta referencia" 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.

Así como una nota lateral, aquí es un ejemplo en el "presente ref" podría ser útiles, y en mi humilde opinión sigue siendo legible:

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

estoy de acuerdo que útil para la estructura

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

class siempre pasan 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 ser también

Cuestiones relacionadas