2009-09-30 7 views
5

Cuando el argumento formal de un método es de tipo 'objeto' es posible, a través de la herencia, que el argumento real sea cualquier tipo de objeto. Una vez dentro del método, el objeto se puede convertir al tipo esperado. Todo está bienObjetos, parámetros y la palabra clave ref en C#

Si, sin embargo, la firma del método tiene un argumento formal de 'objeto', usando la palabra clave ref es decir methodname (objeto ref), el compilador genera un error que indica que:

"El mejor método sobrecargado la altura de 'ByRefTest.Program.changeMeByRef (objeto ref)' tiene algunos argumentos no válidos "argumento '1': no ​​se puede convertir de 'ByRefTest.Person ref' a 'objeto ref'".

La diferencia entre usar o no utilizar el ref keword al pasar objetos como parámetros se explica muy bien en el blog de A. Friedman http://crazorsharp.blogspot.com/2009/07/passing-objects-using-ref-keywordwait.html, pero ¿por qué no es posible pasar un tipo personalizado como un argumento real cuando el ¿El argumento formal del tipo 'objeto' usa la palabra clave ref?

Como un ejemplo:

class Program 
{ 
    static void Main(string[] args) 
    { 
     Person p = new Person(); 

     changeMe(p); // compiles 
     changeMeByRef(ref p); // throws error 

     object pObject = (object)p; 
     changeMeByRef(ref pObject); // compiles 
    } 


    public static void changeMeByRef(ref object obj) 
    { 
     Person p = (Person)obj; 
    } 

    public static void changeMe(object obj) 
    { 
     Person p = (Person)obj; 

    } 
} 

public class Person 
{ 
} 

Gracias.

ps me acaba de cambiar la firma a:

public void changeMeByRef <T> (ref T obj) estática donde T: Persona

esta compila para changeMeByRef (ref p);

+0

Este es un duplicado de http://stackoverflow.com/questions/1207144/c-why-doesnt-ref-and-out-support-polymorphism/1207302#1207302 –

Respuesta

8

Porque el método puede cambiar el parámetro para que tenga un valor de tipo diferente, en violación del tipo de la variable utilizada para el argumento. Un simple ejemplo:

public void Foo(ref object x) 
{ 
    x = "hello"; 
} 

... 

// This doesn't compile, fortunately. 
Stream y = null; 
Foo(ref y); 

¿Cuál es el valor de y después de la asignación en el método? Debería ser una cadena, pero eso viola el tipo de la variable. Eso sería algo muy malo, que viola por completo la seguridad del tipo. Este es el mismo tipo de razón para la invarianza genérica de IList<T> incluso en .NET 4.0.

Eric Lippert recently blogged about the invariance of ref in more detail.

2

Porque el parámetro ref funciona en ambos sentidos. Puede asignar el parámetro a un objeto arbitrario dentro de su función, y el código de llamada debe manejarlo.

0

hacer esto. es más fácil.
changeMe (p); // compila
changeMeByRef (ref (Object) p); // esta vez no debería arrojar errores.

+0

@behrooz: ¿Usted intentó esto? No puedes lanzar un argumento de ref. –

Cuestiones relacionadas