匿名方法表达式的类型为int时,为什么它的类型被推断为Func<int?>?

huangapple go评论64阅读模式
英文:

Why is anonymous method that has expression of type int having its type inferred as Func<int?>?

问题

I have a generic function that is supposed to traverse a sequence of properties within a LINQ expression to compare against another passed-in value but discovered that the LINQ expression contained a convert operation, which my function was not expecting. I've been going over the C# type inference docs to see how this could have happened but haven't been having a lot of luck figuring it out. In the process I ended up simplifying the problem to the following.

这是一段通用函数,应该遍历 LINQ 表达式中的属性序列以与传入的另一个值进行比较,但发现 LINQ 表达式包含一个转换操作,而我的函数没有预料到。我一直在查阅C#类型推断文档,以了解可能发生这种情况的原因,但一直没有很好地弄清楚。在这个过程中,我简化了问题,如下所示。

The generic function:

public static void M&lt;T&gt;(Func&lt;T&gt; func, T value)
{
}

通用函数如下:

public static void M&lt;T&gt;(Func&lt;T&gt; func, T value)
{
}

In this block of code the type of T is inferred to be int?, which I wasn't expecting and was trying to figure out why.

int? value = null;
M(() =&gt; 5, value);

在这段代码中,T 的类型被推断为 int?,这让我感到意外,我试图弄清楚为什么。

int? value = null;
M(() =&gt; 5, value);

I was comparing it against this next block of code which fails type inference.

int? value = null;
Func&lt;int&gt; function = () =&gt; 5;
M(function, value);

我正在将它与下面的代码块进行比较,但它未能通过类型推断。

int? value = null;
Func&lt;int&gt; function = () =&gt; 5;
M(function, value);

I believe I understand why type inference fails here: the return type of the function no longer needs to be inferred and Func&lt;int&gt; has no implicit conversion to Func&lt;int?&gt; since they are dealing with value types, not reference types.

我相信我理解为什么类型推断在这里失败:函数的返回类型不再需要推断,而且 Func&lt;int&gt; 无法隐式转换为 Func&lt;int?&gt;,因为它们处理的是值类型,而不是引用类型。

In the first example it seems to me that type inference sees that the anonymous method's expression type of int is implicitly convertible to int? and then infers the anonymous method's type to be Func&lt;int?&gt;. Is this what is happening or is something else going on here?

在第一个示例中,我认为类型推断看到匿名方法的表达式类型 int 隐式可转换为 int?,然后推断匿名方法的类型为 Func&lt;int?&gt;。这是否是正在发生的事情,还是还有其他情况?

If so, I'm kind-of surprised to see type inference reach into the expression and implicitly convert what it was returning.

如果是这样,我有点惊讶于看到类型推断深入到表达式中,并隐式转换它返回的内容。

英文:

I have a generic function that is supposed to traverse a sequence of properties within a LINQ expression to compare against another passed-in value but discovered that the LINQ expression contained a convert operation, which my function was not expecting. I've been going over the C# type inference docs to see how this could have happened but haven't been having a lot of luck figuring it out. In the process I ended up simplifying the problem to the following.

The generic function:

public static void M&lt;T&gt;(Func&lt;T&gt; func, T value)
{
}

In this block of code the type of T is inferred to be int?, which I wasn't expecting and was trying to figure out why.

int? value = null;
M(() =&gt; 5, value);

I was comparing it against this next block of code which fails type inference.

int? value = null;
Func&lt;int&gt; function = () =&gt; 5;
M(function, value);

I believe I understand why type inference fails here: the return type of the function no longer needs to be inferred and Func&lt;int&gt; has no implicit conversion to Func&lt;int?&gt; since they are dealing with value types, not reference types.
In the first example it seems to me that type inference sees that the anonymous method's expression type of int is implicity convertible to int? and then infers the anonymous method's type to be Func&lt;int?&gt;.
Is this what is happening or is something else going on here?
If so, I'm kind-of surprised to see type inference reach into the expression and implicitly convert what it was returning.

答案1

得分: 0

你的要求已经被记录下来,我将只返回翻译好的部分。以下是翻译:

你的思路基本正确,尽管我不会完全用你在问题中的措辞。类型推断非常复杂,仅仅通过阅读C#标准,我相当确信我至少在某些地方发现了一个错误(xᵢ 应该是 pᵢ,我将尝试在下周修复它),所以我会避免正式的过程。

相反,让我们分别看一下这两种情况:

情况 1

public static void M<T>(Func<T> func, T value) {}
...
int? value = null;
M(() => 5, value);

有两个参数:一个匿名函数和一个类型为 int? 的简单变量。

推断过程将会推断:

  • 必须存在从 5T 的隐式转换,以便将匿名函数转换为 Func<T>
  • 必须存在从 int?value 变量的类型)到 T 的隐式转换,以使第二个参数有效

非常粗略,但可以合理地想象编译器说:“嘿,让我们尝试在这里使用 T=int?”:

  • 第一个条件已满足,因为从 5int? 存在隐式转换。所以我们可以将 () => 5 转换为 Func<int?>
  • 第二个条件是微不足道的,因为从 int?int? 存在标识转换

情况 2

public static void M<T>(Func<T> func, T value) {}
...
int? value = null;
Func<int> function = () => 5;
M(function, value);

在这里,类型推断需要:

  • 必须存在从 Func<int>Func<T> 的隐式转换,以使第一个参数有效 - 这意味着从 intT 必须存在标识转换
  • 必须存在从 int?T 的隐式转换,以使第二个参数有效

类型推断失败,因为没有类型 T 同时满足这两个约束条件。

英文:

You're basically thinking along the right lines, although I wouldn't phrase it quite as you did in the question. Type inference is massively complicated, and just reading through the C# standard I'm fairly convinced I've spotted at least one error (xᵢ should be pᵢ in some places; I'll try to get that fixed next week), so I'll avoid the formal process.

Instead, let's look at the two situations separately:

Situation 1

public static void M&lt;T&gt;(Func&lt;T&gt; func, T value) {}
...
int? value = null;
M(() =&gt; 5, value);

There are two arguments: an anonymous function, and a simple variable of type int?.

The inference process will infer:

  • There must be an implicit conversion from 5 to T, in order for there to be a conversion from the anonymous function to Func&lt;T&gt;
  • There must be an implicit conversion from int? (the type of the value variable) to T, in order for the second argument to be valid

Massively hand-wavy, but it's reasonable to imagine the compiler saying, "Hey, let's just try T=int? here":

  • The first condition is met, as there is an implicit conversion from 5 to int?. So we can convert () =&gt; 5 to a Func&lt;int?&gt;
  • The second condition is trivially met as there's an identity conversion from int? to int?

Situation 2

public static void M&lt;T&gt;(Func&lt;T&gt; func, T value) {}
...
int? value = null;
Func&lt;int&gt; function = () =&gt; 5;
M(function, value);

Here, type inference requires:

  • There must be an implicit conversion from Func&lt;int&gt; to Func&lt;T&gt; for the first argument to be valid - which means there must be an identity conversion from int to T
  • There must be an implicit conversion from int? to T for the second argument to be valid

Type inference fails as there's no type T that satisfies both of those constraints.

huangapple
  • 本文由 发表于 2023年5月7日 00:09:29
  • 转载请务必保留本文链接:https://go.coder-hub.com/76189896.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定