2014-06-06 44 views
4

會不會有任何缺點?接口中的方法返回動態

現有的代碼不會因爲它而被改變,因爲底層類型仍然是相同的,它會使代碼略少。

public class MyClass : IClonable 
{ 
    //... 
    public object Clone() 
    { 
     //... 
     return new MyClass(...); 
    } 
} 

MyClass foo = new MyClass(...); 
MyClass bar = foo.Clone() as MyClass; 

唯一減少到上面的代碼正在改變FOO酒吧變種的聲明的詳細程度。現在

,如果IClonable.Clone()返回動態相反,基礎類(在運行時)仍然會MyClass的,但代碼會變得稍微更簡潔:

MyClass foo = new MyClass(...); 
MyClass bar = foo.Clone(); 

這樣的改變會有什麼不利嗎?

+0

只有當您使用'null'檢查時,才應使用'as'。如果您不想這樣做,請使用投射,例如'MyClass bar =(MyClass)foo.Clone();'。 – svick

+1

另外,我認爲這裏的正確解決方案是完全避免使用ICloneable,而不是試圖解決它的問題。 – svick

回答

5

這種變化的一個缺點是編譯器無法捕獲由錯別字造成的錯誤。例如,如果你寫

if (foo.Clone().Equalls(foo)) { 
//     ^^ 
//     || 
// Here is a typo ==++ 
} 

Clone()返回一個object,編譯器會抓住它。將dynamic更改爲編譯器將會很好,因此您的程序會爲缺少的方法拋出運行時異常。

3

是的,一個主要的缺點是動態性不能提供編譯時安全性......或對此有用的智能感知。所以,不僅會花費更長的時間,並且更容易出錯訪問對象上的某個屬性,但是如果確實犯了錯誤,那麼直到運行時纔會捕獲它。

它並不總是如此,但通常情況下,您提供的「冗長」的例子可以更好地避免泛型。 ICloneable是一個接口的例子,出於某種原因(可能歷史性)沒有通用版本,但是當存在通用版本時,這意味着您可以返回所需的確切類型,而不是必須轉換的對象。

+0

編譯時安全問題只會出現在由@dasblinkenlight描述的情況下,其中一個成員是直接從方法(foo.Clone()。Member)訪問的。這是一個非常有效的觀察,並且我還沒有想過,但是編譯時安全性和智能感知在其他情況下(例如我在OP中介紹的那些)中得到維護。 – Wasabi

+2

@Wasabi是的,如果它被分配給一個強類型變量,那麼它並不比一個強制類型更糟糕。但我不認爲這是一個安全的假設,總是合適的,特別是在屬性而不是方法的情況下。不得不將這些分配給變量實際上會導致更多的樣板而不是更少 –