2

I wrote this code to check a Collection to find objects with the same value, but it returns the index -1 and causes an IndexOutOfRangeException. Can anyone help find my mistake?

List<MyFileInfo> selectedItemsList = dataInbox.SelectedItems.Cast<MyFileInfo>().ToList();
foreach (MyFileInfo file in selectedItemsList)
{
    if (!file.AdditionalColumn.Equals(""))
    {
        inDB = new ZeichnungInDB(file.FileInfo.Name, file.AdditionalColumn, file.AdditionalColumn2, file.FileInfo.Extension,
        txtAenderungExtern.Text, file.AdditionalColumn3,
        int.Parse(txtProjectNumber.Text), txtTag.Text, bemerkung, anhangPfad, cmbDokumententyp.Text, false);
        if (zeichnungCollection.Count > 0)
        {
            if (zeichnungCollection[zeichnungCollection.IndexOf(inDB)].Zeichnungsnummer != inDB.Zeichnungsnummer &&
            zeichnungCollection[zeichnungCollection.IndexOf(inDB)].Extension != inDB.Extension)
            {
                zeichnungCollection.Add(inDB);
            }
            else
            {
                sameData = true;
            }
        }
        else
        {
            zeichnungCollection.Add(inDB);
        }
    }
}
PaulG
  • 13,871
  • 9
  • 56
  • 78
Only3lue
  • 245
  • 1
  • 3
  • 20

2 Answers2

2

You are creating a new instance of an object, you are then attempting to find the Index of that object where your collection actually holds reference to a different instance.

You can use FindIndex with ToList to pass in a predicate and find the index of the object where a condition is true. https://msdn.microsoft.com/en-us/library/x1xzf2ca(v=vs.110).aspx

Alternatively, you could use FirstOrDefault with some null checking if you'd prefer to keep it as an ObservableCollection https://msdn.microsoft.com/en-us/library/bb340482(v=vs.110).aspx

ColinM
  • 2,622
  • 17
  • 29
2

Assume MyFileInfo looks like this:

public class MyFileInfo
{
    public string Name { get; set; }
}

Now try to use it like this:

List<MyFileInfo> selectedItemsList = new List<MyFileInfo>
    {
        new MyFileInfo { Name = "One" },
        new MyFileInfo { Name = "Two" },
    };

MyFileInfo two = new MyFileInfo { Name = "Two" };
int index = selectedItemsList.IndexOf(two); // index == -1

IndexOf is looking for identical instance references, which it doesn't find, and so returns -1.

If you do this instead, though, the references are the same:

MyFileInfo two = new MyFileInfo { Name = "Two" };
List<MyFileInfo> selectedItemsList = new List<MyFileInfo>
    {
        new MyFileInfo { Name = "One" },
        two,
    };

int index = selectedItemsList.IndexOf(two); // index == 1

This is due to the default implementation of the Equals method, which just compares for reference equality. If you override Equals in MyFileInfo, you get to decide what Equals means. For example:

public class MyFileInfo
{
    public string Name { get; set; }

    public override bool Equals(object obj)
    {
        if (obj?.GetType() == typeof(MyFileInfo))
        {
            return ((MyFileInfo)obj).Name == Name;
        }

        return false;
    }
}

This will find any object with the same Name.

Using methods with predicates is another option, which allows you to define what Equals means on the fly, e.g.:

List<MyFileInfo> selectedItemsList = new List<MyFileInfo>
    {
        new MyFileInfo { Name = "One" },
        new MyFileInfo { Name = "Two" },
    };

MyFileInfo two = new MyFileInfo { Name = "Two" };
int index = selectedItemsList.FindIndex(info => info.Name == two.Name);

Which also finds items with the same Name.

Note: If you override Equals in any class that might be used as a dictionary (hash table) key, you should also override GetHashCode. Here's a discussion. And there are considerations for implementing various other interfaces such as IEquatable<T>, especially for structs (value objects), which I guess is out of scope for this question.

Edit: Why it's important to override GetHashCode when overriding Equals

Community
  • 1
  • 1
Petter Hesselberg
  • 5,062
  • 2
  • 24
  • 42
  • Hm, this solution looks interesting, too. Maybe I will check that out after the weekend, if I can make that work for my problem. – Only3lue Nov 25 '16 at 11:05