2

我们的项目目前使用 2 种方法在页面内查找控件。第一种是递归使用 .FindControl。 另一种是像这样使用LINQ:

(from n in Page.Controls.Cast<Control>().Descendants(c => c.Controls.Cast<Control>())
 where (n as Label != null && n.ID == "TaskIDLabel")
 select n).First() as Label;

哪个使用此扩展:

static public IEnumerable<T> Descendants<T>(this IEnumerable<T> source,
                                            Func<T, IEnumerable<T>> DescendBy)
{
    foreach (T value in source)
    {
        yield return value;

        foreach (T child in DescendBy(value).Descendants<T>(DescendBy))
        {
            yield return child;
        }
    }
}

这两种方法哪个更好?哪个更快?

4

3 回答 3

3

我可以进行测试并发现秒表类快速且易于使用,并且会在大约 30 秒的努力中准确地告诉您需要了解的内容。让我们知道你发现了什么。

http://www.dotnetperls.com/stopwatch

http://msdn.microsoft.com/en-us/library/system.diagnostics.stopwatch.aspx

我建议要么在每个秒表的末尾添加断点,要么只使用 Response.Write 输出值,因为你只是在调试。

编辑: 您实际上是否注意到任何性能问题,或者您是否正在尝试标准化并确保选择正确的方法?

如果您使用 .Net 4,具体取决于控件的数量,您或许可以考虑使用并行扩展来更快地迭代列表,这可能会有所帮助。查找“AsParallel()”

于 2011-04-04T16:42:49.863 回答
1

您的代码FindControl在功能上有所不同。他们不做同样的事情。

FindControl不执行深度搜索,而您的代码执行。来自MSDN

只有当控件直接包含在指定容器中时,此方法才会找到控件;也就是说,该方法不会在控件内的控件层次结构中进行搜索。

哪个更好?这取决于。如果您不知道控件在页面上的哪个位置,那么您的递归方法可以找到它。

但是,假设您在 Panel (ID="MyPanel") 中有两个控件:自定义 UserControl (ID="MyControl") 和 Label (ID="MyName")。如果您调用 `MyPanel.FindControl("MyName"),您将在面板中返回预期的标签。如果您使用您的函数,它将首先在 MyControl 中搜索 ID="MyName" 的标签。因此,如果 MyControl 恰好还包含 ID="MyName" 的标签,则将改为返回它。如果控件碰巧生成了一个与您正在寻找的具有相同 ID 的子控件,这可能是出乎意料的。

至于性能,您的方法执行更深入的搜索,因此它有可能成为更昂贵的操作。

于 2011-04-04T16:40:51.463 回答
1

这是一个直截了当的答案,但我想说你手写的代码将生成的 IL 代码可能与 FindControl 使用的代码非常相似。然而,一个主要区别是 Microsoft 代码通常针对 CLR 进行了极大优化,利用大量编译器提示比大多数手写代码执行得更快。

所以我个人会在递归调用中使用 FindControl。

于 2011-04-04T16:43:31.007 回答