0

我在 WinForms 中,在将更改保存到数据库之前,我必须检查使用的 ErrorProvider 是否包含任何显示控件的错误。

我想出了几种方法来做到这一点:

  • ControlContainer 上的一个简单的 foreach 循环:

        foreach (Control c in ctrlcontainer)
        {
            if (epOrderHeader.GetError(c) != string.Empty)
            {
                return true;
            }
        }
        return false;
    
  • 使用 List 扩展方法 Exists(Predicate):

    return (ctrlcontainer.Exists(c => epOrderHeader.GetError(c) != string.Empty);

从胃开始,我预计第二个是最快的,但是使用我发现的 Eqatec Profiler,foreach 循环稍微快一些(在我的情况下大约 1 毫秒)。虽然这无关紧要,但我仍然想知道为什么会发生这种情况?

编译器如何翻译这些方法,为什么第一个更快?

4

3 回答 3

5

在您的情况下,它可能慢 1 毫秒,因为List<T>.Exists调用FindIndex是通过以下方式实现的:

public int FindIndex(int startIndex, int count, Predicate<T> match)
{
    if (startIndex > this._size)
    {
        ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.startIndex, ExceptionResource.ArgumentOutOfRange_Index);
    }
    if (count < 0 || startIndex > this._size - count)
    {
        ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.count, ExceptionResource.ArgumentOutOfRange_Count);
    }
    if (match == null)
    {
        ThrowHelper.ThrowArgumentNullException(ExceptionArgument.match);
    }
    int num = startIndex + count;
    for (int i = startIndex; i < num; i++)
    {
        if (match(this._items[i]))
        {
            return i;
        }
    }
    return -1;
}

所以这不仅仅是一个简单的foreach.

于 2012-07-27T12:41:29.953 回答
1

为什么您希望 List.Exists 方法更快?本质上,它的作用与您的手动检查相同,但它会做额外的一件事,即使用谓词而不是直接检查进行检查。这必须花费一些性能。

于 2012-07-27T12:43:57.320 回答
0

如果您SetError在内部控件中使用该功能,ctrlcontainer那么您可以跟踪发生错误的时间。我建议ErrorProvider使用您的自定义类扩展该类,或者将该提供程序包含在您的一个类中,以便您可以覆盖该SetError方法,即您不需要检查任何内容,因此和之间的比较Existsforeach相关。

于 2012-07-27T12:53:49.233 回答