2017-01-31 40 views
0

我有以下自定義NUnit限制。它會(當正確實施時)測試給定DateTime等於明天。未強制執行泛型參數

public class TomorrowConstraint : Constraint 
{ 
    public TomorrowConstraint() 
    { 
     Description = "Tomorrow"; 
    } 

    public override ConstraintResult ApplyTo<DateTime>(DateTime actual) 
    { 
     return new ConstraintResult(this, actual, true); 
    } 
} 

請注意,我給了Type參數一個具體類型,而不是泛型類型。

測試下面利用它:

[TestFixture] 
public class X 
{ 
    [Test] 
    public void Foo() 
    { 
     Assert.That("string", new TomorrowConstraint()); 
    } 
} 

我傳遞一個string一個DateTime,但該字符串傳遞給方法沒有任何問題。

如果我看看actual.GetType()的類型,我可以看到它是一個字符串:{Name = "String" FullName = "System.String"}

這是怎麼發生的?

我以爲我會得到一個例外的地方異常?

+2

你沒有制約的typeof'actual'到'DateTime',你只是命名通用參數應用於''DateTime'。如果你把它叫做'T',它會起到同樣的作用。如果您嘗試訪問'actual'上的任何'DateTime'成員(除了'object'定義的那些成員之外),您將得到一個類型錯誤。 – Lee

回答

0

好吧,我猜測和李證實,該行

public override ConstraintResult ApplyTo<DateTime>(DateTime actual) 

不限制泛型類型爲DateTime。相反,它只是使用DateTime作爲通用參數的標識符,如其他情況下的T。要真正約束泛型類型,你需要使用where關鍵字:

public override ConstraintResult ApplyTo<T>(T actual) where T : DateTime 

...除了將不能工作,因爲一個泛型類型約束必須是一個接口或者非密封類,並且DateTime是密封的。所以我不確定是否有一種方法可以單獨使用泛型來獲得編譯時類型安全性。你可以做的是有一個調用的DateTime版本的方法的另一種方法,並使用你的單元測試:

public ConstraintResult ApplyTo(DateTime actual) 
{ 
    return ApplyTo<DateTime>(actual); 
} 
+0

你是對的,除了'where'約束。你不能在值中使用'where'(bar all'struct')。 – BanksySan

+0

@BanksySan這是因爲價值類型(結構)是隱式密封的,屬於我所說的。 – Abion47

+0

我的意思是你不能有'where T:DateTime'。 – BanksySan