【问题标题】:Strange syntax in efef中的奇怪语法
【发布时间】:2016-01-22 12:10:11
【问题描述】:
 var items = context.Items.Where(x => x.IsActive=true).ToList();

为什么是正确的语法和有效的查询?

【问题讨论】:

  • 您必须使用与if 语句相同的语法,即if( obj.IsActive == true)
  • working 是什么意思,您希望这会引发错误吗?
  • 尝试将Items 编译为DBSet<> 会产生error CS0832: An expression tree may not contain an assignment operator。 (外汇 4.5.2,与 2013 年相比)。我编译它的唯一方法是在Where 之前调用ToList,导致它与EF 无关。

标签: c# .net linq lambda entity-framework-6


【解决方案1】:

这是代码中一个非常微妙的错误。 Where Func 需要返回 bool 才有效,但您是在设置值,而不是比较它,所以没有什么可以返回,是吗?

一般说明

代码编译是因为当你在 c# 中赋值时,例如x = 1 该表达式被评估,因此返回,作为分配的值 (1)。

人们有时使用它来懒惰地实例化一个只读属性,例如

private Foo myFoo;

public Foo FooInstance
{
    // set myFoo to the existing instance or a new instance
    // and return the result of the "myFoo ?? new Foo()" expression
    get { return myFoo = myFoo ?? new Foo(); }
}

或将相同的值分配给多个变量:

// set z to 1
// set y to result of "z = 1"
// set x to result of "y = z = 1"
x = y = z = 1;

您的场景

因此,您对列表中的每个条目所做的操作将IsActive 设置为true,并从函数返回相同的true。因此,您最终会得到一个包含所有条目的新列表,并且所有条目都已更改为 Active。

如果您在Where 中使用不是bool 的属性,例如int,则会收到编译错误:

无法将类型“int”隐式转换为“bool”。

将此作为示例 (https://dotnetfiddle.net/9S9NAV)

using System;
using System.Collections.Generic;
using System.Linq;

public class Program
{
    public static void Main()
    {
        var foos = new List<Foo>()
        {
            new Foo(true, 1),
            new Foo(false, 2)
        };

        // works
        var actives = foos.Where(x => x.IsActive=true).ToList();
        // returns 2, not 1!
        Console.WriteLine(actives.Count);

        // compile error
        var ages = foos.Where(x => x.Age = 1).ToList();
    }
}

public class Foo {
    public Foo(bool active, int age)
    {
        this.IsActive = active;
        this.Age = age;
    }

    public bool IsActive { get; set; }
    public int Age { get; set; }
}

【讨论】:

  • 这实际上是一个“尤达条件”可以原谅的场景。 .Where(x =&gt; true == x.IsActive) 会编译,而.Where(x =&gt; true = x.IsActive) 不会,因为你不能分配true。确实非常微妙。当然,.Where(x =&gt; x.IsActive),当然更好,但也许 OP真的想要显式。
【解决方案2】:

您的示例正在工作,因为您正在分配值而不是比较语法正确的值,因此它可以正确编译和执行。请注意,= 用于赋值,== 用于比较。

当你说:

var items = context.Items.Where(x => x.IsActive=true).ToList();

在这里,您不是比较而是将true 值分配给IsActive,这对编译器来说很好,因此您会发现它可以工作。

【讨论】:

    【解决方案3】:

    为什么它有效?

    我认为有效,因为 'x.IsActive = true' 将始终评估为真。所以这不是语法错误。

    换句话说,代码在说:

    • 给我所有物品
    • 将每个项目的 IsActive 设置为 true
    • 返回所有项目 Where(x => x.IsActive)

    因此,当所有项目都设置为 true 时,它​​将返回所有内容。

    【讨论】:

    • Expression&lt;Func&lt;EntityType, bool&gt;&gt; 谓词似乎有问题,请参阅my comment on question
    • 第三点是错误和误导的。 Where(x =&gt; x.IsActive=true)(如果在编译情况下)将返回所有项目,因为它评估为 true,即使 IsActive 最初是 false 并且即使并发进程将 IsActive 设置为 false。它的最后一步不等价于Where(x =&gt; x.IsActive),它的最后一步(假设在运行时执行时可以拆分赋值和返回值)等价于Where(x =&gt; true)
    【解决方案4】:

    使用==检查条件

      var items = context.Items.Where(x => x.IsActive==true).ToList();
    

    或者

      var items = context.Items.Where(x => x.IsActive).ToList();
    

    【讨论】:

    • 我明白。我可以使用 Where(x => x.IsActive)。但我不明白为什么我的例子有效
    • 你所说的not working是什么意思你有什么错误吗?什么是context
    猜你喜欢
    • 1970-01-01
    • 2013-09-05
    • 2017-12-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多