Zamierzam użyć metody ToString() do tworzenia klucza pamięci podręcznej. Ta pamięć podręczna będzie używana do buforowania wywołań na poziomie metod, a klucz zostanie skonstruowany przy użyciu nazw parametrów i odpowiednich wartości. Ponieważ to buforowanie będzie budowane dla dużej biblioteki, nie mam możliwości upewnienia się, że każda metoda ma tylko parametry typu wartości lub wszystkie klasy implementują serializację. Muszę określić w czasie wykonywania, że ​​wywołanie ToString zwraca rzeczywistą wartość w porównaniu z nazwą typu, tak aby wywołanie metody nie mogło uczestniczyć w buforowaniu.

Na przykład rozważ następującą metodę i jej wywołanie

AccountDetails GetDetails(int groupId, Account account)
{
    var ac1 = new Account( accountId = 123 };
    var ac2 = new Account( accountId = 555 };
    var return1 = GetDetails(15, ac1);
    var return2 = GetDetails(15, ac2);
}

W tym przypadku utworzyłbym klucz cache jako "groupId=15+account=namespace.Account" powodując niepoprawną kolizję. Jak wykryć w czasie wykonywania, że ​​moje wywołanie account.GetString() zwróci nazwę typu?

1
Abhinav Gujjar 29 wrzesień 2012, 20:52

2 odpowiedzi

Najlepsza odpowiedź

Nie powinieneś używać ciągów do ogólnych kluczy pamięci podręcznej. To naprawdę nie jest to, do czego ToString został zaprojektowany. Zamiast tego powinieneś używać Equals i GetHashCode, aby sprawdzić równość. Oczywiście, tak jak ToString, każdy obiekt ma metody Equals i GetHashCode... ale na szczęście istnieje interfejs IEquatable<T>, który zapewnia znacznie silniejszy sygnał, że typ został naprawdę zaprojektowany o równość.

Więc dla dowolnego typu X, po prostu sprawdź, czy ten typ implementuje IEquatable<X>. Jeśli tak, rozsądne powinno być użycie jako klucza pamięci podręcznej. Jeśli piszesz ogólną metodę, możesz wymusić to:

void Foo<T>(T key, /* other parameters */) where T : IEquatable<T>
3
Jon Skeet 29 wrzesień 2012, 22:44

Nie wiem, jaka jest implementacja w metodzie „ToString” (o ile wiesz, ktoś przeciążył „ToString” w „Object”, ale zaimplementował go w taki sam sposób, jak jest zaimplementowany w „Object”).

Nie możesz użyć ToString jako rodzaju skrótu dla obiektu. Pomyśl o dwóch logicznie różnych obiektach, takich jak dwa obiekty „Student” o tej samej pełnej nazwie i różnych identyfikatorach (lub o jakiejś wartości innej niż ASCII, takiej jak obrazek). Musisz użyć prawdziwego skrótu - zobacz "GetHashCode".

Jeśli „GetHashCode” nie jest opcją, będziemy potrzebować więcej informacji (np. „dlaczego”)

0
Neowizard 29 wrzesień 2012, 21:07