2017-01-31 14 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', вы просто именование общий параметр 'ApplyTo'' DateTime'. Это будет работать так же, если вы назовете это 'T'. Если вы попытаетесь получить доступ к любым членам 'DateTime' в' actual' (помимо тех, которые определены '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 Это потому, что типы значений (structs) неявно запечатаны, что подпадает под то, что я сказал. – Abion47

+0

Я имею в виду, что у вас не может быть 'where T: DateTime'. – BanksySan