`Where` 子句 returns 空列表,即使逻辑测试为 `true`

`Where` clause returns empty list even if the logic test is `true`

我需要显示满足某些条件的项目。

public BindableCollection<BaseTreeItemViewModel> TreeItems
{
    get
    {
        if (_logicTest)
            return (BindableCollection<BaseTreeItemViewModel>)_treeItems.Where(n => _logicTest);
        else
            return _treeItems;
    }
    set
    {
        _treeItems = value;
        NotifyOfPropertyChange(() => TreeItems);
    }
}

实际上在Where子句中会有不同的测试(n.Header == "ABC"),但它甚至对_logicTest不起作用,我们知道是true而使用 Where.

启动行

_treeItems 包含大约 20 个元素,对于 _logicTest=false 它们都被返回。另一方面,对于 _logicTest=true 函数 returns 空集合。

哪里错了?

在此先感谢您的帮助。

编辑

作为@Robert.S ,我用过:

return new BindableCollection<BaseTreeItemViewModel>(_treeItems.Where(n => _logicTest));

它奏效了。谢谢。

什么是_logicTest?一个属性?如果是这样,它可能会在评估 collection 时发生变化。此外,Where 的 return 值是 IEnumerable<T>。仅当您使用 collection 时(例如在 foreach 循环中)才会评估实际值。

你可以尝试在Where的末尾加一个ToList()ToArray()。这样 collection 会立即被评估,您可以查看在执行 getter 的时间点是否真的没有项目。

另一个选项是 VS 调试器。在手表 table 中,您可以使用小刷新图标评估 collection。这样您也可以看到 "real" 项。

但如果您稍后使用 collection(例如在 foreach 循环中)并且 _logicTest 不再为真,则 collection 可能为空。

这是一个简单的例子:

class Program
{
    static bool _logicTest = false;
    static int[] items = new int[] { 1, 2, 3 };

    static void Main(string[] args)
    {
        _logicTest = true;

        var foo = items.Where(n => _logicTest);

        _logicTest = false;

        Console.WriteLine(foo.Count());

        _logicTest = true;

        Console.WriteLine(foo.Count());
    }
}

输出将是: 0 3

在上面的示例中,Count() 将评估 collection 以确定其大小。您可以看到 _logicTest 的值是在此时计算的,而不是在调用 Where 时计算的。

您的情况可能的解决方法是局部变量:

get
{
    bool logicTest = _logicTest;

    if (logicTest)
        return (BindableCollection<BaseTreeItemViewModel>)_treeItems.Where(n => logicTest);
    else
        return _treeItems;
}

局部变量不会改变。但是您应该将 属性 值存储在另一个变量中。因为如果您在 _logicTest 为 false 时访问 属性,您当然会 运行 陷入同样的​​问题。

这是上面的示例和解决方法:

class Program
{
    static bool _logicTest = false;
    static int[] items = new int[] { 1, 2, 3 };

    static void Main(string[] args)
    {
        _logicTest = true;

        var foo = items.Where(n => _logicTest);
        var bar = Items;

        _logicTest = false;

        Console.WriteLine(foo.Count());
        Console.WriteLine(bar.Count());

        _logicTest = true;

        Console.WriteLine(foo.Count());
        Console.WriteLine(bar.Count());
    }

    static IEnumerable<int> Items
    {
        get
        {
            bool logicTest = _logicTest;

            return items.Where(n => logicTest);
        }
    }
}

输出为 0 3 3 3