3

コンパイラは method を予期しているため、次の呼び出しは失敗しSetAll(PropertyInfo, int)ます。

var infos = GetType().GetProperties(BindingFlags.Instance | BindingFlags.Public);

var setters = infos.Select(SetAll); // no overload matches delegate.

private Action SetAll(PropertyInfo info, object obj) => () => info.SetValue(this, obj);

つまり、コンパイラはこのオーバーロードを使用できません。にキャストできませintobject

これを念頭に置いて、なぜ次の呼び出しがあいまいなのですか?

var b = infos.Select(SetAll); // ambiguous between Select<PropertyInfo, int, Action>
                              //              and  Select<PropertyInfo, Action>

private Action SetAll(PropertyInfo info, object obj) => () => info.SetValue(this, obj);

private Action SetAll(PropertyInfo info) => () => info.SetValue(this, null);

コンパイラがオブジェクトでオーバーロードを使用できない場合、なぜここで苦労するのですか?


これが私が持っている実際のコードです。私はこの問題に簡単に対処できますが、ただの好奇心です。

var infos = GetType().GetProperties(BindingFlags.Instance | BindingFlags.Public);

if (useDefaultsOnReset)
{
    var defaults = infos.Select(GetAll);
    _resetters = infos.Zip(defaults, SetAll).ToArray();
}
else
{
    _resetters = infos.Select(SetAll).ToArray(); // error
}

private object GetAll(PropertyInfo info) => info.GetValue(this);
private Action SetAll(PropertyInfo info, object obj) => () => info.SetValue(this, obj);
private Action SetAll(PropertyInfo info) => () => info.SetValue(this, null);
4

2 に答える 2

3

これは、System.Func<in T1, in T2, out TResult>がその引数の型で反変であるためです。inこれは、対応する型パラメーターの修飾子によって示されます。T1これが意味することは、型の引数を取る関数、または任意の型T1を割り当てることができる関数、および型の引数または任意のT2型を割り当てることができる関数に一致するということT2です。最初のシグネチャはEnumerable.Select、インデックスを組み込まない のオーバーロードと一致します。ただし、2 番目のシグネチャは実際には のオーバーロードと一致し、は に割り当て可能でEnumerable.Selectあるため、インデックスが組み込まれています。intobject

これを実証するために。任意のクラスを作成し、そのようにプログラムを変更するだけです。

private Action SetAll(PropertyInfo info, A a) => () => info.SetValue(this, obj);
private Action SetAll(PropertyInfo info) => () => info.SetValue(this, null);

class A {}

intに割り当てられないため、エラーが消えることがわかりAます。

コメントで説明したように、考慮に入れなかったしわがあります。int反変の関係は、参照型間、および値型に制約されていないジェネリック間に保持されますが、デリゲートを取るデリゲートとobject ギブンの間で直接代入する場合は特に機能しません。

Func<int, Action> f;

Func<object, Action> g;

以下は両方ともエラーです

g = f;
f = g;

intただし、いくつかのクラスに置き換えるとA

Func<A, Action> f;

Func<object, Action> g;

1 つ目はオブジェクトが A ではないためエラーですが、2 つ目は上で説明したように成功します。

g = f;
f = g;
于 2017-01-02T15:58:59.590 に答える
0

メソッドグループを操作するために、ダミー変数を書くことができます。

private Action SetAll(PropertyInfo info, object obj) => () => info.SetValue(this, obj);
private Action SetAll(PropertyInfo info, int _) => () => info.SetValue(this, null); 
//                                           ^ this is dummy but lets you use methodgroup

その後、これは動作します

infos.Select(SetAll).ToArray(); 

Selectインデクサーで使用しますが、それほど重要ではありません。

于 2017-01-02T16:00:34.213 に答える