首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何将Func<T1、T2>转换为Func<T1、int>

如何将Func<T1、T2>转换为Func<T1、int>
EN

Stack Overflow用户
提问于 2018-10-25 13:17:05
回答 2查看 572关注 0票数 0

我有一个

代码语言:javascript
复制
Expression<Func<T1, T2>> source

因此,我可以将它编译成一个Func<T1, T2>,没有任何问题:

代码语言:javascript
复制
Func<T1, T2> result = source.Compile();

但是现在我有一个特例,在这里(给定T2是一个int),我必须返回一个Func<T1, int>。当然,我不能只是投,但我也找不到另一种方式来转换它。

代码语言:javascript
复制
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>
EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2018-10-25 18:53:58

从您的问题中可以准确地看出您的问题是什么,但我可以猜测,将Func<T1, T2>转换为Func<T1, int>会产生无效的强制转换错误。

这是无效的原因是因为C#对从类型参数到任何其他类型的任何转换都是保守的。假设您有一个用户定义的从Foo到Bar的转换。如果你有办法

代码语言:javascript
复制
Bar M<T>(T t) { return (Bar)t; }

然后,您可能会合理地期望M<Foo>(new Foo())会调用用户定义的转换到Bar。但是C#泛型不是模板,也不为每个泛型实例化重新生成代码。只有当存在标识或引用转换时,这种转换才是有效的,而且C#正在阻止您犯这一常见错误。

此外,无论何时对泛型进行类型测试,它都不再是“泛型”。不管类型参数如何,泛型代码都应该同样工作,这就是为什么它被称为“泛型代码”的原因。听起来你所做的是在违背仿制药的目的。

尽管如此,如果您一心想这么做,有几种方法可以在泛型类型之间进行引用转换,如下所示:

代码语言:javascript
复制
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);
  }

}
票数 3
EN

Stack Overflow用户

发布于 2018-10-25 13:51:52

您可以通过使用Convert.ChangeType来实现这一点。

代码语言:javascript
复制
var compiled = source.Compile();

return (T1 x) => (int) Convert.ChangeType(compiled(x), typeof(int));

或者简单的铸造两次

代码语言:javascript
复制
var compiled = source.Compile();
return (T1 x) => (int) (object) compiled(x);
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/52990249

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档