为什么类型推断和隐式运算符在以下情况下不起作用?

我将试着用一个例子来解释我的问题:

class V { public readonly Func Get; public readonly bool IsConstant; V(Func get, bool isConstant) { Get = get; IsConstant = isConstant; } public static implicit operator V(T value) { return new V(() => value, true); } public static implicit operator V(Func getter) { return new V(getter, false); } } void DoSomething(V v) { //... } void Main() { DoSomething("test"); // (1) type inference is not working DoSomething((V)(() => "test")); // (2) implicit operator does not work } 

Main方法中,我有两种情况:

  1. 我必须明确指定方法DoSomething的generics参数
  2. 在这里,我必须添加显式强制转换(V) ,隐式运算符似乎不起作用。

为什么需要这个? 编译器正在考虑哪些替代方案,因此无法选择正确的方法?

你的第二个问题是为什么从()=>""V的隐式转换不成功,即使()=>""可转换为FuncFunc可转换为V

再说一次,我不知道怎么回答“为什么不呢?” 问题,但我知道如何回答“规范的哪一行表明编译器应该拒绝这个代码?”的问题。 相关的是:

首先,如果需要,执行从源类型到用户定义或提升转换运算符的操作数类型的标准转换。

请注意,这里有一个小错误; 这应该说是从源表达式执行标准转换。 源表达式可能没有类型。 我相信在离开团队之前我已经将这个注释发给了规范维护者,所以希望这将在下一版中得到修复。

无论如何,现在应该清楚这里发生了什么。 没有从lambda到委托类型的标准转换,因此用户定义的转换被转换解析算法分类为不适用

我假设你的代码打算调用DoSomething,而不是DumpValue。

你的问题是,首先,为什么

 DoSomething(""); 

没有推断该电话是打算的

 DoSomething((V)""); 

正确?

“为什么”这些问题很难回答,“为什么不呢?” 问题更难。 相反,我会回答一个可以回答的问题: 规范的哪一行certificate了这种行为是正确的?

重载解析的工作方式如下:如果方法组包含generics方法但未提供generics方法类型参数,则类型推断会尝试推断类型参数。 如果无法推断类型参数,则不考虑重载决策的方法。 在您的情况下,由于方法组中只有一个方法,删除它将导致重载解析失败。

为什么类型推断会失败? 无法推断T,因为规范的控制线是:

如果V是构造类型C并且存在一组唯一的类型U1 … Uk,使得从U到C存在标准隐式转换,那么从每个Ui进行精确推断相应的Vi。

没有从stringV 标准隐式转换 。 这是用户定义的隐式转换。

因此类型推断失败。

我会在第二个回答中回答你的第二个问题。 一般来说,在一个问题中提出两个问题是个坏主意。 当你有两个问题时,发两个问题。

我知道你的问题是“为什么类型推断不起作用”,但我只是认为我会在最后讨论你的两个选择。 在这种情况下,我认为隐式转换(eww,我讨厌那些)的更好的替代方法是静态工厂方法。 IMO,当你调用DumpValue时语法会更好。

 static class VFactory { public static V Create(T value) { return new V(() => value, true); } public static V Create(Func getter) { return new V(getter, false); } } class V { public readonly Func Get; public readonly bool IsConstant; internal V(Func get, bool isConstant) { Get = get; IsConstant = isConstant; } } void DumpValue(V v) { //... } void Main() { DumpValue(VFactory.Create("test")); DumpValue(VFactory.Create(() => "test")); }