DDD888 发表于 27-2-2015 13:56:17

System.Collections.Generic.List.ForEach

我看不懂_version,为啥要在for loop里重复多次check啊?难道_version会变吗?


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

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

superopengl 发表于 27-2-2015 14:14:15

你可以看到在List.Add, List.set_this, List.InsertRage, List.RemoveAt里都有this._version++的code。就是说每次更改List时_version就会递增。ForEach里的version check就是每次循环检查一下是不是有其它线程更改了当前List。保持一致性。System.Collections.Generic namespace下的collection的非static操作都是线程不安全的。

DDD888 发表于 28-2-2015 19:59:10

谢谢,我没读其他代码

有没有其他类list更好,ForEach没有冗余检测操作?我写的代码不需要关心其他thread修改list

finger|regnif 发表于 1-3-2015 17:12:54

本帖最后由 finger|regnif 于 2-4-2024 14:35 编辑

superopengl 发表于 3-3-2015 05:28:58

finger|regnif 发表于 1-3-2015 16:12
单线程也有可能出现问题. 比如可能会写这样的看起来正确的代码:

var toRemove = myList.Where(Predicato ...

正确。在forEach里更改当前Collection本身就是bad practice,而且运行一定抛异常。

mason00 发表于 3-3-2015 06:37:18

自己用for呗

cais 发表于 4-3-2015 01:58:39

这个_version看起来是从外面来的。被改变也是有可能的。
页: [1]
查看完整版本: System.Collections.Generic.List.ForEach