防止重复列表<T>条目

neg*_*ble 11 c# collections list duplicates

我希望我能够解决这个问题,但是我无法理解为什么这段代码无法正常运行并允许将重复的条目添加到List中.

if声明条件从未谋面,甚至当我在拖地从相同位置相同的文件.我不明白为什么"包含"方法不匹配它们.

public class Form1:Form {
    private List<FileInfo> dragDropFiles = new List<FileInfo>();

    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 { }
    }
}
Run Code Online (Sandbox Code Playgroud)

我以为我找到了另一种使用"Distinct"实现此目的的方法

但是,它显示checkedDragDropFilesdragDropFiles具有相同数量的条目,包括重复项,除非在其中dragDropFiles显示ListBox它不显示它们.为什么这样做?

我需要防止任何重复的列表条目,因为我将以编程方式创建基于列表数据的菜单.

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<FileInfo> checkedDragDropFiles = dragDropFiles.Distinct().ToList();

        debugList.DataSource = checkedDragDropFiles;
        debugList2.DataSource = dragDropFiles;
        //PopulateContextMenu();
    }
    catch { }
}
Run Code Online (Sandbox Code Playgroud)

Ode*_*ded 18

List<T> 确实允许重复.

在这种情况下FileInfo,该Contains方法将检查引用是否相同,但是当您获取一组全新FileInfo的引用时,引用是不同的.

您需要使用重载的Contains接受一个IEqualityComparer-看这里.

您也可以使用HashSet<T>- 它是一种不允许重复的数据结构(尽管使用不同的引用,您仍然会遇到此问题).

  • `HashSet <T>`很好,因为如果元素已经存在,它不会抛出异常......就像那样! (3认同)

Gro*_*roo 6

因为默认Object.Equals实现按引用比较对象,而不是按值.FileInfo就.NET而言,您创建的每个实例都是不同的对象.

您可以使用LINQ指定自定义比较谓词,以便按不同属性比较对象:

if (dragDropFiles.Any(f => f.Name == file) == false)
{
    dragDropFiles.Add(fileInfo);
}
Run Code Online (Sandbox Code Playgroud)

[编辑]

由于字符串是按值进行比较的,因此您可以将项目投射到列表之前对其进行过滤FileInfo,如下所示:

private void OutputDragDrop(string[] files)
{
    dragDropFiles = files.Distinct().Select(f => new FileInfo(f)).ToList();
    debugList.DataSource = checkedDragDropFiles;
    debugList2.DataSource = dragDropFiles;
}
Run Code Online (Sandbox Code Playgroud)