gpt4 book ai didi

c# - 为什么 List.ForEach 在循环结束后检查版本?

转载 作者:行者123 更新时间:2023-11-30 20:39:05 26 4
gpt4 key购买 nike

我们正在查看 List.ForEach method 的源代码实现如下:

public void ForEach(Action<T> action) {
if( action == null) {
ThrowHelper.ThrowArgumentNullException(ExceptionArgument.match);
}
Contract.EndContractBlock();

int version = _version;

for(int i = 0 ; i < _size; i++) {
if (version != _version && BinaryCompatibility.TargetsAtLeast_Desktop_V4_5) {
break;
}
action(_items[i]);
}

if (version != _version && BinaryCompatibility.TargetsAtLeast_Desktop_V4_5)
ThrowHelper.ThrowInvalidOperationException(ExceptionResource.InvalidOperation_EnumFailedVersion);
}

我们找不到两次检查版本的原因。我们认为可以抛出异常而不是 break。我们还认为,如果列表在循环完成后、检查执行之前被另一个线程修改,则最终检查可能会导致不必要的异常。

为什么循环不是这样实现的:

for(int i = 0 ; i < _size; i++) {
if (version != _version && BinaryCompatibility.TargetsAtLeast_Desktop_V4_5) {
ThrowHelper.ThrowInvalidOperationException(ExceptionResource.InvalidOperation_EnumFailedVersion);
}
action(_items[i]);
}

最佳答案

检查实质上是验证对操作委托(delegate)的最后一次调用不会更改集合。

由于这是契约(Contract)的一部分,根据 remarks in the documentation :

Modifying the underlying collection in the body of the Action delegate is not supported and causes undefined behavior.

那么这是完全合法的,也是正确的做法。

此外,他们已经将异常从循环内部抛出到循环之后的代码中,以避免重复那些有意义的代码。

话虽如此,代码可以这样写:

for (int i = 0 ; i < _size; i++)
{
action(_items[i]);
if (version != _version && BinaryCompatibility.TargetsAtLeast_Desktop_V4_5)
ThrowHelper.ThrowInvalidOperationException(ExceptionResource.InvalidOperation_EnumFailedVersion);
}

代码的当前外观可能是由于反编译或类似的原因,它复制了 if 部分而不是对 ThrowHelper 的调用。

关于c# - 为什么 List<T>.ForEach 在循环结束后检查版本?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34608009/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com