Mam problem projektowy dotyczący właściwości .NET.
interface IX
{
Guid Id { get; }
bool IsInvalidated { get; }
void Invalidate();
}
Problem:
Ten interfejs ma dwie właściwości tylko do odczytu Id
i IsInvalidated
. Jednak fakt, że są one tylko do odczytu, sam w sobie nie gwarantuje, że ich wartości pozostaną stałe.
Powiedzmy, że moim zamiarem było wyjaśnienie, że…
Id
reprezentuje stałą wartość (która dlatego może być bezpiecznie buforowana), natomiastIsInvalidated
może zmienić swoją wartość w czasie życiaIX
obiektu (i dlatego nie powinien być buforowany).
Jak mogę zmodyfikować, interface IX
aby umowa była wystarczająco wyraźna?
Moje trzy próby rozwiązania:
Interfejs jest już dobrze zaprojektowany. Obecność wywoływanej metody
Invalidate()
pozwala programiście wnioskować, żeIsInvalidated
może mieć na nią wpływ wartość właściwości o podobnej nazwie .Ten argument obowiązuje tylko w przypadkach, w których metoda i właściwość są podobnie nazwane.
Rozszerz ten interfejs o wydarzenie
IsInvalidatedChanged
:bool IsInvalidated { get; } event EventHandler IsInvalidatedChanged;
Obecność
…Changed
zdarzenia dlaIsInvalidated
oznacza, że ta właściwość może zmienić swoją wartość, a brak podobnego zdarzenia dlaId
jest obietnicą, że ta właściwość nie zmieni swojej wartości.Podoba mi się to rozwiązanie, ale jest wiele dodatkowych rzeczy, które w ogóle mogą się nie przydać.
Zastąp właściwość
IsInvalidated
metodąIsInvalidated()
:bool IsInvalidated();
To może być zbyt subtelna zmiana. Powinna to być wskazówka, że wartość jest obliczana świeżo za każdym razem - co nie byłoby konieczne, gdyby była stała. W temacie MSDN „Wybieranie właściwości i metod” można o tym powiedzieć:
Użyj metody, a nie właściwości, w następujących sytuacjach. […] Operacja zwraca inny wynik przy każdym wywołaniu, nawet jeśli parametry się nie zmieniają.
Jakich odpowiedzi oczekuję?
Najbardziej interesują mnie zupełnie inne rozwiązania problemu, wraz z wyjaśnieniem, w jaki sposób pokonały moje powyższe próby.
Jeśli moje próby są logicznie błędne lub mają znaczące wady, o których jeszcze nie wspomniano, tak, że pozostaje tylko jedno rozwiązanie (lub żadne), chciałbym usłyszeć o tym, gdzie popełniłem błąd.
Jeśli wady są niewielkie, a po ich uwzględnieniu pozostaje więcej niż jedno rozwiązanie, prosimy o komentarz.
Przynajmniej chciałbym uzyskać informacje zwrotne na temat tego, które jest Twoim preferowanym rozwiązaniem iz jakiego powodu (powodów).
class Foo : IFoo { private bool isInvalidated; public bool IsInvalidated { get { return isInvalidated; } } public void Invalidate() { isInvalidated = true; } }
InvalidStateException
s, ale nie jestem pewien, czy jest to nawet teoretycznie możliwe. Byłoby jednak miło.
IsInvalidated
potrzebujeprivate set
?