質問

次のコードがあります:

using System;
using System.Linq;
using System.Linq.Expressions;

public class Program
{
    public static void Main()
    {
        Descendant d = new Descendant();
        d.TestMethod();
    }
}

public class Base
{
    protected void FigureItOut<TClass, TMember>(Expression<Func<TClass, TMember>> expr)
    {

    }
}

public class Descendant : Base
{
    public void TestMethod()
    {
        FigureItOut(c => c.Name);
    }

    public String Name { get; set; }
}

このコンパイラエラーメッセージが表示されます:

The type arguments for method
'Base.FigureItOut<TClass,TMember> 
(System.Linq.Expressions.Expression<System.Func<TClass,TMember>>)'
cannot be inferred from the usage. Try specifying the type arguments explicitly.

FigureItOutへの呼び出しをこれに変更した場合:

FigureItOut((Descendant c) => c.Name);

それで動作します。代わりに基本クラスを変更してコンパイルする最初の例を取得する方法はありますか?

次のようにBaseクラス全体をジェネリックにすると、次のようになります。

public class Base<TDescendant>
{
    protected void FigureItOut<TMember>(Expression<Func<TDescendant, TMember>> expr)
    {

    }
}

public class Descendant : Base<Descendant>
{
    public void TestMethod()
    {
        FigureItOut(c => c.Name);
    }

    public String Name { get; set; }
}

その後は動作しますが、メソッドレベルで使用できる他のハッキング(つまり、何らかの方法でFigureItOutを変更する)は実行しません。

役に立ちましたか?

解決

実際の(保護された内部)実装を呼び出す拡張メソッドはどうですか?唯一の欠点は、 this。を追加する必要があることです。

これは、 source パラメーター( this を使用)が TClass の型を推測するために機能します。

public class Base
{
    protected internal void FigureItOut<TClass, TMember>(Expression<Func<TClass, TMember>> expr)
    {
        Debug.WriteLine("Got to actual method");
    }
}

public static class BaseExt
{
    public static void FigureItOut<TClass, TMember>(this TClass source, Expression<Func<TClass, TMember>> expr)
        where TClass : Base
    { // call the actual method
        Debug.WriteLine("Got to extension method");
        source.FigureItOut(expr);
    }
}
public class Descendant : Base
{
    public void TestMethod()
    {
        this.FigureItOut(c => c.Name);
    }

    public String Name { get; set; }
}

代替として( internal が苦痛の場合)、主に型推論に使用されるインスタンス引数を使用して、静的にすることを検討してください:

protected static void FigureItOut<TClass, TMember>(TClass source, Expression<Func<TClass, TMember>> expr)
{

}

public void TestMethod()
{
    FigureItOut(this, c => c.Name);
}

他のヒント

パラメータを受け取らない限り、推測することはできません。 戻り値を割り当てない限り、推測することはできません。

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top