Вывод выражения при наследовании - PullRequest
1 голос
/ 04 ноября 2008

У меня есть следующий код:

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

Тогда это работает. Есть ли способ получить первый пример для компиляции, изменив вместо этого базовый класс?

Я знаю, что если я сделаю весь Базовый класс универсальным, вот так:

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).

Ответы [ 2 ]

6 голосов
/ 04 ноября 2008

Как насчет метода расширения, который вызывает фактическую (protected internal) реализацию? Единственным недостатком является то, что вы должны добавить 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);
}
0 голосов
/ 04 ноября 2008

Если он не принимает параметр, он не может быть выведен. Если оно не присваивает возвращаемое значение, оно не может быть выведено.

...