W przestrzeni nazw dostępna jest poręczna klasa statyczna Assert
do obsługi twierdzeń zachodzących w testach.Microsoft.VisualStudio.TestTools.UnitTesting.Assert metoda ogólna przeciąża zachowanie
Coś, co mnie zasmuciło, polega na tym, że większość metod jest wyjątkowo przeciążona, a na dodatek ma ogólną wersję. Specyficznym przykładem jest Assert.AreEqual
który ma 18 przeciążeń, a wśród nich:
Assert.AreEqual<T>(T t1, T t2)
Co jest stosowanie tej metody rodzajowe? Początkowo myślałem, że to sposób na bezpośrednie wywołanie metody IEquatable<T> Equals(T t)
, ale tak nie jest; zawsze będzie wywoływać nietypową wersję object.Equals(object other)
. Dowiedziałem się na własnej skórze po kodowaniu kilku testów jednostkowych spodziewających się takiego zachowania (zamiast wcześniejszego sprawdzania definicji klasy Assert
, tak jak powinienem).
W celu wywołania generyczną wersję Equals
metoda rodzajowa będzie musiał być zdefiniowany jako:
Assert.AreEqual<T>(T t1, T t2) where T: IEquatable<T>
Czy istnieje dobry powód, dlaczego to nie zostało zrobione w ten sposób?
Tak, tracisz sposób ogólny dla wszystkich tych typów, które nie wdrażają IEquatable<T>
, ale nie jest to wielka strata i tak jak równość będzie sprawdzane przez object.Equals(object other)
, więc Assert.AreEqual(object o1, object o2)
jest już wystarczająco dobry.
Czy obecna metoda generyczna oferuje zalety, których nie rozważam, czy jest tak, że nikt nie zastanawiał się nad tym, ponieważ to nie jest tak dużo? Jedyną korzyścią, jaką widzę, jest bezpieczeństwo typu argumentacyjnego, ale wydaje się ono słabe.
Edit: Naprawiono błąd, gdzie trzymane odnosząc się do IComparable
kiedy oznaczało IEquatable
.
Nie można tego ograniczyć, ponieważ dowolne T bez własnego przeciążenia naturalnie rozwiązałoby tę metodę jako część rozdzielczości przeciążania i tylko wtedy kompilator narzekałby na niespełnione ograniczenie dla dowolnego T, które nie implementuje interfejsu. Co do niepoprawnego założenia, czy sprawdziłeś dokumentację metody przed zbudowaniem swojej strategii testowej? –
AnthonyPegram: jeśli ograniczasz to, nie możesz przekazać żadnego T, które nie implementuje interfejsu, więc jak dokładnie przeciążenie nie powiodło się w środowisku wykonawczym? – InBetween
To by się nie udało w czasie kompilacji, ale rozdzielczość przeciążenia już zdecydowałaby o przeciążeniu T i * następnie * sprawdzenie ograniczenia (i niepowodzenie). Ograniczenia nie są częścią podpisu. Jeśli przeszukujesz tę frazę, znajdziesz mnóstwo zasobów (tutaj i gdzie indziej, w szczególności bloga Erica Lipperta), które podadzą ci więcej szczegółów. –