gpt4 book ai didi

c# - 编译器/运行时如何确定 lambda 表达式的类型?

转载 作者:太空宇宙 更新时间:2023-11-03 17:48:23 25 4
gpt4 key购买 nike

我想知道编译器/运行时如何确定 lambda 表达式的类型?

例如下面的System.Linq Select扩展方法(非select查询)

//var recordIds = new List<int>(records.Select(r => r?.RecordId ?? 0));
//var recordIds = new List<int>(records.Where(r => r != null).Select(r => r.RecordId));
var recordIds = new List<int>(records.Select(r => r.RecordId));

定义为

Enumerable.Select<TSource, TResult> Method (IEnumerable<TSource>, Func<TSource, TResult>)

因此采用 lambda r => r.RecordId作为Func<TSource, TResult> .

lambda 的类型是如何确定的,一旦确定,是否只是简单地转换为该类型?

最佳答案

I was wondering how the the compiler/runtime determines a lambda expression's type?

比较复杂。实现此功能是发布 C# 3 的 Visual Studio 版本的“长杆”——因此,我在这方面超过计划的每一天都是 VS 失误的一天! -- 随着在 C# 4 中引入协变和逆变,该功能只会变得更加复杂。

正如其他人所指出的,请查阅规范以了解确切的详细信息。您也可以阅读我多年来撰写的有关它的各种文章。

虽然我可以给你一个快速的概述。假设我们有

records.Select(r => r.RecordId)

哪里records类型为 IEnumerable<Record>RecordId类型为 int .

第一个问题是“IEnumerable<Record> 是否有任何适用的方法称为 Select?不,没有。因此我们进入扩展方法回合。

那么第二个问题是:“是否有任何具有适用于此调用的可访问扩展方法的静态类型?”

SomeType.Select(records, r => r.RecordId)

让我们假设 Enumerable是唯一的这种类型。它有两个版本的 Select ,其中一个采用带有两个参数的 lambda。我们可以自动丢弃那个。正如您所指出的,这给我们留下了:

static IEnumerable<R> Select<A, R>(IEnumerable<A>, Func<A, R>)

第三个问题:能否推导出类型参数对应的类型实参AR

在第一轮类型推断中,我们考虑了所有非 lambda 参数。我们只有一个。我们推断 A可能是 Record .然而,IEnumerable<T>是协变的,所以我们注意到它可能是比 Record 更通用的类型以及。它不能是比 Record 更具体的类型虽然。

现在我们问“我们完成了吗?”不,我们仍然不知道R .

“还有什么可以推断的吗?”是的。我们还没有检查 lambda。

“关于 A 是否有任何矛盾或额外的事实需要了解?”没有。

因此我们“修复”ARecord继续前进。到目前为止我们知道什么?我们有:

static IEnumerable<R> Select<Record, R>(IEnumerable<Record>, Func<Record, R>)

然后我们说 OK,参数必须是 (Record r) => r.RecordId .我们可以推断出这个 lambda 的返回类型吗?显然是的,它是 int .所以我们在 R 上写了一个注释说它可能是int .

我们完成了吗?是的。还有什么我们可以推论的吗?不,我们是否推断出所有的类型参数?是的。所以我们“修复”Rint ,我们就完成了。

现在我们进行最后一轮检查以确保 Select<Record, int>不会产生任何错误;例如,如果 Select有一个被 <Record, int> 违反的通用约束我们现在会拒绝它。

我们推断出 records.Select(r=>r.RecordId)Enumerable.Select<Record, int>(records, (Record r) => { return (int)r.RecordId; } ) 含义相同这是对该方法的合法调用,所以我们完成了。

当您引入多个边界时,事情会变得更加复杂。看看你能不能算出像 Join 这样的东西在有四种类型参数要推断的情况下工作。

关于c# - 编译器/运行时如何确定 lambda 表达式的类型?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49677164/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com