Delegate for an Action< ref>

2019-01-17 10:39发布

问题:

I'm trying to create a delegate of a static method which takes a ref argument. Please don't ask why I'm doing such a cockamamie thing. It's all part of learning how .Net, C#, and reflection work and how to optimize it.

My code is:

    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>;

This gives me a binding error because (I think) the generic action doesn't match the method.

Inspecting the value of Cram_T_Method in the watch window gives

{Void Cram_T(DataRow ByRef, Double)}

I then tried using the ref keyword in the Action:

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

But this won't compile. The C# compiler chokes at the token "ref".

What is the right way to create this delegate?

回答1:

Create your own delegate type:

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

And use MyAction in place of Action<ref DataRow, Double> -- which, as you've noted, doesn't compile.



回答2:

@Ben M has the right idea, although you could make it more generic:

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

The problem has nothing to do with delegates as such - it's just that you can't use ref when you specify a type argument.

In theory the "it's by ref or not" is part of the type information (hence Type.IsByRef) but you can't specify it like that.

Frankly I'm not at all sure what would happen if you tried to create a List<ref int> via reflection, for example - I would hope that an exception would be thrown... it's not a very sensible concept :)

EDIT: I've just tried it:

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

Throws an error:

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