web-dev-qa-db-ja.com

アクションのデリゲート<refT1、T2>

Ref引数を取る静的メソッドのデリゲートを作成しようとしています。なんでこんなコカマミなことをしているのか聞かないでください。これはすべて、.Net、C#、およびリフレクションがどのように機能し、それを最適化するかを学ぶことの一部です。

私のコードは:

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

(私が思うに)一般的なアクションがメソッドと一致しないため、これによりバインディングエラーが発生します。

ウォッチウィンドウでCram_T_Methodの値を調べると、

{Void Cram_T(DataRow ByRef, Double)}

次に、アクションでrefキーワードを使用してみました。

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

しかし、これはコンパイルされません。 C#コンパイラは、トークン「ref」でチョークします。

このデリゲートを作成する正しい方法は何ですか?

29
Max Yaffe

独自のデリゲートタイプを作成します。

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

そして、Action<ref DataRow, Double>の代わりにMyActionを使用します。これは、ご指摘のとおり、コンパイルされません。

39
Ben M

@Ben Mは正しい考えを持っていますが、もっと一般的にすることもできます。

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

この問題は、デリゲート自体とは何の関係もありません。型引数を指定するときにrefを使用できないだけです。

理論的には、「参照によるかどうか」は型情報の一部です(したがって、Type.IsByRef)が、そのように指定することはできません。

率直に言って、リフレクションを介してList<ref int>を作成しようとするとどうなるかはまったくわかりません。たとえば、-私は希望例外がスローされることを望んでいます...それは非常に賢明な概念:)

編集:私はそれを試しました:

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

エラーをスローします:

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