2

これは実際には 2 つの部分からなる質問です。

1. パラメータの型が異なる関数の配列を Array または IEnumerable に格納するにはどうすればよいですか

次のように動作するコードを書くことは可能ですか:

Func<object, bool> fObj = (o) => false;
Func<Animal, bool> fAni = (a) => false;
Func<Cat, bool> fCat = (c) => true;
var funcArray = new Function1Array<bool>(fObj, fAni, fCat);

Function1Array<T>c# では一般的なワイルドカードが(params Func<?, T>[] funcs)許可されていませんが、

2. 質問 1 を実行できると仮定すると、オブジェクトが関数のいずれかのパラメーターと同じ型であるかどうかを確認し、同じ型である場合はオブジェクトにキャストできますか?

例:

Cat myCat = new Cat();
funcArray.invokeFirstMatch(myCat); // Invokes fCat(myCat)

object myCat2 = new Cat();          // Declared as object instead of Cat
funcArray.invokeFirstMatch(myCat2); // Invokes fCat(myCat2)

Dog myDog = new Dog();
funcArray.invokeFirstMatch(myDog); // Invokes fObj(myDog)

私の推測では、この方法で関数の配列を格納する直接的な方法がないことを意味するFunc<Cat, bool>サブタイプではないため、各関数を何らかの方法でラップしないと、両方の質問は不可能であると思います。Func<object, bool>

4

1 に答える 1

2

次のようなことができます。

public class Function1Array<TOut> : IEnumerable
{
    private readonly List<Delegate> funcs = new List<Delegate>();

    public void Add<T>(Func<T, TOut> f)
    {
        this.funcs.Add(f);
    }

    public TOut InvokeFirstMatch<T>(T arg)
    {
        Delegate first = this.funcs.FirstOrDefault(d => d.GetType().GetGenericArguments()[0] == typeof(T));
        if (first == null) throw new ArgumentException("No match");
        return ((Func<T, TOut>)first)(arg);
    }

    IEnumerator IEnumerable.GetEnumerator()
    {
        return this.funcs.GetEnumerator();
    }
}

コレクション初期化子で初期化できます。

var arr = new Function1Array<bool> { fObj, fAni, fCat };

FirstOrDefaultに与えられた述語を useに変更できますが、これには引数の型が正確に一致する必要があることに注意してくださいIsAssignableFrom

のジェネリック パラメーターInvokeFirstMatchは、引数の静的な型に基づいて検索が行われることを意味します。代わりにランタイム タイプを使用できます。

public TOut InvokeFirstMatch(object arg)
{
    var argType = arg.GetType();
    Delegate first = this.funcs.FirstOrDefault(d => d.GetType().GetGenericArguments()[0] == argType);
    if (first == null) throw new ArgumentException("No match");
    return (TOut)first.DynamicInvoke(Convert.ChangeType(arg, argType));
}
于 2013-05-16T21:10:38.683 に答える