9

I want to compare a property instead of the entire object using a List[MyObject]. I therefore use IEquatable[MyObject] but the compiler still wants MyObject instead of the string property. Why?

Here is what I got:

public class AnyClass
{
    public List<AnyOtherClass> MyProperty { get; set; }        
    public string AnyProperty { get; set; }

    public AnyClass(string[] Names, string[] Values, string AnyProperty)
    {
        this.AnyProperty = AnyProperty;
        this.MyProperty = new List<AnyOtherClass>();
        for (int i = 0; i < Names.Length; i++)
            MyProperty.Add(new AnyOtherClass(Names[i], Values[i]));
    }
}

public class AnyOtherClass : IEquatable<string>
{
    public AnyOtherClass(string Name, string Values)
    {
        this.Name = Name;
        this.Values = Values.Split(';').ToList();
    }

    public string Name { get; set; }
    public List<string> Values { get; set; }

    public bool Equals(string other)
    {
        return this.Name.Equals(other);
    }
}

    private void DoSomething()
    {
        string[] Names = new string[] { "Name1", "Name2" };
        string[] Values = new string[] { "Value1_1;Value1_2", "Value2" };
        AnyClass ac = new AnyClass(Names, Values, "any Property");

        if (ac.MyProperty.Contains("Name1")) //Problem is here...
            //do something
    }
UNeverNo
  • 549
  • 3
  • 8
  • 29

5 Answers5

24

You might want to try using this :

myList.Any(x => x.someProperty == someValue);

from MSDN : http://msdn.microsoft.com/en-us/library/bb534972.aspx

Determines whether any element of a sequence satisfies a condition.

The x => x.someProperty == someValue is called a lambda expression in case you didn't know.

And note that you can use this on anything implementing IEnumerable, so that doesn't restrict you to List<T>.

Pacane
  • 20,273
  • 18
  • 60
  • 97
  • 2
    I was just about to post this. `Any` will stop evaluating when the first match is found, whereas `Where` will keep going to get a complete list (and potentially take a lot longer to run). – Jon B Dec 03 '12 at 14:41
  • Okay I'll head for using LINQ here. – UNeverNo Dec 03 '12 at 15:02
4

sounds like you should be doing a Where rather than a Contains

string value = "test";
ac.Where(ac => ac.Name1 == value || ac.Name2 == value);

The reason ac.MyProperty.Contains("Name1") is blowing up is because MyProperty is a List<AnyOtherClass> and not a string

hunter
  • 62,308
  • 19
  • 113
  • 113
  • Yes, LINQ works here, but I still don't understand why IEquatable is not working. – UNeverNo Dec 03 '12 at 14:43
  • +1 just because *sounds like you should be doing a Where rather than a Contains* sentence helped me so much! – Izzy Apr 02 '15 at 14:17
3

It should be IEquatable<AnyOtherClass> not <string>. You are comparing instances of AnyOtherClass not instances of String, despite the fact that your comparison is actually comparing strings within your class.

But it looks more like what you are trying to do is make some kind of dictionary. In which case you should use the dictionary classes.

Matt Burland
  • 44,552
  • 18
  • 99
  • 171
  • But I do want compare a string to a property of my class. I don't have the entire object to compare to. – UNeverNo Dec 03 '12 at 14:42
  • @UNeverNo: That's not what the `IEquatable` interface is for. It's for comparing objects of the *same* type. As I said before, what it really sounds like you are looking for isn't a `List` but a `Dictionary`. – Matt Burland Dec 03 '12 at 15:24
2

That is not the intended usage of IEquatable<T>. Look at the documentation http://msdn.microsoft.com/en-us/library/ms131187.aspx:

Notes to Implementers Replace the type parameter of the IEquatable<T> interface with the type that is implementing this interface.

Besides not designed to work like that, why would you force an implementation of equals on a class because a different class has a specific requirement about looking up instances? Leave it up to the class holding the collection to do the key-based lookup as described in other answers.

fsimonazzi
  • 2,975
  • 15
  • 13
0

This worked like a champ for me!

"""

public class Point : IComparable<Point>, IEquatable<Point>
{
    public DateTime x;
    public double y;
    public uint z;

    public Point(DateTime dateTime, double rate, uint sequence)
    {
        x = dateTime;
        y = rate;
        z = sequence;
    }

    public int Compare(Point a, Point b)
    {
        // Equal.
        if (a.z == b.z)
        {
            return 0;
        }
        // Less than.
        else
        if ((a.z < b.z))
        {
            return -1;
        }
        // Greater than.
        else
        {
            return 1;
        }
    }

    public int CompareTo(Point point)
    {
        return Compare(this, point);
    }

    public static int operator- (Point a, Point b)
    {
        return (int)(a.z - b.z);
    }

    public bool Equals(Point point)
    {
        return z == point.z;
    }
}

"""

Gregory
  • 3
  • 3