c# - Collection 底层的 ReadOnlyCollection 属性在迭代时被修改

标签 c# readonly-collection

我有以下属性:

private static Collection<Assembly> _loadedAssemblies = new Collection<Assembly>();
    internal static ReadOnlyCollection<Assembly> LoadedAssemblies
    {
        get { return new ReadOnlyCollection<Assembly>(_loadedAssemblies); }
    }

在另一个类中,我循环遍历 LoadedAssemblies

foreach (Assembly assembly in ResourceLoader.LoadedAssemblies)

在遍历程序集时,底层集合 (_loadedAssemblies) 有时会发生变化,这会导致 System.InvalidOperationException。使 LoadedAssemblies 安全的首选方法是什么?我无法重现该问题,所以我无法尝试。

可以吗?

internal static ReadOnlyCollection<Assembly> LoadedAssemblies
    {
        get { return new ReadOnlyCollection<Assembly>(_loadedAssemblies.ToList()); }
    }

编辑

    public static void Initialize()
    {

        foreach (Assembly assembly in AppDomain.CurrentDomain.GetAssemblies())
        {
            AddAssembly(assembly);
        }
        AppDomain currentDomain = AppDomain.CurrentDomain;
        currentDomain.AssemblyLoad += OnAssemblyLoad;
    }

    private static void OnAssemblyLoad(object sender, AssemblyLoadEventArgs args)
    {
        AddAssembly(args.LoadedAssembly);
    }

    private static void AddAssembly(Assembly assembly)
    {
        AssemblyName assemblyName = new AssemblyName(assembly.FullName);
        string moduleName = assemblyName.Name;

        if (!_doesNotEndWith.Exists(x => moduleName.EndsWith(x, StringComparison.OrdinalIgnoreCase)) &&
            _startsWith.Exists(x => moduleName.StartsWith(x, StringComparison.OrdinalIgnoreCase)))
        {
            if (!_loadedAssemblies.Contains(assembly))
            {
                _loadedAssemblies.Add(assembly);
            }
        }
    }

最佳答案

您在问题中提出的建议将会奏效。即:

internal static ReadOnlyCollection<Assembly> LoadedAssemblies
{
    get { return new ReadOnlyCollection<Assembly>(_loadedAssemblies.ToList()); }
}

原因是您的问题来自 _loadedAssemblies 在您枚举它时被更改。这当然会发生,因为 ReadOnlyCollection 只是 _loadedAssemblies 的包装器,它使用基础集合的枚举器。

如果您执行 _loadedAssemblies.ToList(),那么这将创建一个新列表,该列表是原始 _loadedAssemblies 的副本。它在创建时将具有所有相同的元素,但永远不会再次更新(因为您甚至没有对新集合的引用,您无法修改它)。这意味着当 _loadedAssemblies 更新时,您在 ReadOnlyCollection 中的新列表很幸运地不知道该更改,因此您的枚举将毫无问题地继续到最后。

关于c# - Collection 底层的 ReadOnlyCollection 属性在迭代时被修改,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45688470/

相关文章:

c# - 对 IReadOnlyCollection 的隐式/显式转换混淆

c# - 如何防止更改 IReadOnlyList<T>?

c# - StreamReader 不会停止读取 C#

C# List Group By 和 where

c# - 没有添加的公共(public)列表

.net - 为什么 SortedList(TKey,TValue).Keys 属性是 IList(TKey) 而不是 ReadOnlyCollection(TKey)?

c# - 如何解决参数字典包含不可为空类型 'productId'的参数 'System.Int32'的空条目

c# - 如何使用 EPPLus 库清除 Excel 中的行?

c# - 泛型与 IBindingList 和 BindingList<T> 混淆

c# - 返回 List<T> 的只读包装器的哪种方式更可取?