I expect I'll be able to make a work around but I can't for the life of me understand why this code is not functioning correctly and allowing duplicate entries to be added to the List.
The if
statement condition is never met, even when I drag identical files in from the same location. I don't understand why the "Contains" method isn't matching them up.
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 { }
}
}
I thought I had found another method in which to achieve this using "Distinct"
However, it appears checkedDragDropFiles
& dragDropFiles
have the same amount of entries, including duplicates, except when dragDropFiles
is displayed in a ListBox
it doesn't show them. Why does it do this?
I need to prevent any duplicated list entries, as I would be programmatically creating a menu based off of the list data.
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 { }
}
List<T>
does indeed allow duplicates.
In the case of FileInfo
, the Contains
method will be checking whether the references are the same, but as you are fetching a completely new set of FileInfo
, the references are different.
You need to use the overload of Contains
that takes an IEqualityComparer
- see here.
You can also use HashSet<T>
instead - it is a data structure that does not allow duplicates (though with different references, you will still have this issue).
Because the default Object.Equals
implementation compares objects by reference, not by value. Each FileInfo
instance you create is a different object, as far as .NET is concerned.
You can use LINQ to specify your custom comparison predicate in order to compare objects by different property:
if (dragDropFiles.Any(f => f.Name == file) == false)
{
dragDropFiles.Add(fileInfo);
}
[Edit]
Since strings are compared by value, you might as well filter the list before you project it to FileInfo
, like this:
private void OutputDragDrop(string[] files)
{
dragDropFiles = files.Distinct().Select(f => new FileInfo(f)).ToList();
debugList.DataSource = checkedDragDropFiles;
debugList2.DataSource = dragDropFiles;
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With