2010-03-17 137 views
4

我想解決這個問題使用擴展方法和未來發展類接口的maginification的(現在假設,但未來propably實)。擴展方法和源代碼前進了兼容性

例子:

/* the code written in 17. March 2010 */ 
public class MySpecialList : IList<MySpecialClass> { 
    // ... implementation 
} 
// ... somewhere elsewhere ... 
MySpecialList list = GetMySpecialList(); // returns list of special classes 
var reversedList = list.Reverse().ToList(); // .Reverse() is extension method 
/* now the "list" is unchanged and "reveresedList" has same items in reversed order */ 

/* --- in future the interface of MySpecialList will be changed because of reason XYZ*/ 

/* the code written in some future */ 
public class MySpecialList : IList<MySpecialClass> { 
    // ... implementation 
    public MySpecialList Reverse() { 
     // reverse order of items in this collection 
     return this; 
    } 
} 
// ... somewhere elsewhere ... 
MySpecialList list = GetMySpecialList(); // returns list of special classes 
var reversedList = list.Reverse().ToList(); // .Reverse() was extension method but now is instance method and do something else ! 
/* now the "list" is reversed order of items and "reveresedList" has same items lake in "list" */ 

我的問題是:有沒有一些方法如何防止這種情況下(我沒找到)?如果現在如何防止它,有沒有辦法找到像這樣的可能的問題?如果現在如何找到可能的問題,我是否應該禁止使用擴展方法?

謝謝。

編輯:

此致答案是有用的。 我可以在代碼中找到擴展方法嗎?和/或我可以找到代碼中的哪些地方使用實例方法,但存在具有相同簽名的擴展方法?

回答

4

它看起來像你所描述的是以下情況

  1. 在你的產品MySpecialList的V1沒有Reverse方法,以便於Reverse綁定到同一名稱的擴展方法的所有調用
  2. 在V2您的產品MySpecialList獲得Reverse方法,現在所有先前綁定到擴展方法的綁定都會綁定到實例方法。

如果您想在實例/擴展方法窗體中調用Reverse,則無法防止此操作,因爲它是設計的行爲。如果擴展方法至少與擴展方法版本一樣好,那麼實例方法將總是優先於擴展方法。

100%防止這種情況的唯一方法是將擴展方法稱爲靜態方法。例如

ExtensionMethods.Reverse(list); 

的結合與產品的新版本的新方法,這一問題不僅僅侷限於擴展方法(雖然問題可能是一個有點差)。有很多事情可以做,以一個類型改變方式方法結合會受到影響,如實現一個新的接口,繼承或添加新的轉換

+0

是的,我的意思是完全一樣的情況。 如果我理解正確,最正確的方法是使用擴展方法,如靜態方法,不使用擴展方法? 如何在代碼審查中發現,指定的代碼沒有使用擴展方法? – TcKs 2010-03-17 16:48:53

+1

我不認爲Jared說擴展方法的調用就好像它們是普通的靜態方法是正確的;他只是說這是完全避免你所描述的風險的唯一途徑 - 但這種風險無論如何都不是完全可以避免的。 – 2010-03-17 16:52:23

+0

@JacobM正確。 – JaredPar 2010-03-17 17:04:43

1

保證這一點的唯一方法是給你的擴展方法唯一的名稱。這可能與爲您的姓名縮寫添加前綴一樣簡單。我知道它看起來很醜,但應該在99.9%的時間內工作。

+0

是的,它看起來很醜,但是BCL /第三方組件的擴展方法呢? – TcKs 2010-03-17 16:50:08

+0

@TcKs - 你不能監視每個人的代碼。沒有足夠的時間。去@ Chad的答案 - 編寫單元測試,告訴你擴展方法是否被破壞代碼的東西所取代。 – ChrisF 2010-03-17 16:53:12

1

在這種特定情況下我認爲,擴展方法返回一個新的反向列表(而不是反向列表)不應該被稱爲「反向」,但應該是getReversedList()或其他類似的。

但你的觀點是正確的(約無副作用的擴展方法得到不經意間的副作用引起本地方法代替);命名約定可能是一個好方法,但是,這是不使用擴展方法不加區分(但不足以禁止它們)的原因。

2

這就是我們編寫單元測試的原因。

首先寫入擴展方法。準確地命名它們。所以總有一天,如果一個擴展方法在同名的類中被實現爲一個真正的方法,那麼這是一個很好的機會,它和擴展方法的功能相同,並且沒有任何中斷。其次,通過單元測試,你很快就會看到破壞了什麼,並且因爲擴展方法不再被調用而被破壞,因爲類現在擁有一個擁有該名稱的自己的方法。鑑於此,您可以選擇重命名您的方法,將您的擴展方法稱爲靜態方法,或者重新編寫代碼以正確使用新方法。