防止重复列表条目
我希望我能够解决这个问题,但是我无法理解为什么这段代码无法正常运行并允许将重复的条目添加到List中。
即使我从同一位置拖动相同的文件,也永远不会满足if
语句条件。 我不明白为什么“包含”方法不匹配它们。
public class Form1:Form { private List dragDropFiles = new List(); private void Form1_DragDrop(object sender, DragEventArgs e) { try { if (e.Data.GetDataPresent(DataFormats.FileDrop)) { string[] files = (string[])e.Data.GetData(DataFormats.FileDrop); OutputDragDrop(files); } } catch { } } private void Form1_DragEnter(object sender, DragEventArgs e) { if (e.Data.GetDataPresent(DataFormats.FileDrop)) e.Effect = DragDropEffects.Copy; else e.Effect = DragDropEffects.None; } private void OutputDragDrop(string[] files) { try { foreach (string file in files) { FileInfo fileInfo = new FileInfo(file); if (dragDropFiles.Contains(fileInfo)) { dragDropFiles.Remove(fileInfo); } dragDropFiles.Add(fileInfo); } PopulateContextMenu(); } catch { } } }
我以为我找到了另一种使用“Distinct”实现此目的的方法
但是,看起来checkedDragDropFiles
和checkedDragDropFiles
具有相同数量的条目,包括重复项,除非在ListBox
显示checkedDragDropFiles
时它不显示它们。 为什么这样做?
我需要防止任何重复的列表条目,因为我将以编程方式创建基于列表数据的菜单。
private void OutputDragDrop(string[] files) { try { foreach (string file in files) { FileInfo fileInfo = new FileInfo(file); //if (dragDropFiles.Contains(fileInfo)) //{ // dragDropFiles.Remove(fileInfo); //} dragDropFiles.Add(fileInfo); } List checkedDragDropFiles = dragDropFiles.Distinct().ToList(); debugList.DataSource = checkedDragDropFiles; debugList2.DataSource = dragDropFiles; //PopulateContextMenu(); } catch { } }
List
确实允许重复。
对于FileInfo
, Contains
方法将检查引用是否相同,但是当您获取一组全新的FileInfo
,引用是不同的。
您需要使用Contains
IEqualityComparer
的Contains
的重载 – 请参阅此处 。
您也可以使用HashSet
– 它是一个不允许重复的数据结构(尽管使用不同的引用,您仍然会遇到此问题)。
因为默认的Object.Equals
实现通过引用而不是按值来比较对象。 就.NET而言,您创建的每个FileInfo
实例都是一个不同的对象。
您可以使用LINQ指定自定义比较谓词,以便按不同属性比较对象:
if (dragDropFiles.Any(f => f.Name == file) == false) { dragDropFiles.Add(fileInfo); }
[编辑]
由于字符串是按值进行比较的,因此您可以在将其投影到FileInfo
之前过滤列表,如下所示:
private void OutputDragDrop(string[] files) { dragDropFiles = files.Distinct().Select(f => new FileInfo(f)).ToList(); debugList.DataSource = checkedDragDropFiles; debugList2.DataSource = dragDropFiles; }
您可以轻松地为同一个文件创建多个FileInfo实例 – 因此您的列表将仅包含每个FileInfo一次,但它可能具有多个用于smae文件的FileInfos。
所以你最好的选择可能是使用Hashtable并使用FileInfo.FullName作为标准。
如果您希望ICollection
的实现不允许重复,同时仍保留排序,请考虑使用SortedSet
而不是List
。