在傳統的代碼庫中,由於許多技術原因,我們正在將以前基類類型的參數替換爲接口類型。例如:是否有任何代碼分析工具在比較特定類型時檢測==運算符?
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 <出T>),其對於我們需要的多態行爲是必需的。理想情況下,我們只需用.Equals()替換所有'=='。但是,我們的代碼庫非常龐大,而查找所有我們關心的'=='運算符將是一項艱鉅的任務。
一個想法是,我們可以編寫一個FxCop規則來標記在'=='比較中使用的某個接口類型的變量(即,IDomainObject)的所有變量。但是這不起作用--FxCop不支持這一點。另一個想法是編寫我們自己的代碼分析工具,只是檢查這種情況,但這會很耗時。
所以問題是,是否已經有一些代碼分析工具在那裏,我們可以用它來找到這些'=='發生?
您可以使用jetbrains.com的R#工具來查找所有類型的用法。它支持插件,您可以添加所需的功能。 – 2012-01-11 16:39:15
不,找到用法並沒有找到它們。 – afeygin 2012-01-11 16:50:17
你爲什麼說FxCop不支持這個?您是否真的嘗試創建一個自定義的FxCop規則來查找針對您的目標接口實例的不適當的相等性驗證? – 2012-01-11 17:18:19