0

So I created a class like this:

public class ClassName
{
public int ID;

public String n_1 {get; set; }
public String n_2 {get; set; }
// ....
public String n_x {get; set; }
}

Later in my code I compare 2 ClassName objects:

ClassName Item_1 /*...*/ ;
ClassName Item_2 /*...*/ ;

Like this:

if (Item_1 != Item_2 && Item_1.n_a == Item_2.n_a)
{
//do something
}

Now my Problem is that Item_1.ID and Item_2.ID should be ignored. Is there a easy way to do this? The only solution I came up with is a no brainer of like

if ( (Item_1.n_1 != Item_2.n_1 || Item_1.n_2 != Item_2.n_2 || /* ... */ ) && Item_1.n_a == Item_2.n_a)
axbeit
  • 853
  • 11
  • 35
  • 1
    What's wrong with this? If you're doing manual comparison and you've already ignored `ID` ? – Hary Nov 16 '18 at 10:36
  • 1
    You should check the [IComparable](https://learn.microsoft.com/en-us/dotnet/api/system.icomparable-1.compareto?view=netframework-4.7.2) interface – Jeroen van Langen Nov 16 '18 at 10:36
  • Why not override the Equals method? – Klaus Gütter Nov 16 '18 at 10:36
  • 2
    https://learn.microsoft.com/en-us/dotnet/api/system.collections.generic.icomparer-1?view=netframework-4.7.2 – mjwills Nov 16 '18 at 10:37
  • 1
    By doing `Item_1 != Item_2`, you will not actually check if all properties from both objects are not equal, it will only check if the references stored inside `Item_1` and `Item_2` are not equal. – SᴇM Nov 16 '18 at 10:41
  • Hi @SeM - Can you explain it to me a little bit more please? I imagined it would compare all the properties in those 2 objects. (Kinda like the no brainer I wrote) – axbeit Nov 16 '18 at 10:51
  • 1
    @axbeit I have added some explanation in answers, you can check it out and if you have questions, feel free to ask. – SᴇM Nov 16 '18 at 11:35

3 Answers3

1

Override the object.Equals method in your class and specify how you want it to be compared.

Then use !Item1.Equals(Item2) instead of !=

https://learn.microsoft.com/en-us/dotnet/api/system.object.equals?view=netframework-4.7.2

Kieran
  • 612
  • 6
  • 22
1

The easy way is what you are actually doing , just create a method like this

    public bool Method(ClassName Item_1,ClassName Item2)
    {
    bool check=false;
    if ( (Item_1.n_1 != Item_2.n_1 || Item_1.n_2 != Item_2.n_2 || /* ... */ ) && Item_1.n_a == Item_2.n_a)
    check=true

return check
    }
MatteoCracco97
  • 426
  • 6
  • 17
  • 2
    https://learn.microsoft.com/en-us/dotnet/api/system.collections.generic.icomparer-1?view=netframework-4.7.2 may be of interest. – mjwills Nov 16 '18 at 10:54
  • @mjwills hi. The IComparer way seems to be similar to the "no brainer". I still have to write everything manually. Is there an autofill option for it? – axbeit Nov 16 '18 at 11:31
  • 1
    Is there a way to do it less manually? Yes there is. But honestly, it is way more effort (for a once off) than what matteo has suggested here. If you did want to do it the hard way, use https://stackoverflow.com/a/986617/34092 as a starting point @axbeit. – mjwills Nov 16 '18 at 11:34
1

To perform something like Item_1 != Item_2 or Item_1 == Item_2 and get all properties (or the ones you want) to be compared, you need to implement your own Equals method and ==, != operators overloads.

== operator, from MSDN:

For reference types other than string, == returns true if its two operands refer to the same object.

For that you can start with some straightforward solution, to implement IEquatable<T> interface, fill your comparing logic inside Equals method and overload == and != operators internally calling your type-safe Equals method:

public class ClassName : IEquatable<ClassName>
{
    public int ID;

    public String n_1 { get; set; }
    public String n_2 { get; set; }
    // ....
    public String n_x { get; set; }

    public static bool operator ==(ClassName obj1, ClassName obj2)
    {
        if (((object)obj1) == null || ((object)obj2) == null)
            return Equals(obj1, obj2);
        return obj1.Equals(obj2);
    }

    public static bool operator != (ClassName obj1, ClassName obj2)
    {
        if (((object)obj1) == null || ((object)obj2) == null)
            return !Equals(obj1, obj2);
        return !obj1.Equals(obj2);
    }


    public bool Equals(ClassName obj)
    {
        if (obj == null) return false;

        return (n_1 == obj.n_1) && (n_2 == obj.n_2) && (n_x == obj.n_x); //you can ignore ID here
    }

    public override bool Equals(object obj)
    {
        if (obj == null)
            return false;

        ClassName classNameObj = obj as ClassName;
        if (classNameObj == null)
            return false;
        else
            return Equals(classNameObj);
    }

    public override int GetHashCode()
    {
        //This code was generated by VS ide, you can write your own hashing logic
        var hashCode = 1032198799;
        hashCode = hashCode * -1521134295 + ID.GetHashCode();
        hashCode = hashCode * -1521134295 + EqualityComparer<string>.Default.GetHashCode(n_1);
        hashCode = hashCode * -1521134295 + EqualityComparer<string>.Default.GetHashCode(n_2);
        hashCode = hashCode * -1521134295 + EqualityComparer<string>.Default.GetHashCode(n_x);
        return hashCode;
    }
}

Then you can check in your if:

if (Item_1 != Item_2)
{
    //Do Something
}

For Equals method you should stick to Guidelines for Overriding Equals() and Operator == .

References: == Operator, != Operator, IEquatable Interface, IEquatable.Equals(T) Method, Guidelines for Overriding Equals() and Operator ==

SᴇM
  • 7,024
  • 3
  • 24
  • 41