`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
我需要显示满足某些条件的项目。
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