简体   繁体   中英

Removing duplicates from fileinfo list

I am populating a combobox from a fileinfo list - but it gives me duplicates when I add --Please Select-- at the start of the index:

string[] filters = new[] { "*.html", "*.htm" };
string[] gettemplates = filters.SelectMany(f => Directory.GetFiles(emailTemplatesFolder, f)).ToArray();

List<System.IO.FileInfo> templates = new List<System.IO.FileInfo>();
FileInfo fi = new FileInfo("---Please Select---");
templates.Insert(0, fi);

foreach (string file in gettemplates)
{                        
   System.IO.FileInfo t = new System.IO.FileInfo(file);
   templates.Add(t);
}

BindingSource bs = new BindingSource();
bs.DataSource = templates;

comboEmailTemplates.DisplayMember = "Name";
comboEmailTemplates.ValueMember = "Filepath";
comboEmailTemplates.DataSource = bs;

Have tried

 List System.IO.FileInfo unique = templates.Distinct().ToList();

and binding to the new source but it still brings in the duplicates.

What am I doing wrong?

Thanks

Jen

When using Distinct it uses the default comparer of the type in question. In your case it is of FileInfo which doesn't override the defaults of Object . Therefore the comparison is by reference. As each item in your list is a different instance (use of the new keyword) they are not the same.

A quick solution - have the strings as a distinct collection:

filters.SelectMany(f => Directory.GetFiles(emailTemplatesFolder, f)).Distinct().ToArray();

All together I'd refactor a bit:

var templates = new List<FileInfo>();
templates.Insert(0, new FileInfo("---Please Select---"););

templates.AddRange(filters.SelectMany(f => Directory.GetFiles(emailTemplatesFolder, f))
                          .Distinct()
                          .Select(f => new FileInfo(f)));
BindingSource bs = new BindingSource();
bs.DataSource = templates;

The problem is all elements in your list are different objects, and the Distinct() LINQ method will compare them on reference. The solution is to implement an IEqualityComparer and use an override of Distinct() method. An example, if you want to compare them by name.

public class FileNameComparer : IEqualityComparer<FileInfo>
{
   public bool Equals(FileInfo x, FileInfo y)
   {
      if (x == y)
      {
         return true;
      }

      if (x == null || y == null)
      {
         return false;
      }

      return string.Equals(x.Name, y.Name, StringComparison.OrdinalIgnoreCase);
   }

   public int GetHashCode (FileInfo obj)
   {
      return obj.Name.GetHashCode ();
   }
}

and then use it like this

List System.IO.FileInfo unique = templates.Distinct(new FileNameComparer()).ToList();

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM