2010-03-26 291 views
4

Visual sutdio 2008能夠自動創建單元測試存根。我用它來創建一些基本的單元測試,但我的東西迷惑:C#泛型鑄造

private class bla : BaseStoreItem 
    { 
    // 
    } 

    /// <summary> 
    ///A test for StoreData 
    ///</summary> 
    public void StoreDataTestHelper<T>() where T : BaseStoreItem 
    { 
    FileStore<T> target = new FileStore<T>(); // TODO: Initialize to an appropriate value 

    BaseStoreItem data = new bla(); 

    target.StoreData(data); 
    } 

    [TestMethod()] 
    public void StoreDataTest() 
    { 
    //Assert.Inconclusive("No appropriate type parameter is found to satisfies the type constraint(s) of T. " + 
    //  "Please call StoreDataTestHelper<T>() with appropriate type parameters."); 

    StoreDataTestHelper<bla>(); 
    } 

爲什麼我會收到「錯誤:無法轉換類型‘StorageUnitTests.FileStoreTest.bla’到‘T’」當T鍵入「bla」?

我知道「bla」不是一個好的函數名,但它只是一個例子。

回答

4

爲什麼不那樣呢? (它沒有多大SENCE創建StoreDataTestHelper的BLA內的一個實例,如果你有機會到T)

public void StoreDataTestHelper<T>() where T : BaseStoreItem, new() 
{ 
    FileStore<T> target = new FileStore<T>(); 

    T data = new T(); 

    target.StoreData(data); 
} 
+0

我認爲它應該是Activator.CreateInstance ()而不是新的T().. – 2010-03-26 10:01:19

+0

@Akash爲什麼? Activator.CreateInstance使用反射,它很慢。它認爲新的T()更優雅。 – gsharp 2010-03-26 10:11:59

+0

gsharp,對不起,我錯過了,在你的代碼中的new()約束,因爲沒有指定new() – 2010-03-26 10:19:13

0

因爲,如果TDerivedStoreItem(繼承BaseStoreItem),您就違反了類型FileStore<T>通過存儲BaseStoreItem

0

這是有道理的。通過指定T: BaseStoreItem,您確保T將作爲基類的BaseStoreItem類型,而不是它必然是BaseStoreItem。因此,如果T後來被設置爲來自BaseStoreItem的某種類型,那麼您的target.StoreData(data);行將執行非法操作。

雖然你的情況,你只用T集調用StoreDataTestHelperbla,C#的typechecker需要確保爲StoreDataTestHelper的代碼是類型安全的一般。這是一種強類型語言的好處之一:在製作它們之前捕獲潛在的輸入錯誤。

1

when T is type "bla"

你的上述條件僅適用於當前的情況下也是如此,但我可以創造一個諾特爾類

public class Bla2: BaseStoreItem {... 

然後Bla2 <> BLA ...,既不Bla2從BLA派生,所以如果我嘗試使用

StoreDataTestHelper<Bla2>(); 

這是錯誤的,編譯器是足夠聰明,明白,在這種情況下它不會工作,計算機語言是不喜歡英語,他們正在創建工作exactl y在所有條件下都相同。而且它們的設計使語言規則在所有情況下都是正確的。如果他們不同,你會發現混亂髮現錯誤的地方。