将通用方法参数转换为特定类型

时间:2013-03-12 04:14:45

标签: c# linq generics lambda expression

给定一个通用方法Get<T>,它采用以下参数......

Expression<Func<T,bool>> foo   

在该方法体中,我想测试'T'是否为typeof(Stuff),如果是,则将其投射:

Expression<Func<Stuff,bool>> boo = (???) foo;

我期望的第一个反应是“不需要施放它,如果传入它,它已经是Stuff类型。”但我发现在方法调度方面并不正确!!

所以是的,我需要测试和演员,但不知道如何。

以下是必要的原因和地点。

我有这样的代码:

public class Stuff {
    public int Alpha;
}

interface ISomething {
    List<T> Get<T>(Expression<Func<T,bool>> lambda);
}

public class Something : ISomething {

    List<T> Get<T>(Expression<Func<T,bool>> expr){
      //...

      //Makes non-recursive call to non-generic 'Get' method.
      //Works as expected.
      Get((Stuff x) => x.Alpha > 10);

      //UH-OH! makes recursive call to Get<T> even when T is typeof(Stuff)!
      //This is where casting is needed!
      Get(expr);

      //...
    }

    List<Stuff> Get(Expression<Func<Stuff,bool>> expr){
       //...
    }
}

如果Get<T> Get专门采用expr类型的参数,我的目的是让通用方法LambdaExpression调用非通用Stuff。但这不是上面代码中发生的情况。

如果我运行此代码......

ISomething foo = new Something();
var result = foo.Get((Stuff x) => x.Alpha < 20);

...调用的函数是Get<T>。这并不奇怪,即使非通用Get是更好的匹配,因为Get<T>是ISomething接口中唯一可用的匹配。所以这没关系。

但是一旦Get<T>方法执行,我希望使用名为Get的相同参数调用非泛型expr。鉴于我正在观察的行为,如果我将Expression<Func<T,bool>>转换为Expression<Func<Stuff,bool>>,我看起来似乎只能获得我想要的内容。这也假设我有一个测试,例如isas,以确认它是可投射的。

如何完成类型测试,以及如何完成演员表?

是否有其他方法来强制调用更具体和非通用的Get方法?请假设呼叫者必须仅通过ISomething接口工作。

当然,如果立即调用非通用Get而不通过Get<T>,那将更加理想。但如果我被迫通过ISomething界面工作,我认为这是不可能的。

仅供参考,如果可以找到一种方法使其工作 - 那么它将提供与C ++中的“traits - the else-then-if”类似的功能。

1 个答案:

答案 0 :(得分:3)

这样的事情怎么样:

public List<T> Get<T>(Expression<Func<T,bool>> expr){
    var expr2 = expr as Expression<Func<Stuff, bool>>;
    if (expr2 != null){
        return Get(expr2) as List<T>;
    }

    //...
}

此代码使ReSharper变得怪异,但似乎有效:)

如果可能,更好的选择是向ISomething添加非泛型重载。