【问题标题】:How to synchronize a list and an enumerable in an effective way?如何以有效的方式同步列表和可枚举?
【发布时间】:2014-09-11 01:27:52
【问题描述】:

我经常遇到问题,我需要在 C# 中同步两个列表。 例如,我有一个简单的字符串数组。 我想以一种非常简单的方式将这些字符串加载到 Listview 的 Items 列表中。我还想以最少的项目交换来更新列表视图。

示例:

 var strings = new List<string>() { "a", "b", "c", "d" };
 listview1.Items.Synchronize(strings);
 strings.Add("xx");
 listview1.Items.Synchronize(strings); // just create a new item for xx

【问题讨论】:

    标签: c# list lambda enumerable


    【解决方案1】:

    我这里有一个简短的扩展函数,它可以同步两个不同类型的列表。 Lambda 扩展函数进行转换。 用法示例:

            listView1.Items.SyncList(strings, lvItem => lvItem.Tag as string, str => new ListViewItem(str) { Tag = str });
    

    扩展函数定义如下:

        /// <summary>
        /// synchronizes an enumerable with a list with two different types, 
        /// </summary>
        /// <typeparam name="TSource">Type of the elements in the source list</typeparam>
        /// <typeparam name="TDestination">Type of the elements in the destination list</typeparam>
        /// <param name="source">Source</param>
        /// <param name="destination">Destination list</param>
        /// <param name="selector">returns the corresponding source object for the destination list item</param>
        /// <param name="creator">Creates new object for the destination list from the source. The selection function applied on the new object must return the source object. </param>
        public static void SyncList<TSource, TDestination>(this IList destination, IEnumerable<TSource> source, Func<TDestination, TSource> selector, Func<TSource, TDestination> creator)
            where TDestination : class
            where TSource : class
        {
            if (source == null)
                throw new ArgumentNullException("source");
    
            if (destination == null)
                throw new ArgumentNullException("destination");
    
            if (selector == null)
                throw new ArgumentNullException("selector");
    
            if (creator == null)
                throw new ArgumentNullException("creator");
    
            var syncObject = destination.IsSynchronized ? destination.SyncRoot : new object();
    
            lock (syncObject)
            {
                var ExistingItems = destination.OfType<TDestination>().Where(d => selector(d) != null).ToDictionary(d => selector(d));
    
                foreach (var s in source)
                {
                    if (!ExistingItems.Remove(s)) // s does not exist yet in the destination list
                    {
                        var NewObject = creator(s);
    
                        if (selector(NewObject) != s)
                            throw new ArgumentException("the selector must return the creation object of the new item");
    
                        destination.Add(creator(s));
                    }
                }
    
                var RemovedItems = ExistingItems.Values;
    
                if (RemovedItems.Count == destination.Count)
                    destination.Clear();
                else
                    foreach (var i in RemovedItems)
                    {
                        destination.Remove(i);
                    }
    
            }
    
        }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2014-02-13
      • 1970-01-01
      • 1970-01-01
      • 2013-05-16
      • 1970-01-01
      • 2018-03-29
      • 1970-01-01
      • 2014-02-13
      相关资源
      最近更新 更多