Frage

Ich habe den folgenden Code:

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; }
}

Ich erhalte diese Fehlermeldung Compiler:

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.

Wenn ich den Anruf zu FigureItOut Um dies zu ändern:

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

Dann funktioniert es. Gibt es eine Möglichkeit das erste Beispiel zu erhalten, indem die Basisklasse zu kompilieren statt?

Ich weiß, dass, wenn ich die gesamte Basisklasse generic machen, wie folgt aus:

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; }
}

Dann funktioniert es, aber ich möchte lieber nicht tun, andere Hacks, die eingesetzt werden können, vielleicht auf der Methode Ebene (dh. Verändern FigureItOut irgendwie).

War es hilfreich?

Lösung

Wie wäre es eine Erweiterungsmethode, die die tatsächliche (protected internal) Implementierung ruft? Der einzige Nachteil ist, dass Sie this. hinzuzufügen haben.

Das funktioniert, weil die source Parameter (via this) einen Typ für TClass folgert.

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; }
}

Als Alternative (wenn der internal ein Schmerz ist), sollten Sie es statisch zu machen, mit einer Instanz Argumente, das in erster Linie für Typinferenz verwendet wird:

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

}

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

Andere Tipps

Es sei denn, es einen Parameter nimmt, kann nicht gefolgert werden. Es sei denn, es einen Rückgabewert zuweist, kann nicht gefolgert werden.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top