当==运算符';s比较特定的类型

本文关键字:类型 比较 运算符 | 更新日期: 2023-09-27 18:19:57

在遗留代码库中,由于许多技术原因,我们将以前属于基类类型的参数替换为接口类型。例如:

public interface IDomainObject { int Id { get; } }
public abstract class BaseDomainObject : IDomainObject
{
    public int Id { get; protected set; }
    public override bool Equals(object obj)
    {
        var domainObj = obj as BaseDomainObject;
        return domainObj != null && Id.Equals(domainObj.Id);
    }
    public static bool operator ==(BaseDomainObject x, BaseDomainObject y)
    {
        return !ReferenceEquals(x, null) && !ReferenceEquals(y, null) && x.Equals(y);
    }
    public static bool operator !=(BaseDomainObject x, BaseDomainObject y)
    {
        return !(x == y);
    }
}
public class MyDomainObject : BaseDomainObject
{
    public MyDomainObject(int id) { Id = id; }
    ...
}

因此,在代码中的任何地方,我们以前有一个类型为BaseDomainObject的变量,现在我们有一个IDomainObject类型的变量。然而,我们遇到了"=="运算符的问题——它不适用于接口。对于所有接口类型,"=="运算符只返回到ReferenceEquals()

以下代码演示了该问题:

    // Old style
    BaseDomainObject baseobj1A = new MyDomainObject(1);
    BaseDomainObject baseobj1B = new MyDomainObject(1);
    BaseDomainObject baseobj2 = new MyDomainObject(2);
    Assert.IsTrue(baseobj1A != baseobj2);
    Assert.IsTrue(baseobj1A == baseobj1B); // Succeeds
    // New style
    IDomainObject iobj1A = new MyDomainObject(1);
    IDomainObject iobj1B = new MyDomainObject(1);
    IDomainObject iobj2 = new MyDomainObject(2);
    Assert.IsTrue(iobj1A != iobj2);
    Assert.IsTrue(iobj1A == iobj1B); // Fails

返回使用基类不是一种选择——我们的接口是通用的协变(类似于IDomainObject<outT>),这对于我们需要的多态行为是必要的。理想情况下,我们只需将所有的"=="替换为.Equals()。然而,我们的代码库是巨大的,找到我们关心的所有"==="运算符将是一项艰巨的任务。

一种想法是,我们可以编写一个FxCop规则,该规则将标记在"=="比较中使用的特定接口类型的变量(即IDomainObject)的所有出现。但这并没有奏效——FxCop不支持这一点。另一个想法是编写我们自己的代码分析工具,只检查这种情况,但这会很耗时。

所以问题是,是否已经有某种代码分析工具可以用来查找这些"=="事件?

当==运算符';s比较特定的类型

您可以使用ReSharper的自定义搜索模式来执行这样的操作。

你也可以考虑用"老式的方式"来做这件事。更改所有引用,然后修复编译错误。

如果Visual Studio的"查找所有引用"无法找到==特定实现的所有用法,我相信Resharper的"查找用法"会毫无问题地找到它们。