C#泛型委托类型推断

3
为什么C#编译器不能在指定的例子中推断T为int?
void Main()
{
    int a = 0;
    Parse("1", x => a = x);
    // Compiler error:
    // Cannot convert expression type 'int' to return type 'T'
}

public void Parse<T>(string x, Func<T, T> setter)
{
    var parsed = ....
    setter(parsed);
}

1
我也无法推断。尝试使用Parse<int>(...) - L.B
解析方法的语法糖。我可以使用表达式来完成,但那样我就必须使用反射,这是不可取的。 - m0sa
“表达式”不是“反射”。请展示您所尝试做的完整代码。 - gdoron
@L.B 这正是我现在正在做的事情。但我想知道为什么编译器不能弄清楚,因为 'x => a = x' 返回一个 int。 - m0sa
@gdoron 我可以使用表达式来获取我要设置的属性的 PropertyInfo,但是我必须使用反射来调用它。 - m0sa
2个回答

5

对于lambda函数的方法类型推断,需要在推断返回值类型之前已经知道lambda参数的类型。例如,如果您有以下内容:

void M<A, B, C>(A a, Func<A, B> f1, Func<B, C> f2) { }

并且调用

M(1, a=>a.ToString(), b=>b.Length);

那么我们可以推断出:
A is int, from the first argument
Therefore the second parameter is Func<int, B>. 
Therefore the second argument is (int a)=>a.ToString();
Therefore B is string.
Therefore the third parameter is Func<string, C>
Therefore the third argument is (string b)=>b.Length
Therefore C is int.
And we're done.

我们需要A来解决B的问题,需要B来解决C的问题。在您的情况下,您希望从T中解决T的问题,这是不可能的。


当你这样说的时候,它真的显而易见... :) - m0sa
@ceztko:语言设计者不必列出未将某些功能添加到语言的原因!可能有无限多种可能的功能,我们还没有想出所有不要使用它们的原因。相反,功能必须由需要它们的人来证明其合理性。如果您有一个语言功能的提案,请随时在Github上设计并提出。 - Eric Lippert
1
@ceztko:没错,完整性一致性都是设计标准,但我认为它们是“弱”标准。也就是说,在一个“完整”的设计和一个“缺少某些情况”的设计之间,如果在其他方面相似,我们会选择“完整”的设计。问题是,这些设计从来不会“在其他方面相似”。举个例子,我们在C# 3.0中添加了扩展方法。为什么不追求完整性,同时添加扩展属性/构造函数/索引器/运算符呢? - Eric Lippert
1
因为预算的原因。我们曾经设计了扩展属性,但意识到它会给时间表带来巨大的压力,而且并不能让LINQ更好地工作,于是我们迅速放弃了它。完整性是昂贵的,这既因为它有直接的成本——必须有人设计、实现、测试、文档化和发布该功能——也因为它有机会成本——你花在不必要的完美主义功能上的时间就是你没有为某个实际需要的功能添加时间。 - Eric Lippert
关于扩展方法的完整性,提案:静态扩展方法是一篇很好的阅读材料。它展示了一个“简单”的特性可以变得特别复杂。此外,它还有许多看起来合理的提案,专家们解释了这些提案中发现的问题。 - Brian
显示剩余2条评论

2

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接