gpt4 book ai didi

c# - 如何提高自定义 BindingList 上 AddRange 方法的性能?

转载 作者:太空狗 更新时间:2023-10-29 20:09:27 25 4
gpt4 key购买 nike

我有一个自定义 BindingList,我想为其创建自定义 AddRange 方法。

public class MyBindingList<I> : BindingList<I>
{
...

public void AddRange(IEnumerable<I> vals)
{
foreach (I v in vals)
Add(v);
}
}

我的问题是大型集合的性能很糟糕。我现在正在调试的案例是尝试添加大约 30,000 条记录,并且花费了无法接受的时间。

在线查看此问题后,问题似乎在于使用 Add 会在每次添加时调整数组的大小。 This answer我认为总结如下:

If you are using Add, it is resizing the inner array gradually as needed (doubling)

我可以在我的自定义 AddRange 实现中做什么来指定 BindingList 需要根据项目计数调整大小,而不是让它在添加每个项目时不断地重新分配数组?

最佳答案

CSharpie 在他的 answer 中解释道性能不佳是由于 ListChanged -事件在每个 Add 之后触发,并展示了一种实现方式 AddRange为您定制BindingList .

另一种方法是实现 AddRange作为 BindingList<T> 的扩展方法的功能.基于 CSharpies 实现:

/// <summary>
/// Extension methods for <see cref="System.ComponentModel.BindingList{T}"/>.
/// </summary>
public static class BindingListExtensions
{
/// <summary>
/// Adds the elements of the specified collection to the end of the <see cref="System.ComponentModel.BindingList{T}"/>,
/// while only firing the <see cref="System.ComponentModel.BindingList{T}.ListChanged"/>-event once.
/// </summary>
/// <typeparam name="T">
/// The type T of the values of the <see cref="System.ComponentModel.BindingList{T}"/>.
/// </typeparam>
/// <param name="bindingList">
/// The <see cref="System.ComponentModel.BindingList{T}"/> to which the values shall be added.
/// </param>
/// <param name="collection">
/// The collection whose elements should be added to the end of the <see cref="System.ComponentModel.BindingList{T}"/>.
/// The collection itself cannot be null, but it can contain elements that are null,
/// if type T is a reference type.
/// </param>
/// <exception cref="ArgumentNullException">values is null.</exception>
public static void AddRange<T>(this System.ComponentModel.BindingList<T> bindingList, IEnumerable<T> collection)
{
// The given collection may not be null.
if (collection == null)
throw new ArgumentNullException(nameof(collection));

// Remember the current setting for RaiseListChangedEvents
// (if it was already deactivated, we shouldn't activate it after adding!).
var oldRaiseEventsValue = bindingList.RaiseListChangedEvents;

// Try adding all of the elements to the binding list.
try
{
bindingList.RaiseListChangedEvents = false;

foreach (var value in collection)
bindingList.Add(value);
}

// Restore the old setting for RaiseListChangedEvents (even if there was an exception),
// and fire the ListChanged-event once (if RaiseListChangedEvents is activated).
finally
{
bindingList.RaiseListChangedEvents = oldRaiseEventsValue;

if (bindingList.RaiseListChangedEvents)
bindingList.ResetBindings();
}
}
}

这样,根据您的需要,您甚至可能不需要自己编写 BindingList -子类。

关于c# - 如何提高自定义 BindingList 上 AddRange 方法的性能?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43331145/

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