2010-01-08 9 views
25

Estoy intentando crear un delegado de un método estático que toma un argumento de ref. Por favor, no preguntes por qué estoy haciendo una cosa tan cacarea. Todo es parte de aprender cómo funciona .Net, C# y la reflexión y cómo optimizarla.Delegado para una acción < ref T1, T2>

Mi código es:

public struct DataRow 
    { 

     private double t; 
     static public void Cram_T(ref DataRow dr, double a_t) 
     { 
      dr.t = a_t; 
     } 
    } 
'''' 
    Type myType = typeof(DataRow); 
    MethodInfo my_Cram_T_Method = myType.GetMethod("Cram_T"); 
    var myCram_T_Delegate = 
     Delegate.CreateDelegate(typeof(Action<DataRow, Double>),  
           my_Cram_T_Method) 
           as Action<DataRow, Double>; 

Esto me da un error porque la unión (creo) la acción genérica no coincide con el método.

Inspeccionar el valor de Cram_T_Method en la ventana de inspección da

{Void Cram_T(DataRow ByRef, Double)} 

entonces he intentado usar la palabra clave ref en la Acción:

var myCram_T_Delegate = 
     Delegate.CreateDelegate(typeof(Action<ref DataRow, Double>),   
           my_Cram_T_Method) 
           as Action<ref DataRow, Double>; 

Pero esto no se compilará. El compilador C# se ahoga en el token "ref".

¿Cuál es la forma correcta de crear este delegado?

Respuesta

33

Crear su propio tipo de delegado:

delegate void MyAction(ref DataRow dataRow, double doubleValue); 

y el uso MyAction en lugar de Action<ref DataRow, Double> - que, como se ha señalado, no se compila.

+0

que trae limitaciones al método interno s. – Bitterblue

21

@Ben M tiene la idea correcta, aunque se podría hacer que sea más genérico:

public delegate void RefAction<T1, T2>(ref T1 arg1, T2 arg2) 

El problema no tiene nada que ver con los delegados como tal - es sólo que no se puede utilizar cuando se especifica ref un tipo de argumento.

En teoría, "es por ref o no" es parte de la información de tipo (de ahí Type.IsByRef) pero no se puede especificar así.

Francamente no estoy del todo seguro de lo que sucedería si se trató de crear un List<ref int> través de la reflexión, por ejemplo - Me esperanza de que una excepción sería arrojado ... no es un concepto muy sensible :)

EDIT: acabo probé:

Type refInt = typeof(int).MakeByRefType(); 
Type refIntList = typeof(List<>).MakeGenericType(refInt); 

genera un error:

Unhandled Exception: System.ArgumentException: The type 'System.Int32&' may 
not be used as a type argument. 
+4

Los argumentos de tipo deben ser tipos cuyos valores sean convertibles en objeto. Los tipos de punteros administrados y no administrados no cumplen con ese requisito. –

+1

Bueno, yo nunca. Fascinante. Por una vez, * no * creo que valdrá la pena incluir eso en C# en profundidad. Tal vez como una nota ... –

+0

Esto funciona, pero el comentario de la lista es irrelevante. public delegate void RefGenAction (ref T1 arg1, T2 arg2); var myCram_TDelegate = Delegate.CreateDelegate (typeof (RefGenAction ), myType.GetMethod ("Cram_T")) como RefGenAction ; –

Cuestiones relacionadas