Hello everyone,

I've been coding small demos to improve my programming skills, and I've run into a problem getting indices of list items which I have been unable to figure out. I'm using C# 4.0, and Visual Studio Express 2010.

I've tried to use the IndexOf(T) method, but intellisense doesn't show it in its list. If I type it in manually, it shows as an error. I had thought that by default there would be a reference equality check and I wouldn't need to do anything explicit to use IndexOf. I've looked around to try and work out some solution, but everything that I can find just shows people using the function straightaway with no difficulty. This suggests to me that I'm missing something very basic and obvious, but whatever it is I am clearly missing it.

My code looks something like this (I can't post the actual code right now, as I'm not at my own computer). Where several Commodities have been instantiated above the function, List<Commodity> l is a list containing those Commodity objects, and c is the Commodity whose index I want:

// Class definition
class Commodity
{
    string name;
    public string Name { get; }

    // Several int and double fields
}

// New .cs file below
// Commodities instantiated here, along with a List<Commodity> which is filled with them

public void SomeFunction(List<Commodity> l, Commodity c)
{
    int index = l.IndexOf(c); // What I want to do,  but can't seem to
    Console.WriteLine("The index of {0} is {1}.", c.Name, index);
}

I have a few guesses about what might be the problem, but none of them have led to a resolution for me:

1. I'm relying too much on intellisense, and if I type the code as above it will compile

2. I need to inherit a particular interface in Commodity and/or overload functions and operators for Commodity for use with the IndexOf method. I've tried the overloading bit, but wouldn't be surprised to find out I did it incorrectly.

3. I need to code a delegate that can handle Commodity objects for use with IndexOf (and, more obviously, FindIndex(Predicate<T>), but I don't think I would need to use that function)

I know my fake code snippet above isn't worth much of anything, but is there anything that needs to be explicitly done to enable use of the IndexOf method of a list containing user defined objects? Or is the issue more likely some issue peculiar to my code that is preventing its use?

Are you using:

using System.Collections.Generic;

Try this:

using System.Collections.Generic;

namespace DW_397605
{
   public class Commodity
   {
      public string strName { get; set; }
      public double dblValue { get; set; }

      public Commodity()
      {
         strName = "";
         dblValue = 0.0;
      }

      public Commodity(string strName, double dblValue)
      {
         this.strName = strName;
         this.dblValue = dblValue;
      }

      public override string ToString()
      {
         return strName + '-' + dblValue.ToString();
      }

      public override bool Equals(object obj)
      {
         return this.ToString().Equals(((Commodity)obj).ToString());
      }


      public override int GetHashCode()
      {
         return this.ToString().GetHashCode();
      }
   }

   public class Program
   {
      static void Main(string[] args)
      {
         List<Commodity> lstCommodity = new List<Commodity>()
         {
            new Commodity("Oranges", 3.3),
            new Commodity("SowBellies", 9.2),
            new Commodity("Gold", 539.2)
         };

         Commodity comGold = new Commodity("Gold", 539.2);
         int iIndex = lstCommodity.IndexOf(comGold);

      }
   }
}

For complex types (like classes), you will need to tell the framework what is a MATCH (or Equals).
Here, I have said that in order to make a match between different Commodity objects, they must match by String value. I also dictated what is the string value and that the Hash is based on that string value (of the object).

commented: Correctly diagnosed my problem, provided a clear solution, and explained how and why it worked. And it worked! +0

I'm almost positive that I am (it's listed in the code I've got online from other files in the project, but I don't have that particular file in front of me).

If I'm not, I'll post that as an update when I get home, but at the moment I assume that I have that directive included.

Thank you for the sample code, I'll try it when I'm home. I bet I did something wrong in overriding Equals for my Commodity class.

Also, what will you do if someone adds a Commodity of the same name with a different value?

You might be better off NOT using indexOf unless the Equals in the class really only returns elements that make it unique (this could already be the case).

For something like that code shown above, I would prefer LINQ to get the target records (or record)

public class Program
   {
      static void Main(string[] args)
      {
         List<Commodity> lstCommodity = new List<Commodity>()
         {
            new Commodity("Oranges", 3.3),
            new Commodity("SowBellies", 9.2),
            new Commodity("Gold", 539.2),
            new Commodity("Gold", 600.5),
            new Commodity("Gold", 644.98)
         };

         Commodity comGold = new Commodity("Gold", 539.2);
         int iIndex = lstCommodity.IndexOf(comGold); //returns 2

         List<Commodity> lstFound = 
         (
            from comm in lstCommodity
            where comm.strName.Equals(comGold.strName)
            select comm
         ).ToList(); // Gets all 3 Gold Commodities
      }
   }

Thank you for the advice, I may end up needing it later on. For now the names will all be unique, there will be exactly one listing for a commodity of a given type as a dictionary key, and the quantity is tracked by value. I may change this later on though.

And I'm sure it's better practice to do as you've described, but LINQ has intimidated me so far. At the moment I'm struggling to get a basic function of a generic collection to work, and have been for a while, so my confidence hasn't been running too high.

An update before I mark the thread solved:

thines01's solution worked! I had incorrectly laid out an override for Equals in my Commodity class.

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.