c# - このクラスを一般的なクラスに変えることは可能ですか?

c# generics delegates

この質問の最後にリストされているクラスを「一般化」できる人はいますか?クラスが「GetStateDelegate」型のデリゲートではなく、一般的なデリゲートにロックされることを望みます。それは可能ですか?

私はいくつか試しましたが、1)C#はこの種のクラス宣言が好きではありません。

public class StringToMethodMapper<T> where T: System.Delegate


これにより、「System.Delegateを型パラメーターの制約として使用できません」が生成されます。

私を正しい軌道に乗せるためのヒントをいただければ幸いです。また、解決策が存在する場合、消費者が変更による影響をできるだけ受けないようにしたいと考えています。たとえば、 "Add(string、delegate)"の呼び出しコードは変更しません。

コード:

public delegate bool GetStateDelegate(object someObject);

public class StringToMethodMapper
{
    private Dictionary<string, GetStateDelegate> _methods;

    public StringToMethodMapper()
    {
        _methods = new Dictionary<string, GetStateDelegate>();
    }

    public void Add(string key, GetStateDelegate method)
    {
        _methods.Add(key, method);
    }

    internal virtual GetStateDelegate GetMethodFor(string key)
    {
        foreach (var storedKey in _methods.Keys)
        {
            if (key.ToUpper().StartsWith(storedKey.ToUpper()))
            {
                return _methods[storedKey];
            }
        }
        return null;
    }
}
答え
それを一般化するという意味では...まあ、それは一種の可能性です。 Unconstrained Melodyと呼ばれるライブラリがあり、デリゲート制約のあるジェネリックに対してILリライティングを使用しています。コードで同じILリライタを使用できます。それはかなり醜いですが。基本的にILは必要な制約をサポートしていますが、C#はサポートしていません。 「MulticastDelegateから派生するが、MulticastDelegate自体は含まないタイプである必要がある」という制約はないことに注意してください。誰かがStringToMethodMapper<MulticastDelegate>を作成する可能性がありますが、それはなめらかではありません。

1種類のデリゲート署名(たとえば、「常に3つのパラメーターとvoidによる戻り値」)に固執することに満足している場合は、ジョージの回答からのアプローチを使用できます。デリゲート型の場合は、ILの書き換えアプローチに拘束されているか、制約を放棄しています。



(コメントに基づいて編集。)

残りのコードに関しては、辞書の使用は非常に遅いです。現在、O(n)ルックアップがあります。 Dictionaryを介した通常のTryGetValueアクセスを使用しますが、大文字と小文字を区別しない一致を取得するには、コンストラクタにStringComparer.OrdinalIgnoreCase(または類似の何か)を渡します。確かに、starts-with一致は得られません...しかし、いずれにしても、ディクショナリのキーとして "foo"と "fo"が使用される可能性があるため、現在のアプローチは確定的ではありません。したがって、イテレータがキーを返す順序に依存しています。素晴らしいアイデアではありません。

StartsWithの動作が本当に必要な場合は、trieの実装を調査することをお勧めします。または、O(N)ルックアップに満足している場合は、List<KeyValuePair<string, TDelegate>>を使用していないことを明確にします本当に辞書として使っています。
関連記事

c# - 端末(Windows-CE)が5分後にシャットダウンしないようにする方法

c# - 要素の1つを取得、変更、保存できるようにするために、関連する値のリストを保存するために使用する必要があるもの

c# - エンタープライズライブラリdbcommand AddInParameterメソッド

c# - RIAデータサービスの呼び出しをサービスレイヤーにリファクタリングするにはどうすればよいですか?

c# - MoqでHttpApplicationStateをモックするときにオブジェクトを設定できないようです

c# - ラインオブジェクトのエンドキャップの幅または高さの値を取得するにはどうすればよいですか?

c# - データベースにアクセスしてエンティティフレームワークデータをテストする

c# - LoadAsyncとMemoryStreamを使用して、データベースから画像ボックスに画像をロードしたい

c# - リピーターをカスタムクラスの配列にバインドする方法[閉まっている]

c# - CSSをasp.net Webアプリケーションに追加する方法