Cached property vs Lazy
W. Net 4 poniższy fragment z buforowaną właściwością może być również napisany przy użyciu System.Lazy<T>
klasy. Zmierzyłem wydajność obu podejść i jest prawie taka sama. Czy jest jakaś prawdziwa korzyść lub magia, dlaczego powinienem używać jednego nad drugim?
Cached Property
public static class Brushes
{
private static LinearGradientBrush _myBrush;
public static LinearGradientBrush MyBrush
{
get
{
if (_myBrush == null)
{
var linearGradientBrush = new LinearGradientBrush { ...};
linearGradientBrush.GradientStops.Add( ... );
linearGradientBrush.GradientStops.Add( ... );
_myBrush = linearGradientBrush;
}
return _myBrush;
}
}
}
Lazy
public static class Brushes
{
private static readonly Lazy<LinearGradientBrush> _myBrush =
new Lazy<LinearGradientBrush>(() =>
{
var linearGradientBrush = new LinearGradientBrush { ...};
linearGradientBrush.GradientStops.Add( ... );
linearGradientBrush.GradientStops.Add( ... );
return linearGradientBrush;
}
);
public static LinearGradientBrush MyBrush
{
get { return _myBrush.Value; }
}
}
7 answers
Użyłbym Lazy<T>
ogólnie:
- Jest bezpieczny dla wątków (może nie być problemem w tym przypadku, ale będzie w innych)]}
- to sprawia, że oczywiste jest, co się dzieje tylko po nazwie
- pozwala null być poprawną wartością
Zauważ, że nie musisz używać wyrażenia lambda dla delegata. Na przykład, oto podejście, które może być nieco czystsze:
public static class Brushes
{
private static readonly Lazy<LinearGradientBrush> _myBrush =
new Lazy<LinearGradientBrush>(CreateMyBrush);
private static LinearGradientBrush CreateMyBrush()
{
var linearGradientBrush = new LinearGradientBrush { ...};
linearGradientBrush.GradientStops.Add( ... );
linearGradientBrush.GradientStops.Add( ... );
return linearGradientBrush;
}
public static LinearGradientBrush MyBrush
{
get { return _myBrush.Value; }
}
}
Jest to szczególnie przydatne, gdy proces tworzenia komplikuje się za pomocą pętli itd. Zauważ, że wygląda na to, że możesz użyć inicjalizatora kolekcji dla GradientStops
w kodzie tworzenia.
Inną opcją jest Nie , aby robić to leniwie, oczywiście... jeśli nie masz kilku takich właściwości w swojej klasie i chcesz tworzyć odpowiednie obiekty tylko jeden po drugim, możesz polegać na leniwej inicjalizacji klasy w wielu sytuacjach.
Jak wspomniano w odpowiedzi DoubleDown, nie ma sposobu na zresetowanie tego, aby wymusić rekomputację (chyba, że zrobisz Lazy<T>
field not readonly) - ale bardzo rzadko uznałem to za ważne.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-12-31 10:28:56
Użyj Lazy<T>
, ponieważ wyraża dokładnie to, co robisz-leniwe Ładowanie.
Ponadto utrzymuje Twoją nieruchomość w czystości i jest Bezpieczna.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-02-27 17:49:49
Zazwyczaj jedynym powodem, aby nie używać lazy jest reset zmiennej do wartości null, więc następny dostęp powoduje jej ponowne załadowanie. Lazy nie ma resetu i musisz odtworzyć leniwego od zera.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-02-27 18:59:15
Lazy<T>
będzie poprawnie obsługiwać współbieżne scenariusze (jeśli przekażesz poprawne LazyThreadSafetyMode ), podczas gdy twój przykład nie ma żadnych kontroli bezpieczeństwa wątków.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-02-27 17:49:40
{[0] } jest prostsza-jasno wyraża intencję Kodeksu.
Jest również bezpieczny dla nici.
Zauważ, że jeśli używasz tego w wielu wątkach, musisz zrobić to [ThreadStatic]
; obiekty GDI+ nie mogą być współdzielone między wątkami.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-02-27 17:49:37
Lazy ma narzut synchronizacji, aby zapewnić bezpieczeństwo wątku, podczas gdy właściwość buforowana jest inicjowana przez CLR przed jakimkolwiek innym kodem i nie musisz płacić kosztów synronizacji
Z punktu widzenia testowalności, Lazy jest dobrze przetestowanym i sprawdzonym artefaktem.
Ma jednak, moim zdaniem, bardzo lekki overhead nad inną opcją
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-10-07 09:53:14
Cóż, jeśli Twoja wydajność jest mniej więcej taka sama, to jedynym powodem do użycia Lazy<T>
nad buforowaną wersją byłoby to, że nie jesteś pewien, czy użytkownik rzeczywiście załaduje właściwość.
Punktem Lazy<T>
jest oczekiwanie, aż użytkownik będzie potrzebował zasobu, a następnie utworzenie go w danej instancji w czasie. Jeśli zawsze będą potrzebować zasobów, nie ma sensu używać Lazy<T>
, chyba że potrzebujesz innych celów, takich jak bezpieczeństwo wątku.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-02-27 17:51:55