Howto override List<T> Contains
Asked Answered
O

5

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
    }
Ona answered 3/12, 2012 at 14:34 Comment(0)
H
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>.

Hogan answered 3/12, 2012 at 14:39 Comment(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).Wilds
Okay I'll head for using LINQ here.Ona
B
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

Birdwatcher answered 3/12, 2012 at 14:35 Comment(2)
Yes, LINQ works here, but I still don't understand why IEquatable is not working.Ona
+1 just because sounds like you should be doing a Where rather than a Contains sentence helped me so much!Curtiscurtiss
M
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.

Maxie answered 3/12, 2012 at 14:40 Comment(2)
But I do want compare a string to a property of my class. I don't have the entire object to compare to.Ona
@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<AnyOtherClass> but a Dictionary<string,AnyOtherClass>.Maxie
B
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.

Bartley answered 3/12, 2012 at 14:52 Comment(0)
R
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;
    }
}

"""

Railhead answered 12/11, 2019 at 19:45 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.