是否“选择新的”? 在 linq 中触发评估/加载?
我目前正在尝试创建一个实现 IEnumerable
IEnumerable<Tab> tabs = GetTabs();
IEnumerable<TabNode> tabNodes = tabs.AsHierarchy().WithStartLevel(2).WithMaxDepth(5);
所以,关于yield语句,我想知道我是否可以在我的NodeHierarchy:IEnumerable
类中做这样的事情:
private IEnumerable<TabNode> _nodes;
public NodeHierarchy(IEnumerable<Tab> tabs)
{
_nodes = CreateHierarchy(tabs);
}
public IEnumerable<TabNode> CreateHierarchy(IEnumerable<Tab> tabs)
{
/* About this block: I'm trying to find the top level
nodes of the first tab collection, maybe this is done poorly? */
var tabIds = tabs.Select(t => t.TabID);
IEnumerable<TabNode> nodes = from tab in tabs
where !tabIds.Contains(tab.ParentId)
select new TabNode {
Tab = node,
ChildNodes = CreateHierarchy(tabs, node.TabID, 1),
Depth = 1 };
return nodes;
}
或者我是否必须做这样的事情:
private IEnumerable<TabNode> _nodes;
public NodeHierarchy(IEnumerable<Tab> tabs)
{
_nodes = CreateHierarchy(tabs);
}
public IEnumerable<TabNode> CreateHierarchy(IEnumerable<Tab> tabs)
{
var tabIds = tabs.Select(t => t.TabID);
IEnumerable<Tab> startingNodes = from tab in tabs
where !tabIds.Contains(tab.ParentId)
select tab;
foreach(Tab node in startingNodes)
{
yield return
new TabNode()
{
Tab = node,
ChildNodes = CreateHierarchy(tabs, node.TabID, 1),
Depth = 1
};
}
I'm currently trying to create a class which implements IEnumerable<T>
in order to construct a Hierarchy from a flat list of objects which have references to each other through a ParentId property. I'd like to write a fluent interface for this so I can do something like this
IEnumerable<Tab> tabs = GetTabs();
IEnumerable<TabNode> tabNodes = tabs.AsHierarchy().WithStartLevel(2).WithMaxDepth(5);
So, about the yield statement, I wonder whether I could do something like this within my NodeHierarchy : IEnumerable<TabNode>
class:
private IEnumerable<TabNode> _nodes;
public NodeHierarchy(IEnumerable<Tab> tabs)
{
_nodes = CreateHierarchy(tabs);
}
public IEnumerable<TabNode> CreateHierarchy(IEnumerable<Tab> tabs)
{
/* About this block: I'm trying to find the top level
nodes of the first tab collection, maybe this is done poorly? */
var tabIds = tabs.Select(t => t.TabID);
IEnumerable<TabNode> nodes = from tab in tabs
where !tabIds.Contains(tab.ParentId)
select new TabNode {
Tab = node,
ChildNodes = CreateHierarchy(tabs, node.TabID, 1),
Depth = 1 };
return nodes;
}
or whether I would have to do something like this:
private IEnumerable<TabNode> _nodes;
public NodeHierarchy(IEnumerable<Tab> tabs)
{
_nodes = CreateHierarchy(tabs);
}
public IEnumerable<TabNode> CreateHierarchy(IEnumerable<Tab> tabs)
{
var tabIds = tabs.Select(t => t.TabID);
IEnumerable<Tab> startingNodes = from tab in tabs
where !tabIds.Contains(tab.ParentId)
select tab;
foreach(Tab node in startingNodes)
{
yield return
new TabNode()
{
Tab = node,
ChildNodes = CreateHierarchy(tabs, node.TabID, 1),
Depth = 1
};
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
不,
select new
不会触发评估。 这将映射到对以下内容的调用:请注意,
Select
(至少对于 LINQ-to-Objects)本质上是这样的:这里的关键点是它评估惰性 - 不是一次全部评估。
两种方法都应该具有可比性 - 唯一的区别是,如果没有
yield return
,某些 代码将立即运行 - 但只有构建.Where(.. .).Select(...)
链 - 在您开始迭代结果之前,它实际上不会处理行。此外,根据数据源,该方法实际上可以更有效 - 例如,使用 LINQ-to-SQL 后端,因为 TSQL 生成器可以跳过不必要的列。
No,
select new
will not trigger evaluation. This will map to a call to:And note that
Select
(for LINQ-to-Objects, at least) is essentially something like:The key point here being that it evaluates lazy - not all at once.
Either approach should be comparable - the only difference is that without
yield return
, some code will run immediately - but only the code to build the.Where(...).Select(...)
chain - it won't actually process the rows until you start iterating the result.Furthermore, depending on the data source, that approach can actually be more efficient - for example, with a LINQ-to-SQL backend, as the TSQL generator can skip the unnecessary columns.