C# linq 的 let 关键字是否比其 into 关键字更好?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/641931/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-04 11:27:15  来源:igfitidea点击:

Is linq's let keyword better than its into keyword?

c#linq

提问by mezoid

I'm currently brushing up on LINQ and am trying to comprehend the difference between the letand using the intokeyword. So far the letkeyword seems better than the intokeyword as far as my understanding goes.

我目前正在复习 LINQ,并试图理解let和 使用into关键字之间的区别。到目前为止,就我的理解而言,let关键字似乎比关键字更好into

The intokeyword essentially allows one to continue a query after a projection. (Just want to state explicitly that I'm not referring to the one for group join.)

into关键字基本上可以让一个投影后继续查询。(只是想明确说明我不是指组加入的那个。)

Given an array of names it allows one to do the following:

给定一组名称,它允许执行以下操作:

var intoQuery =
  from n in names
  select Regex.Replace(n, "[aeiou]", "")
  into noVowel
  where noVowel.Length > 2
  select noVowel;

It takes the result of the select and places it into the noVowelvariable which then allows one to introduce additional where, orderby, and selectclauses. Once the noVowelvariable is created, the nvariable is no longer available.

它需要选择的结果,并将其放置到noVowel变量,然后允许一个引入额外的whereorderbyselect条款。一旦noVowel变量被创建,该n变量不再可用。

The letkeyword, on the other hand, uses temp anonymous types to allow you to reuse more than one variable at a time.

let关键字,而另一方面,使用温度匿名类型,让你在同一时间重复使用一个以上的变量。

You can do the following:

您可以执行以下操作:

var letQuery =
  from n in names
  let noVowel = Regex.Replace(n, "[aeiou]", "")
  where noVowel.Length > 2
  select noVowel;

Both the noVoweland nvariables are available for use (even though I haven't used it in this case).

无论是noVoweln变量都可以使用(尽管我没有在这种情况下使用它)。

While I can see the difference, I can't quite understand why one would want to use the intokeyword over the letkeyword unless one explicitly wanted to make sure that previous variables were not able to be used in latter parts of the query.

虽然我可以看到差异,但我不太明白为什么要在into关键字上使用let关键字,除非明确希望确保不能在查询的后面部分使用先前的变量。

So, is there a good reason why both keywords exist?

那么,这两个关键字存在的理由是否充分?

采纳答案by Jon Skeet

Yes, because they're doing different things, as you've said.

是的,正如你所说,因为他们在做不同的事情。

select ... intoeffectively isolates the whole of one query and lets you use it as the input to a new query. Personally I usuallyprefer to do this via two variables:

select ... into有效地隔离整个查询,并让您将其用作新查询的输入。我个人通常更喜欢通过两个变量来做到这一点:

var tmp = from n in names
          select Regex.Replace(n, "[aeiou]", "");

var noVowels = from noVowel in tmp
               where noVowel.Length > 2
               select noVowel;

(Admittedly in this case I would do it with dot notation in two lines, but ignoring that...)

(诚​​然,在这种情况下,我会在两行中使用点符号来完成,但忽略了这一点......)

Often you don't wantthe whole baggage of the earlier part of the query - which is when you use select ... intoor split the query in two as per the above example. Not only does that mean the earlier parts of the query can't be used when they shouldn't be, it simplifies what's going on - and of course it means there's potentially less copying going on at each step.

通常,您不想要查询早期部分的全部包袱 - 即您select ... into按照上面的示例使用或拆分查询时。这不仅意味着查询的早期部分在不应该使用时不能使用,它还简化了正在发生的事情 - 当然这意味着每一步进行的复制可能会减少。

On the other hand, when you dowant to keep the rest of the context, letmakes more sense.

另一方面,当您确实想要保留上下文的其余部分时,let则更有意义。

回答by leppie

The primary difference is the letinjects the variable into the context/scope, where intocreates a new context/scope.

主要区别是let将变量注入上下文/范围,在其中into创建新的上下文/范围。

回答by Rm558

Wanting to know the difference on DB side, wrote 2 Entity Framework queries.

想知道 DB 端的区别,写了 2 个实体框架查询。

  • Let

    from u in Users
    let noVowel = u.FirstName.Replace("a","").Replace("e","").Replace("i","")
    where noVowel.Length >5
    select new {u.FirstName, noVowel}
    
  • Into

    from u in Users
    select u.FirstName.Replace("a","").Replace("e","").Replace("i","")
    into noVowel
    where noVowel.Length >5
    select noVowel
    
  • from u in Users
    let noVowel = u.FirstName.Replace("a","").Replace("e","").Replace("i","")
    where noVowel.Length >5
    select new {u.FirstName, noVowel}
    
  • 进入

    from u in Users
    select u.FirstName.Replace("a","").Replace("e","").Replace("i","")
    into noVowel
    where noVowel.Length >5
    select noVowel
    

The generated SQLs are almost identical. The SQL is not perfect, same string process code are repeated on 2 places (where and select).

生成的 SQL 几乎相同。SQL 并不完美,相同的字符串处理代码在 2 个地方(where 和 select)重复。

SELECT 1 AS [C1], [Extent1].[FirstName] AS [FirstName], 
REPLACE(REPLACE(REPLACE([Extent1].[FirstName], N'a', N''), N'e', N''), N'i', N'') AS [C2]
FROM [dbo].[User] AS [Extent1]
WHERE ( CAST(LEN(REPLACE(REPLACE(REPLACE([Extent1].[FirstName], N'a', N''), N'e', N''), N'i', N'')) AS int)) > 5
GO

SELECT 
REPLACE(REPLACE(REPLACE([Extent1].[FirstName], N'a', N''), N'e', N''), N'i', N'') AS [C1]
FROM [dbo].[User] AS [Extent1]
WHERE ( CAST(LEN(REPLACE(REPLACE(REPLACE([Extent1].[FirstName], N'a', N''), N'e', N''), N'i', N'')) AS int)) > 5

Here is the SQL generated by LINQ-to-SQL

下面是 LINQ-to-SQL 生成的 SQL

-- Region Parameters
DECLARE @p0 NVarChar(1000) = 'a'
DECLARE @p1 NVarChar(1000) = ''
DECLARE @p2 NVarChar(1000) = 'e'
DECLARE @p3 NVarChar(1000) = ''
DECLARE @p4 NVarChar(1000) = 'i'
DECLARE @p5 NVarChar(1000) = ''
DECLARE @p6 Int = 5
-- EndRegion
SELECT [t1].[FirstName], [t1].[value] AS [noVowel]
FROM (
    SELECT [t0].[FirstName], REPLACE(REPLACE(REPLACE([t0].[FirstName], @p0, @p1), @p2, @p3), @p4, @p5) AS [value]
    FROM [User] AS [t0]
    ) AS [t1]
WHERE LEN([t1].[value]) > @p6
GO

-- Region Parameters
DECLARE @p0 NVarChar(1000) = 'a'
DECLARE @p1 NVarChar(1000) = ''
DECLARE @p2 NVarChar(1000) = 'e'
DECLARE @p3 NVarChar(1000) = ''
DECLARE @p4 NVarChar(1000) = 'i'
DECLARE @p5 NVarChar(1000) = ''
DECLARE @p6 Int = 5
-- EndRegion
SELECT [t1].[value]
FROM (
    SELECT REPLACE(REPLACE(REPLACE([t0].[FirstName], @p0, @p1), @p2, @p3), @p4, @p5) AS [value]
    FROM [User] AS [t0]
    ) AS [t1]
WHERE LEN([t1].[value]) > @p6

Seems Linq-to-SQL is smarterthan Entity Framework, string process performed only once.

似乎 Linq-to-SQL比实体框架更智能,字符串处理只执行一次。

回答by snr

Visualized version of leppie's answer. As can be seen, the compiler yields error in the query with intounlike the latter one as accessing to first variable.

leppie 答案的可视化版本。可以看出,编译器在查询中产生错误,into与后一种访问第一个变量不同。

enter image description here

在此处输入图片说明