c# - 为什么 List<T>.ForEach() 实现 for 循环?

标签 c# .net list foreach

我不明白为什么 List<T>.ForEach()扩展方法实现了一个 for在引擎盖下循环。这打开了修改集合的可能性。正常 foreach在这种情况下肯定会抛出异常 ForEach()应该以同样的方式使用react吗?

如果您出于任何原因必须改变一个集合,那么您肯定应该手动迭代 for 中的集合循环?

foreach 之间似乎有一点语义上的矛盾。和 List<T>.ForEach() .

我错过了什么吗?

最佳答案

只有 BCL 团队的一名成员可以肯定地告诉我们,但这可能只是一个疏忽 List<T>.ForEach允许您修改列表。

首先,David B 的回答对我来说没有意义。这是List<T> ,而不是 C#,它会检查您是否修改了 foreach 中的列表循环并抛出 InvalidOperationException如果你这样做。这与您使用的语言无关。

其次,documentation 中有这个警告:

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

我发现 BCL 团队不太可能想要像 ForEach 这样简单的方法有未定义的行为。

第三,从 .NET 4.5 开始,List<T>.ForEach 抛出 InvalidOperationException如果代表修改列表。如果程序依赖于旧行为,it will stop working当它被重新编译为目标 .NET 4.5 时。 Microsoft 愿意接受这一重大更改这一事实强烈表明原始行为是无意的,不应依赖。

作为引用,这里是List<T>.ForEach在 .NET 4.0 中实现,直接来自引用源:

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

    for(int i = 0 ; i < _size; i++) {
        action(_items[i]);
    }
}

下面是它在 .NET 4.5 中的变化:

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);
}

关于c# - 为什么 List<T>.ForEach() 实现 for 循环?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11493330/

相关文章:

c# - 在格式错误的 xml 中转义属性中的内部引号

c# - MDI 子级在 MDI 父级中的分布

C# 设计 - 如何在没有空接口(interface)的情况下将类和枚举分组到列表中?

c# - 如何匹配正则表达式中包含^的字符串?

c# - 使用 SubSonic 寻呼

c# - 如何处理对azure服务总线的多次访问

.net - "Official"将程序集部署到 GAC 的方法?

python - 根据列表替换字符串中的子字符串

java - 进一步排序一个已经排序的列表

c# - Web Api Controller 中无法识别 Json 方法