gpt4 book ai didi

c# - C# Lambda 表达式类型安全吗?何时(编译时/运行时)检查它们?

转载 作者:行者123 更新时间:2023-11-30 20:23:15 26 4
gpt4 key购买 nike

我正在处理 LINQ to XML 查询,并使用过匿名函数和 lambda 表达式。一个简单的例子是 select IEnumerables 上的方法。

我理解LINQ查询是延迟执行的,这有点类似于lazy evaluation的概念,但是当VS2012的quick watch不能处理lambda表达式的语句时,我想到了这个问题。

Lambda 表达式在 C# 中是类型安全的吗?

我找不到对此的直接答案,或者可能是因为我没有完全理解类型安全。我知道 OCaml 和 Java 是类型安全的,而 Python 是弱类型的,我能想到的另一种方式是,如果语言是类型安全的,那么该语言中的 lambda 表达式就没什么特别的了。 There is ambiguity in strong/weak typing但在这里我提到它好像具有错误类型的 lambda 表达式将通过编译器并允许在运行时执行。如果存在引发异常的错误,它们是否仅在运行时被捕获?

他们什么时候检查?编译时或运行时

例如,OCaml 类型在编译时进行检查,并且在解析类型之前不会执行。而 Python 不那么严格,是一种动态语言,即使出现类型错误,它也会编译和执行,只在运行时捕获错误。从这个意义上讲,C# 如何处理 lambda 表达式?

在问这个问题之前我做了一些相关的研究:

  1. How are Java lambdas compiled
  2. This blog posts says LINQ is type-safe
  3. Tutorial on using lambda expressions from CodeProject
  4. Difference between C# Anonymous functions and Lambda Expressions

最佳答案

在 C# 中存在两种类型的 Lambda Expression :

A lambda expression is an anonymous function that you can use to create delegates or expression tree types.

第一种 lambda 表达式是匿名函数的语法糖:

Func<int, int> myFunc = x => x + 1;

完全等同于:

Func<int, int> myFunc = delegate(int x) { return x + 1; };

所以它显然是类型安全的,因为它是具有不同构成的 C# 代码。

另一种类型的 Lambda 表达式是生成表达式树的表达式:

Expression<Func<int, int>> myFunc = x => x + 1;

这是不同的东西。这不是编译为“代码”,而是编译为一些 Expression 类型的对象,它“描述”了 x => x + 1 (甚至描述了delegate)... 它被编译为:

ParameterExpression par = Expression.Parameter(typeof(int), "x");
Expression<Func<int, int>> myFunc2 = Expression.Lambda<Func<int, int>>(
Expression.Add(par, Expression.Constant(1)),
par);

现在,这段代码不能直接执行。它可以通过.Compile() 方法转换为可执行代码。一般来说,.Compile()d 表达式树是类型安全的,但表达式树通常不会被简单地编译。程序倾向于操纵它们以获得有趣的结果。它们可用于各种任务......例如提取属性或“方法”的“名称”而不在代码中包含具有属性或方法名称的字符串,或者转换为其他语言( Entity Framework /LinqToSQL 将表达式树转换为 SQL)。表达式树是非常安全的(可以在运行时“手动构建”一个无效的表达式,但是当你执行 .Compile() 时你会得到一个异常,并且表达式树被C# 编译器通常可以安全编译),但如果表达式树用于其他用途,则可能会发生错误,甚至是与类型安全相关的错误。

我将引用自:Why the anonymous type instance cannot accept null values returned by the entity framework query?

var l =  (from s in db.Samples
let action = db.Actions.Where(x => s.SampleID == x.SampleID && x.ActionTypeID == 1).FirstOrDefault()
where s.SampleID == sampleID
select new
{
SampleID = s.SampleID,
SampleDate = action.ActionDate,
}).ToList();

或多或少等同于

var l = db.Samples.Select(s => new
{
s = s,
action = db.Actions.Where(x => s.SampleID == x.SampleID && x.ActionTypeID == 1).FirstOrDefault()
}).Where(x => x.s.SampleID == sampleID).Select(x => new
{
SampleID = x.s.SampleID,
SampleDate = x.action.ActionDate
}).ToList();

这里的ActionDateDateTimeSampleDate也是。这个 LINQ 表达式将被编译器转换为一个大的 Lambda 表达式,并由 Entity Framework SQL Server 端执行。现在...问题是 action 可能变为 null,因此 action.ActionDate 可能为 null(因为表达式不会在本地执行,所以不会有 NullReferenceException),当 null 被放入 时,可能会抛出(将被抛出)异常>SampleDate(我认为是 InvalidCastException)。因此,虽然表达式是类型安全的,但库对它所做的操作会导致表达式生成非类型安全代码(无效转换)

关于c# - C# Lambda 表达式类型安全吗?何时(编译时/运行时)检查它们?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29400634/

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