3

私はジェネリッククラスを持っています:

public class MyList<LinkedItem> : List<LinkedItem> where LinkedItem : MyItem, new()
{
}

そのジェネリック クラスから、MyItem クラスの子孫である LinkedItem クラスから静的関数にアクセスしたいと思います。(したがって、LinkedItem のインスタンスを作成せずに)。

出来ますか?

ありがとうございました、

エリック

4

6 に答える 6

2

それは反射を通して行うことができます。C#には静的メンバーに対するAPI制約がないため、これを行う簡単な方法はありません。

現在のシナリオはわかりませんが、ほとんどの場合、これは推奨される解決策ではありません:)

public class MyList<LinkedItem> : List<LinkedItem> 
                                      where LinkedItem : MyItem, new()
{
    public int CallStaticMethod()
    {
        // Getting a static method named "M" from runtime type of LinkedItem 
        var methodInfo = typeof(LinkedItem)
                      .GetMethod("M", BindingFlags.Static | BindingFlags.Public);

        // Invoking the static method, if the actual method will expect arguments
        // they'll be passed in the array instead of empty array
        return (int) methodInfo.Invoke(null, new object[0]);
    }

}

public class MyItem
{
}

class MyItemImpl : MyItem
{
    public MyItemImpl()
    {
    }

    public static int M()
    {
        return 100;
    }
}

したがって、たとえば次のコードは次のように出力します100

public void Test()
{
    Console.WriteLine(new MyList<MyItemImpl>().CallStaticMethod());
}
于 2010-08-16T17:28:19.620 に答える
2

はい、可能ですが、リフレクションを使用して MethodInfo を取得しtypeof(T).GetMethod("Foo", BindingFlags.Public | BindingFlags.Static)、それを呼び出すInvoke必要があります。

特に MethodInfo ではなく ConstructorInfo で同じ手法を使用する場合、コンストラクターでパラメーターを使用するジェネリック ファクトリを作成すると非常に便利です。とはいえ、控えめに使うものです。特に、問題の型が必要な署名の静的メソッドを持っていることをコンパイル時に保証する方法がないため、型の安全性がなくなり、そのようなエラーは実行時までキャッチされません。

于 2010-08-16T17:33:31.327 に答える
2

いいえ、ジェネリック型パラメーターで静的メソッドを呼び出すことができないため、型パラメーターから直接これを行うことはできません (C# Lang Spec セクション 4.5)。

静的メンバーまたはネストされた型を識別するために、型パラメーターをメンバー アクセス (§7.5.4) または型名 (§3.8) で使用することはできません。

はい、他の人が指摘したように、これはリフレクション トリックを介して達成することが可能です。しかし、一般的に言えば、単純なメソッド呼び出しシナリオを解決するためにリフレクションを使用することは、設計が悪いことを示しています。

はるかに優れた設計は、静的メソッドをタイプセーフな方法でカプセル化するファクトリ/デリゲートを渡すことです。

class MyItem : MyItem {
  static void TheFunction() { ... }
}

public class MyList<LinkedItem> : List<LinkedItem> where LinkedItem : MyItem, new()
{
  public MyList(Action theStaticFunction) {
    ...
  }
}

new MyList<MyItem>(MyItem.TheFunction);
于 2010-08-16T17:19:20.030 に答える
0

これは不可能です。LinkedItem問題の静的メソッドを含める必要があるというパラメーターの制約を宣言する方法はありません。

おそらく最も近いのは次のとおりです。

public class ILinkedItemFactory<T>
{
    void YourMethodGoesHere();
}

public class MyList<LinkedItem, Factory> : List<LinkedItem>
    where Factory : ILinkedItemFactory<LinkedItem>
    where LinkedItem : MyItem, new()
{
    public MyList(Factory factory)
    {
        factory.YourMethodGoesHere();
    }
}
于 2010-08-16T17:20:01.523 に答える
0

デフォルトでは、これは不可能です。ただし、呼び出したいメソッドの名前が分かっていて、すべてLinkedItemの型にこのメソッドが含まれていることが確実な場合は、リフレクションを使用して目標を達成できます。注: 一般的なプログラミング タスクでは、リフレクションに解決するよりも良い方法がよくあります。

以下は、常に に対して出力trueされDoSomethingます。常に使用可能な静的メンバーを呼び出します (静的メソッドでは重要ではないため、ジェネリック型の制約を削除しました)。

public class MyList<LinkedItem> : List<LinkedItem>
{
    public bool DoSomething()
    {
        Type t = typeof(LinkedItem);
        object o = new Object();
        var result = t.InvokeMember("ReferenceEquals",
            BindingFlags.InvokeMethod |
            BindingFlags.Public |
            BindingFlags.Static,
            null,
            null, new[] { o, o });

        return (result as bool?).Value;
    }
}

// call it like this:
MyList<string> ml = new MyList<string>();
bool value = ml.DoSomething();   // true

PS: 一方、私がこれを入力している間、他の人は同じアプローチを提案しているようです ;-)

于 2010-08-16T17:38:18.047 に答える
0

これは完全に可能ですが、おそらく反省せずにあなたが述べている方法で直接ではありません。基本クラスに非静的アクセス メソッドを実装し、特定の継承クラスごとにオーバーライドする必要があります。

public class MyItem
{
    public static void DoSomeStaticStuff() { //DoSomeStaticStuff for MyItem }
    public virtual void AccessSomeStaticStuff() { MyItem.DoSomeStaticStuff(); }
}

public class SomeItem : MyItem
{
    public static void DoSomeStaticStuff() { //DoSomeStaticStuff for SomeItem }
    public override void AccessSomeStaticStuff() { SomeItem.DoSomeStaticStuff(); }
}

次に、 T : MyItem という制約を持つクラスで、 T.AccessSomeStaticStuff(); を呼び出すだけです。

于 2010-08-16T17:50:01.713 に答える