当你想递归枚举一个分层对象,根据一些标准选择一些元素时,有许多技术的例子,如"展平",然后使用Linq进行过滤:如下所示:
但是,当您枚举类似Form的Controls集合或TreeView的Nodes集合时,我一直无法使用这些类型的技术,因为它们似乎需要一个参数(对于扩展方法),这是一个IEnumerable集合:传入SomeForm.Controls不编译.
我发现最有用的是:
哪个为您提供Control.ControlCollection的扩展方法,其中包含IEnumerable结果,然后您可以使用Linq.
我修改了上面的例子来解析TreeView的节点没有问题.
public static IEnumerable<TreeNode> GetNodesRecursively(this TreeNodeCollection nodeCollection)
{
foreach (TreeNode theNode in nodeCollection)
{
yield return theNode;
if (theNode.Nodes.Count > 0)
{
foreach (TreeNode subNode in theNode.Nodes.GetNodesRecursively())
{
yield return subNode;
}
}
}
}
Run Code Online (Sandbox Code Playgroud)
这是我现在使用扩展方法编写的代码:
var theNodes = treeView1.Nodes.GetNodesRecursively();
var filteredNodes =
(
from n in theNodes
where n.Text.Contains("1")
select n
).ToList();
Run Code Online (Sandbox Code Playgroud)
而且我认为在传递约束的地方可能会有更优雅的方法.
我想知道是否可以一般性地定义这样的过程,以便:在运行时我可以将集合类型以及实际集合传递给泛型参数,因此代码与是否无关它是TreeNodeCollection或Controls.Collection.
我还有兴趣知道是否有任何其他方式(更便宜?fastser?)比第二个链接(上面)中所示,以获得Linq可用的形式的TreeNodeCollection或Control.ControlCollection.
Leppie关于'在第一个(上图)链接的SO帖子中的SelectMany的评论似乎是一个线索.
我对SelectMany的实验是:好吧,称之为"灾难".:)
感谢任何指针.我已经花了几个小时阅读我发现的那些触及这些区域的SO帖子,然后漫无目的地进入像"y-combinator"这样的exotica.一个"谦卑"的经历,我可能会补充:)
我在Rex Logan发布的这个帖子中发现了一些源代码:
... Foredecker在同一个帖子中也发布了一些非常有趣的代码,但它不完整且复杂:我对'跟踪工具知道如何完全实现它不够了...
我能够在WinForms应用程序中成功发布此控制台代码Rex(友好地),以记录各种事件,并将消息推送到调试中非常有用; 我也可以从应用程序代码中清除它.
我似乎无法做的是在打开控制台窗口时(在主窗体加载事件中)可靠地设置控制台窗口的屏幕位置.如果我尝试设置WindowLeft或WindowTop属性,我得到编译阻止System.ArgumentOutOfRangeException错误:
必须设置窗口位置,使当前窗口大小适合控制台的缓冲区,并且数字不能为负数.参数名称:left实际值为#
但是,我可以设置WindowWidth和WindowHeight属性.
我试过移动激活控制台各个位置的代码,包括:
控制台在代码中的所有这些位置都可以正常激活,但看似随机切换屏幕左上象限的位置没有变化.
控制台窗口打开的位置似乎随机变化(主窗体始终在屏幕上的同一位置初始化).
在树视图中上下移动节点的最准确方法是什么.我在每个节点上都有一个上下文菜单,所选节点应该随其所有子节点一起移动.
我正在使用C#.Net 3.5 WinForms
在什么情况下(使用场景)你会选择编写扩展而不是对对象进行子类化?
<完全披露:我不是MS员工; 我个人不知道Mitsu Furota; 我知道这里提到的开源Componax库的作者,但我与他没有任何业务往来; 我不是在创建或计划使用扩展创建任何商业产品:总之:这篇文章来自与我试图(不断)意识到"最佳实践"相关的纯粹智力上的好奇心
我发现扩展方法的想法很"酷",显然你可以用它们做"远远"的事情,就像你在Mitsu Furota(MS)博客文章链接文本中的许多例子一样.
一位私人朋友写了开源Componax图书馆链接文本,那里有一些非凡的设施; 但他完全控制着他的小公司,完全控制代码指南,每一行代码都"通过他的手".
虽然这是我的猜测:我认为/猜测其他问题可能会在大中型软件团队的情况下重新使用Extensions.
在链接文本中查看MS的指南,您会发现:
通常,您可能会比实现自己的方法更频繁地调用扩展方法....一般情况下,我们建议您谨慎实施扩展方法,并且仅在必要时实施.必要时,必须扩展现有类型的客户端代码应通过创建从现有类型派生的新类型来实现.有关更多信息,请参见继承(C#编程指南)....当编译器遇到方法调用时,它首先在类型的实例方法中查找匹配项.如果未找到匹配项,它将搜索为该类型定义的任何扩展方法,并绑定到它找到的第一个扩展方法.
在Ms的链接文本中:
扩展方法没有特定的安全漏洞.它们永远不能用于模拟类型上的现有方法,因为所有名称冲突都被解析为有利于类型本身定义的实例或静态方法.扩展方法无法访问扩展类中的任何私有数据.
对我来说显而易见的因素包括:
我假设你不会写一个扩展,除非你期望它被非常普遍地使用.另一方面:难道你不能对子类别说同样的话吗?
知道我们可以将它们编译成一个单独的dll,并添加已编译的dll,并引用它,然后使用扩展:是"酷",但是这"平衡"编译器中固有的成本首先必须检查才能看到如果实例方法如上所述定义.或者,在"名称冲突"的情况下使用静态调用方法来确保调用扩展而不是实例定义的成本?
频繁使用Extensions会影响运行时性能或内存使用:我不知道.
因此,与子分类相比,我会感谢您的想法,或了解您如何/何时做或不做,使用扩展.
比尔,谢谢
在用户选择退出WinForms程序后,是否有更好的方法来处理执行某项操作的任务:
:[编辑1 响应由"NoBugz评论 ] 在这种情况下,有形式没有控制盒,并有用于把一个间接层中,当用户选择关闭窗体[/编辑1]会发生什么原因
[编辑2:响应GMT +7 1月20日18:35的所有评论 ] 也许使用淡出MainForm可以简单说明您在关闭应用程序时可能需要做什么:用户无法与之交互:它显然与用户决定终止申请有关.[/ edit 2]
(使用某种形式的线程?)(对多线程应用程序有什么影响?)(这段代码"味道不好"吗?)
// 'shutDown is an external form-scoped boolean variable
//
private void Form1_FormClosing(object sender, FormClosingEventArgs e)
{
// make sure we don't block Windows ShutDown
// or other valid reasons to close the Form
if (e.CloseReason != CloseReason.ApplicationExitCall) return;
// test for 'shutDown flag set here
if (shutDown) return;
// cancel closing the Form this time through
e.Cancel = true;
// user choice …Run Code Online (Sandbox Code Playgroud) c# ×5
winforms ×3
treeview ×2
c#-3.0 ×1
console ×1
formclosing ×1
ienumerable ×1
linq ×1
runtime ×1
window ×1