Implementing IEquatable <T> in a Mutable Type

I have a class representing an external physical measuring device. A simplified version is as follows:

public class Device {
    public string Tag { get; set; }
    public int Address { get; set; }
}

Tagis a user-defined value for device identification. Addressis the value used by the adapter to communicate with the device. If two instances Devicehave the same Address, then the same external measuring device will be used.

I would like to emulate this behavior in your code (for use of methods such as Containsand Distinct) by redefining Equalsand implementing IEquatable<T>:

public class Device : IEquatable<Device> {
    public string Tag { get; set; }
    public int Address { get; set; }

    public override bool Equals(object obj) {
        return Equals(obj as Device);
    }
    public bool Equals(Device other) {
        if (null == other) return false;
        if (ReferenceEquals(this, other)) return true;
        return Address.Equals(other.Address);
    }
}

As you can see, I ignore the property Tagin the implementation Equals.

, : Tag Equals? ? , ? Tag, Address Device Address ( App.config, IDevice, Address).

Update:

.

, , IEqualityComparer. - , , ?

public interface IDevice {
    string Tag { get; set; }
    double TakeMeasurement();
}
internal class Device : IDevice {
    public string Tag { get; set; }
    public int Address { get; set; }
    public double TakeMeasurement() {
        // Take a measurement at the device address...
    }
}

IEqualityComparer?

public class DeviceEqualityComparer : IEqualityComparer<IDevice> {
    public bool Equals(IDevice x, IDevice y) {
        Contract.Requires(x != null);
        Contract.Requires(y != null);
        if ((x is Device) && (y is Device)) {
            return x.Address.Equals(y.Address);
        }
        else {
            return x.Equals(y);
        }
    }

    public int GetHashCode(IDevice obj) {
        Contract.Requires(obj != null);
        if (obj is Device) {
            return obj.Address.GetHashCode();
        }
        else {
            return obj.GetHashCode();
        }
    }
}
+3
5

, . .

, IEquatable<Device>, , IEqualityComparer<Device>,

class DeviceAddressEqualityComparer : IEqualityComparer<Device> {
    public bool Equals(Device x, Device y) {
        Contract.Requires(x != null);
        Contract.Requires(y != null);
        return x.Address.Equals(y.Address);
    }

    public int GetHashCode(Device obj) {
        Contract.Requires(obj != null);
        return obj.Address.GetHashCode();
    }
}

IEqualityComparer<T> Contains, Distinct LINQ, (, GroupBy).

+2

, GetHashCode(), .

IMO Equals , . Tag .

Equals . IEqualityComparer<T> , . , , IEqualityComparer<T> .

null, . , , .

public class DeviceByAddressEqualityComparer : IEqualityComparer<IDevice> {
    public bool Equals(IDevice x, IDevice y) {
        if(x==y)
          return true;
        if(x==null||y==null)
          return false;
        return x.Address.Equals(y.Address);
    }

    public int GetHashCode(IDevice obj) {
        if(obj == null)
          return 0;
        else
          return obj.Address.GetHashCode();
    }
}

, . Equals , x.GetType()==y.GetType(), , , , , .

+4

Tag Equals?

, , .

?

: , , -, .

, ?

, :

  • DeviceWithTag Device " ".

, , Tag "" , , , .

+2

Tag ? , , .

Address, , ... ? , , , , .

, Address .

+1

IDevice . .

public interface IPhysicallyEquatable<T>
{
    bool PhysicallyEquals(T other);
    int GetPhysicalHashCode();
}

public class PhysicalEqualityComparer<T> : IEqualityComparer<T>
    where T : IPhysicallyEquatable<T>
{
    public bool Equals(T x, T y)
    {
        if (null == x) throw new ArgumentNullException("x");
        if (null == y) throw new ArgumentNullException("y");
        return x.PhysicallyEquals(y);
    }
    public int GetHashCode(T obj)
    {
        if (null == obj) throw new ArgumentNullException("obj");
        return obj.GetPhysicalHashCode();
    }
}

public interface IDevice : IPhysicallyEquatable<IDevice>
{
    // ...
}
0

All Articles