我有一个
Expression<Func<T1, T2>> source因此,我可以将它编译成一个Func<T1, T2>,没有任何问题:
Func<T1, T2> result = source.Compile();但是现在我有一个特例,在这里(给定T2是一个int),我必须返回一个Func<T1, int>。当然,我不能只是投,但我也找不到另一种方式来转换它。
public Func<T1, int> GetFuncToReturnId()
{
if (source.ReturnType != typeof(int))
{
throw new InvalidOperationException("source must be of return type must be of type int");
}
return // ??? please help !!!
}我尝试将表达式的部分或已编译的Func部分转换为Func<T1, int>的构造函数,但这并没有帮助。我能做些什么
Expression<Func<T1, T2>>转换为Expression<Func<T1, int>>Func<T1, T2>到Func<T1, int>发布于 2018-10-25 18:53:58
从您的问题中可以准确地看出您的问题是什么,但我可以猜测,将Func<T1, T2>转换为Func<T1, int>会产生无效的强制转换错误。
这是无效的原因是因为C#对从类型参数到任何其他类型的任何转换都是保守的。假设您有一个用户定义的从Foo到Bar的转换。如果你有办法
Bar M<T>(T t) { return (Bar)t; }然后,您可能会合理地期望M<Foo>(new Foo())会调用用户定义的转换到Bar。但是C#泛型不是模板,也不为每个泛型实例化重新生成代码。只有当存在标识或引用转换时,这种转换才是有效的,而且C#正在阻止您犯这一常见错误。
此外,无论何时对泛型进行类型测试,它都不再是“泛型”。不管类型参数如何,泛型代码都应该同样工作,这就是为什么它被称为“泛型代码”的原因。听起来你所做的是在违背仿制药的目的。
尽管如此,如果您一心想这么做,有几种方法可以在泛型类型之间进行引用转换,如下所示:
class C<T1, T2>
{
void M(Func<T1, int> f) {}
// This way is wrong.
void N1(Func<T1, T2> f)
{
if (f is Func<T1, int>)
M((Func<T1, int>)f); // Error, cannot convert
}
// This works.
void N2(Func<T1, T2> f)
{
var fi = f as Func<T1, int>;
if (fi != null)
M(fi);
}
// This also works.
void N3(Func<T1, T2> f)
{
if (f is Func<T1, int>)
M((Func<T1, int>)(object)f);
}
// This works in C# 7; it's a more concise way to combine the previous two
void N4(Func<T1, T2> f)
{
if (f is Func<T1, int> fi)
M(fi);
}
}发布于 2018-10-25 13:51:52
您可以通过使用Convert.ChangeType来实现这一点。
var compiled = source.Compile();
return (T1 x) => (int) Convert.ChangeType(compiled(x), typeof(int));或者简单的铸造两次
var compiled = source.Compile();
return (T1 x) => (int) (object) compiled(x);https://stackoverflow.com/questions/52990249
复制相似问题