实施IEquatable< T>在一个可变型变型、IEquatable、LT、GT

2023-09-09 21:00:36 作者:◆◇丶假装不在乎

我有一个重新presents外部物理测量设备类。简化的版本是这样的:

 公共类设备{
    公共字符串标记{获得;组; }
    公众诠释地址{获得;组; }
}
 

标签是用于识别设备的用户定义的值。 地址是由一个适配器与设备进行通信的价值。如果设备的两个实例具有相同地址,那么同样的外部测量设备将被使用。

我想模仿code这种行为(使用方法,如包含分明 )通过覆盖等于和实施 IEquatable< T>

 公共类设备:IEquatable<装置> {
    公共字符串标记{获得;组; }
    公众诠释地址{获得;组; }

    公众覆盖布尔等于(obj对象){
        回报等于(OBJ装置);
    }
    公共布尔等于(设备除外){
        如果(空==等)返回false;
        如果(的ReferenceEquals(这一点,其他))返回true;
        返回Address.Equals(other.Address);
    }
}
 

正如你所看到的,我忽略了标签属性的实施等于

所以,我的问题是:我应该忽略标签属性的实施等于?请问这样做使code更难理解?是否有这样做我想要做的更好的办法?我需要的标签属性,因为,通常情况下,用户不会知道地址,甚至与否的设备有一个地址(即采取在App.config文件中关怀,用户将被处理的接口名为的iDevice 不具有地址属性)。

更新:

感谢大家的响应。

所以,我推测,我应该使用自定义的的IEqualityComparer 。你有没有对如何做任何指导,所以如果我的真实code看起来更像吗?

 公共接口的iDevice {
    字符串标记{获得;组; }
    双TakeMeasurement();
}
内部类设备:的iDevice {
    公共字符串标记{获得;组; }
    公众诠释地址{获得;组; }
    公共双TakeMeasurement(){
        //执行测量的设备的地址...
    }
}
 
适用于电流模式DC DC转换器的统一的LTspice AC模型

我应该检查设备类型我的的IEqualityComparer

 公共类DeviceEqualityComparer:的IEqualityComparer<的iDevice> {
    公共布尔等于(i设备的x,的iDevice Y){
        Contract.Requires(X!= NULL);
        Contract.Requires(Y!= NULL);
        如果((x为设备)及及(y为设备)){
            返回x.Address.Equals(y.Address);
        }
        其他 {
            返回x.Equals(Y);
        }
    }

    公众诠释GetHash code(i设备的obj){
        Contract.Requires(OBJ!= NULL);
        如果(obj是设备){
            返回obj.Address.GetHash code();
        }
        其他 {
            返回obj.GetHash code();
        }
    }
}
 

解决方案

是的,你当前的实现肯定是混乱的。您所定义的平等显然是不公平的设备的正确观念。

所以,而不是实施 IEquatable<装置> 为你做了,我会明确的实施的IEqualityComparer<装置> ,也许

 类DeviceAddressEqualityComparer:的IEqualityComparer<装置> {
    公共布尔等于(设备X,设备Y){
        Contract.Requires(X!= NULL);
        Contract.Requires(Y!= NULL);
        返回x.Address.Equals(y.Address);
    }

    公众诠释GetHash code(设备OBJ){
        Contract.Requires(OBJ!= NULL);
        返回obj.Address.GetHash code();
    }
}
 

您可以通过的IEqualityComparer&LT的实例; T> 包含分明以及依赖于平等的其他LINQ的方法(例如, GROUPBY )。

I have a class that represents an external physical measuring device. The simplified version looks like this:

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

Tag is a user-defined value for identifying the device. Address is the value used by an adapter to communicate with the device. If two instances of Device have the same Address, then the same external measuring device will be used.

I'd like to mimic that behavior in code (for using methods like Contains and Distinct) by overriding Equals and 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'm ignoring the Tag property in the implementation of Equals.

So, my question is: Should I ignore the Tag property in the implementation of Equals? Does doing so make the code harder to understand? Is there a better way of doing what I'm trying to do? I need the Tag property because, often, the user will not know the Address, or even whether or not the Device has an Address (that is taken care of in the App.config file, and the user will be dealing with an interface called IDevice which doesn't have an Address property).

Update:

Thanks everyone for the responses.

So, I gather that I should be using a custom IEqualityComparer. Do you have any guidance on how to do so if my real code looks more like this?

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's address...
    }
}

Should I check the device type in my 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();
        }
    }
}

解决方案

Yes, your current implementation is definitely confusing. The equality you've defined is clearly not the right notion of equality for devices.

So, rather than implementing IEquatable<Device> as you've done, I'd define an implementation of IEqualityComparer<Device>, maybe

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();
    }
}

You can pass instances of IEqualityComparer<T> to Contains, Distinct and other LINQ methods that depend on equality (e.g., GroupBy).