Podczas wywoływania Single
lub SingleOrDefault
na IEnumerable<T>
, i ma więcej niż jeden wynik, rzuca InvalidOperationException
.Po Single i SingleOrDefault rzucanie bardziej zwięzły wyjątek
Podczas gdy rzeczywisty komunikat wyjątku jest bardzo opisowy, problematyczne jest pisanie kodu, który będzie obsługiwał tylko przypadki, w których nie powiodą się połączenia Single
/SingleOrDefault
.
public virtual Fee GetFeeByPromoCode(string promoCode)
{
try
{
return _fees.SingleOrDefault(f => f.IsPromoCodeValid(promoCode));
}
catch (InvalidOperationException)
{
throw new TooManyFeesException();
}
}
W tym scenariuszu, jeśli IsPromoCodeValid
rzuca również InvalidOperationException
, wówczas staje się niejednoznaczna, co jest haczyk jest obsługa.
Mogę sprawdzać wiadomość o wyjątku, ale chciałbym tego uniknąć, ponieważ uważam, że zabrudzeniem jest obsługa kodu w zależności od komunikatu o wyjątku.
Mój obecny alternatywą dla SingleOrDefault
wygląda następująco:
public virtual Fee GetFeeByPromoCode(string promoCode)
{
var fees = _fees.Where(f => f.IsPromoCodeValid(promoCode)).ToList();
if (fees.Count > 1)
{
throw new InvalidFeeSetupException();
}
return fees.FirstOrDefault();
}
Jednak kod ten jest dużo mniej oczywiste niż kod powyżej, dodatkowo, to generuje mniej efektywne zapytania (jeśli przy użyciu LINQ ORM) niż przy użyciu SingleOrDefault
.
Mogę również zrobić Take(2)
z moim drugim przykładem, aby zoptymalizować nieco, ale to dalej zaciemnia cel kodu.
Czy istnieje sposób, aby to zrobić bez pisania własnego rozszerzenia zarówno dla IEnumerable
i IQueryable
?
Być może ma 'IsPromoCode' throw niestandardowy wyjątek? Ale ciekawe pytanie. – BradleyDotNET
Czy rozważałeś utworzenie dobrze nazwanej metody rozszerzenia, która wykonuje twoją metodę 'take (2)'? – Khan
'Mogę również zrobić Take (2) z moim drugim przykładem, aby zoptymalizować go nieco, ale to dalej zaciemnia cel kodu" - IMO, 'Take (2)' z zaznaczeniem 'fees.Count> 1 'czyni to bardziej zrozumiałym – Habib