2

给定一个采用以下参数的通用方法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具体采用 type 参数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>>鉴于我观察到的行为,看起来只有将to 转换为我才能得到我想要的东西Expression<Func<Stuff,bool>>。这也假设我有一个测试,比如isor as,以确认它是可铸造的。

类型测试是如何完成的,演员是如何完成的?

Get是否有另一种方法来强制调用更具体和非通用的方法?请假设调用者必须ISomething只通过接口工作。

Get当然,如果不经过任何处理就立即调用非泛型会更加理想Get<T>。但如果我被迫通过ISomething界面工作,我认为这是不可能的。

仅供参考,如果可以找到一种方法来完成这项工作 - 然后它将提供类似于C++ 中的“特征 - else-then-if ”的功能。

4

1 回答 1

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 添加非泛型重载。

于 2013-03-12T04:51:04.977 回答