Czy metody C #, które * mogą * być statyczne, powinny być statyczne? [Zamknięte]


103

Czy metody C #, które mogą być statyczne, powinny być statyczne?

Rozmawialiśmy o tym dzisiaj i jestem na płocie. Wyobraź sobie, że masz długą metodę, w której refaktoryzujesz kilka wierszy. Nowa metoda prawdopodobnie pobiera kilka zmiennych lokalnych z metody nadrzędnej i zwraca wartość. Oznacza to, że może być statyczny.

Pytanie brzmi: czy powinno być statyczne? Nie jest statyczny z założenia ani z wyboru, po prostu z natury, ponieważ nie odwołuje się do żadnych wartości instancji.



41
„dość dokładny” to oksymoron
Matt Briggs

1
Resharper , narzędzie narzędzi Visual Studio, mówi tak! :-)
Rebecca

@Junto Może w twojej wersji, ale moja mówi, że można ją statycznie ...
Robbie Dee

Odpowiedzi:


59

To zależy. Naprawdę istnieją 2 rodzaje metod statycznych:

  1. Metody, które są statyczne, ponieważ MOGĄ być
  2. Metody, które są statyczne, ponieważ MUSZĄ takie być

W małej lub średniej bazie kodu można naprawdę traktować obie metody zamiennie.

Jeśli masz metodę, która należy do pierwszej kategorii (może być statyczna) i musisz ją zmienić, aby uzyskać dostęp do stanu klasy, stosunkowo łatwo jest dowiedzieć się, czy można zmienić metodę statyczną w metodę instancji.

Jednak w dużej bazie kodu sama liczba witryn wywołujących może sprawić, że wyszukiwanie w celu sprawdzenia, czy możliwe jest przekonwertowanie metody statycznej na niestatyczną, jest zbyt kosztowne. Wiele razy ludzie zobaczą liczbę połączeń i powiedzą „ok ... lepiej nie zmieniać tej metody, ale zamiast tego utworzę nową, która robi to, czego potrzebuję”.

Może to spowodować:

  1. Dużo powielania kodu
  2. Eksplozja liczby argumentów metod

Obie te rzeczy są złe.

Więc moja rada byłaby taka, że ​​jeśli masz kod bazowy powyżej 200K LOC, uczyniłbym metody statycznymi tylko wtedy, gdy są one metodami statycznymi.

Refaktoryzacja z niestatycznej do statycznej jest stosunkowo łatwa (wystarczy dodać słowo kluczowe), więc jeśli chcesz później przekształcić zmienną can-be-static w rzeczywistą statyczną (gdy potrzebujesz jej funkcjonalności poza instancją), możesz. Jednak refaktoryzacja odwrotna polegająca na przekształceniu metody can-be-static w metodę instancji jest DUŻO droższa.

W przypadku dużych baz kodu lepiej jest popełniać błędy po stronie łatwości rozszerzenia niż po stronie czystości idealogicznej.

Tak więc w przypadku dużych projektów nie rób statycznych rzeczy, chyba że tego potrzebujesz. W przypadku małych projektów po prostu rób to, co lubisz najbardziej.


43

Chciałbym nie sprawiają, że publiczne statyczne członkiem tej klasy . Powodem jest to, że upublicznienie statycznego oznacza powiedzenie czegoś o typie klasy: nie tylko to, że „ten typ wie, jak zrobić to zachowanie”, ale także „to on jest odpowiedzialny za wykonanie tego zachowania”. A są szanse, że zachowanie nie ma już żadnego rzeczywistego związku z większym typem.

Nie oznacza to jednak, że w ogóle bym tego nie statował. Zadaj sobie pytanie: czy nowa metoda logicznie może być inna? Jeśli możesz na to odpowiedzieć „tak”, prawdopodobnie zechcesz uczynić go statycznym (i również go przesunąć). Nawet jeśli to nieprawda, nadal możesz to uczynić statycznym. Po prostu nie zaznaczaj tego public.

Dla wygody możesz przynajmniej to oznaczyć internal. Zwykle pozwala to uniknąć konieczności przenoszenia metody, jeśli nie masz łatwego dostępu do bardziej odpowiedniego typu, ale nadal pozostawia ją dostępną w razie potrzeby w taki sposób, że nie będzie wyświetlana jako część publicznego interfejsu dla użytkowników Twojej klasy .


6
Zgoda. Generalnie ustawiam metodę jako „private static” w takim przypadku.
harpo

6
Nie zakładałbym też prywatnych zakłóceń. Najważniejsze jest, aby zadać sobie pytanie: czy ta metoda logicznie pasuje do tego typu, czy też jest tutaj dla wygody? Jeśli to drugie, czy lepiej pasowałoby gdzie indziej?
Joel Coehoorn

1
Na przykład: „czy nowa metoda mogłaby logicznie należeć gdzie indziej” - wskazówka jest taka, że ​​nie polega ona na stanie lokalnym, być może typ zwracany jest tam, gdzie należy?
AndyM

20

Niekoniecznie.

Przeniesienie metod publicznych ze statycznej na niestatyczną jest przełomową zmianą i wymagałoby zmian dla wszystkich wywołań lub konsumentów. Jeśli metoda wydaje się być metodą instancji, ale nie wykorzystuje żadnych elementów instancji, sugerowałbym uczynienie jej metodą instancji jako miary przyszłości.


Myślę, że odnosi się głównie do prywatnych metod
George Mauer

@Ray - racja, dotyczy to tylko członków niebędących osobami prywatnymi. Zaktualizowałem odpowiedź, aby to odzwierciedlić.
Michael

Moje myśli dokładnie - tylko dlatego, że mógłby zrobić coś statycznego nie znaczy, trzeba lub powinno .....
marc_s

Więc co byś zrobił dla prywatnych metod, które można uczynić statycznymi?
Ray

@Ray - Prawdopodobnie zostawię tak, jak jest, dopóki nie będę miał wystarczającego powodu, aby przejść do statycznego.
Michael

13

Tak. Powodem, dla którego „może być statyczny” jest to, że nie działa na stan obiektu, na którym jest wywoływana. Dlatego nie jest to metoda instancji, ale metoda klasowa. Jeśli może robić to, co musi, nigdy nie uzyskując dostępu do danych instancji, powinien być statyczny.


11

Tak, powinno. Istnieją różne metryki sprzężenia, które mierzą zależność twojej klasy od innych rzeczy, takich jak inne klasy, metody itp. Uczynienie metod statycznymi jest sposobem na utrzymanie niskiego stopnia sprzężenia, ponieważ możesz być pewien, że metoda statyczna nie odwołuje się do żadnych członków.


7
Niekoniecznie. Metoda statyczna nie będzie miała dostępu do informacji o instancji, żadnych członków, jak powiedziałeś, ale może współdziałać z innymi klasami, a także z inną popularną metodą. Bycie statycznym nie oznacza koniecznie ograniczenia sprzężenia. Jednak zrozumiałem twój punkt widzenia.
Victor Rodrigues

Zamiast tego statyczność faktycznie zwiększa sprzężenie, ponieważ jesteś ograniczony do dokładnie tej statycznej metody, na przykład nie ma możliwości jej ominięcia, a tym samym nie ma możliwości zmiany zachowania.
HimBromBeere

8

Myślę, że byłoby to trochę bardziej czytelne, gdybyś oznaczył to jako statyczne ... Wtedy ktoś, kto się pojawi, będzie wiedział, że nie odwołuje się do żadnych zmiennych instancji bez konieczności czytania całej funkcji ...


6

Osobiście jestem wielkim fanem bezpaństwowości. Czy Twoja metoda wymaga dostępu do stanu klasy? Jeśli odpowiedź brzmi nie (i prawdopodobnie nie, w przeciwnym razie nie rozważałbyś uczynienia tego metodą statyczną), to tak, idź do tego.

Brak dostępu do stanu to mniejszy ból głowy. Tak jak dobrym pomysłem jest ukrycie prywatnych członków, którzy nie są potrzebni innym klasom, tak samo dobrym pomysłem jest ukrycie stanu przed członkami, którzy tego nie potrzebują. Ograniczony dostęp może oznaczać mniej błędów. Ułatwia również tworzenie wątków, ponieważ znacznie łatwiej jest zachować bezpieczeństwo wątków statycznych elementów członkowskich. Istnieje również kwestia wydajności, ponieważ środowisko wykonawcze nie musi przekazywać odwołania do tego jako parametru dla metod statycznych.

Oczywiście wadą jest to, że jeśli kiedykolwiek okaże się, że Twoja poprzednio statyczna metoda będzie musiała uzyskać dostęp do stanu z jakiegoś powodu, musisz to zmienić. Teraz rozumiem, że może to stanowić problem dla publicznych interfejsów API, więc jeśli jest to metoda publiczna w klasie publicznej, być może powinieneś trochę pomyśleć o konsekwencjach tego. Mimo to nigdy nie spotkałem się z sytuacją w prawdziwym świecie, w której rzeczywiście spowodowałoby to problem, ale może po prostu mam szczęście.

Więc tak, zrób to, jak najbardziej.


1
Metoda statyczna nadal może mieć dostęp do stanu. Po prostu pobiera stan z przekazanego do niego obiektu. I odwrotnie, pola instancji niekoniecznie zawierają zmienny stan.
Jørgen Fogh

6

Metody statyczne są szybsze niż metody niestatyczne, więc tak, powinny być statyczne, jeśli to możliwe i nie ma specjalnego powodu, aby pozostawić je niestatyczne .


3
Jest to technicznie prawda, ale nie w sensie materialnym. Różnica między statycznym a brakiem bardzo, bardzo rzadko będzie czynnikiem wpływającym na wydajność.
Foredecker

22
-1: Przedwczesna optymalizacja podręcznika. Szybkość z pewnością nie powinna być pierwszym kryterium przy decydowaniu o statycznej lub niestatycznej w przypadku ogólnym.
Nie jestem pewien,

2
Zgadzam się z Nie jestem pewien, to powinien być twój ostatni powód, aby kiedykolwiek rozważyć statyczne czy nie.
Samuel

5
Chodzi mi o to, że szybkość jest jednym z najgorszych powodów, dla których można zdecydować, czy funkcja jest statyczna czy niestatyczna w 99% przypadków. Istnieją znacznie ważniejsze kwestie, jeśli chodzi o projektowanie obiektów obiektowych, niż inne posty.
Nie jestem pewien,

2
@agnieszka: Szczególnym powodem używania metod instancji zamiast metod statycznych jest stan. Jeśli zostawisz swoje metody statyczne, w złożonej aplikacji wprowadzisz błędy, które będą powodować wyrywanie włosów. Pomyśl o
zmianie

5

Dziwię się, że tak niewielu wspomina tutaj o hermetyzacji. Metoda instancji automatycznie uzyska dostęp do wszystkich prywatnych pól (instancji), właściwości i metod. Oprócz wszystkich chronionych dziedziczonych z klas podstawowych.

Kiedy piszesz kod, powinieneś pisać go tak, aby ujawniać jak najmniej, a także aby mieć jak najmniejszy dostęp.

Więc tak, może być ważne, aby przyspieszyć kod, co mogłoby się zdarzyć, gdybyś uczynił swoje metody statycznymi, ale zwykle ważniejsze jest to, aby kod był tak samo niezdolny do tworzenia błędów, jak to tylko możliwe. Jednym ze sposobów na osiągnięcie tego jest zapewnienie, aby Twój kod miał jak najmniejszy dostęp do „prywatnych rzeczy”.

Na pierwszy rzut oka może się to wydawać nieistotne, ponieważ OP oczywiście mówi o refaktoryzacji, która nie może się nie udać w tym scenariuszu i stworzyć żadnych nowych błędów, jednak ten refaktoryzowany kod musi być utrzymywany w przyszłości i modyfikowany, co powoduje, że twój kod ma większy "atak surface ”w odniesieniu do nowych błędów, jeśli ma dostęp do prywatnych członków instancji. Generalnie myślę, że wniosek jest taki „tak, głównie twoje metody powinny być statyczne”, chyba że istnieją inne powody, dla których nie mają one statyczności. A to po prostu dlatego, że „lepsze wykorzystanie hermetyzacji i ukrywania danych oraz tworzenie„ bezpieczniejszego ”kodu”…


4

Robienie czegoś statycznego tylko dlatego, że możesz, nie jest dobrym pomysłem. Metody statyczne powinny być statyczne ze względu na swój projekt, a nie z przypadku.

Jak powiedział Michael, zmiana tego później spowoduje uszkodzenie kodu, który go używa.

Mając to na uwadze, wygląda na to, że tworzysz prywatną funkcję narzędzia dla klasy, która w rzeczywistości jest statyczna z założenia.


4

Jeśli udało Ci się zrefaktoryzować kilka wierszy, a wynikowa metoda mogłaby być statyczna, prawdopodobnie oznacza to, że wiersze, które wyciągnąłeś z tej metody, w ogóle nie należą do klasy zawierającej i powinieneś rozważyć przeniesienie ich do własną klasę.


2

Osobiście nie miałbym innego wyboru, jak tylko uczynić to statycznym. Resharper ostrzega w tym przypadku, a nasz premier ma zasadę „Żadnych ostrzeżeń od Resharper”.


1
Możesz zmienić ustawienia ReSharper: P
Bernhard Hofmann

1
Gdyby to było takie łatwe, nie mielibyśmy żadnych ubrań od Resharper ... nigdy :)
Prankster

1

To zależy, ale generalnie nie ustawiam tych metod jako statyczne. Kod ciągle się zmienia i być może kiedyś będę chciał uczynić tę funkcję wirtualną i zastąpić ją w podklasie. A może pewnego dnia będzie musiał odwołać się do zmiennych instancji. Wprowadzenie tych zmian będzie trudniejsze, jeśli trzeba będzie zmienić każdą witrynę wywołującą.


Tak, ale jeśli kiedyś będziesz musiał to zrobić, zawsze możesz to zrobić, aby nie było statyczne. A może coś mi brakuje?
Ray

1
@Ray - omawiam to w mojej odpowiedzi. Statyczny na niestatyczny to przełomowa zmiana, więc wszyscy konsumenci muszą zostać zmodyfikowani. Nie jest to wielka sprawa dla małego programu, ale jeśli jest to biblioteka do użytku przez innych, należy to wziąć pod uwagę.
Michael

Wszystkie witryny wywołań muszą zostać zmienione z wywołania metody statycznej na wywołanie funkcji składowej.
Brian Ensink

Przepraszam, dodałeś to po moim komentarzu. W mojej głowie myślałem o metodach prywatnych, ale to ważny punkt w przypadku metod publicznych.
Ray

... lub któregoś dnia możesz to wyrzucić. te argumenty nie są wystarczająco dobre, abym mógł uczynić metodę niestatyczną.
agnieszka

1

Sugeruję, aby najlepiej o tym pomyśleć: Jeśli potrzebujesz metody klasy, która musi być wywołana, gdy żadne instancje klasy nie są tworzone lub utrzymują jakiś stan globalny, statyczny jest dobrym pomysłem. Ale ogólnie sugeruję, abyś wolał, aby członkowie nie byli statyczni.


1

Powinieneś pomyśleć o swoich metodach i klasach:

  • Jak zamierzasz ich używać?
  • Potrzebujesz dostępu do nich z różnych poziomów swojego kodu?
  • Czy to metoda / klasa, której mogę użyć w prawie każdym możliwym do pomyślenia projekcie.

Jeśli ostatnie dwa to „tak”, twoja metoda / klasa powinna być prawdopodobnie statyczna.

Najczęściej używanym przykładem jest prawdopodobnie Mathklasa. Każdy główny język obiektowy ma to i wszystkie metody są statyczne. Ponieważ musisz mieć możliwość korzystania z nich w dowolnym miejscu i czasie, bez tworzenia instancji.

Innym dobrym przykładem jest Reverse()metoda w C #.
To jest metoda statyczna w Arrayklasie. Odwraca kolejność twojej tablicy.

Kod:

public static void Reverse(Array array)

Nawet nic nie zwraca, twoja tablica jest odwrócona, ponieważ wszystkie tablice są instancjami klasy Array.


Matematyka to zły przykład. Myślę, że jest lepiej: newnumber = number.round (2) than newnumber = Math.round (number)
graffic

3
Klasa Math jest doskonałym przykładem wykorzystania klas statycznych. O tym jest ten temat, a nie o tym, jak wolisz zaokrąglać liczby ...
KdgDev

1

Tak długo, jak ustawisz nową metodę jako private static, nie będzie to przełomowa zmiana. W rzeczywistości FxCop zawiera te wskazówki jako jedną ze swoich zasad ( http://msdn.microsoft.com/en-us/library/ms245046(VS.80).aspx ), z następującymi informacjami:

Po oznaczeniu metod jako statycznych kompilator wyemituje niewirtualne witryny wywołań do tych elementów członkowskich. Emitowanie niewirtualnych witryn wywołań uniemożliwi sprawdzanie w czasie wykonywania każdego wywołania, które gwarantuje, że bieżący wskaźnik obiektu ma wartość różną od null. Może to spowodować wymierny wzrost wydajności w przypadku kodu wrażliwego na wydajność. W niektórych przypadkach brak dostępu do bieżącej instancji obiektu oznacza problem z poprawnością.

To powiedziawszy, pierwszy komentarz Davida Kean'a bardziej zwięźle podsumowuje obawy, mówiąc, że w rzeczywistości chodzi bardziej o bycie poprawnym niż o wzrost wydajności:

Chociaż ta reguła jest klasyfikowana jako problem z wydajnością, poprawa wydajności dzięki uczynieniu metody statyczną wynosi tylko około 1%. Jest to raczej problem z poprawnością, który może wskazywać na niekompletność lub błąd w elemencie członkowskim przez niepowodzenie w użyciu innych członków instancji. Oznaczanie metody statycznej ( Shared w Visual Basic) wyjaśnia, że ​​nie ma zamiaru dotykać stanu wystąpienia.


1

Zdecydowanie zmieniłbym wszystko, co mogę w statyczne z innego powodu:

Funkcje statyczne, gdy są JIT, są wywoływane bez parametru „this”. Oznacza to na przykład, że 3-parametrowa funkcja niestatyczna (metoda składowa) zostaje wypchnięta z 4 parametrami na stosie.

Ta sama funkcja skompilowana jako funkcja statyczna byłaby wywoływana z 3 parametrami. Może to zwolnić rejestry dla JIT i zaoszczędzić miejsce na stosie ...


1

Jestem w obozie „Tylko statyczne metody prywatne”. Utworzenie metody publicznej może wprowadzić sprzężenie, którego nie chcesz, i może zmniejszyć testowalność: nie możesz zablokować publicznej metody statycznej.

Jeśli chcesz przetestować jednostkowo metodę, która używa publicznej metody statycznej, w końcu testujesz również metodę statyczną, co może nie być tym, czego chcesz.


1

Z natury statyczne metody, które z jakiegoś powodu są niestatyczne, są po prostu irytujące. Dowcip:

Dzwonię do banku i pytam o saldo.
Proszą o numer mojego konta.
Słusznie. Metoda instancji.

Dzwonię do banku i pytam o adres pocztowy.
Proszą o numer mojego konta.
WTF? Niepowodzenie - powinno być metodą statyczną.


1
A jeśli różni klienci są obsługiwani przez różne oddziały? Korespondencja wysyłana pocztą do centrali banku może w końcu trafić do odpowiedniego oddziału, ale nie oznacza to, że klientowi nie byłoby lepiej, gdyby korzystał z adresu oddziału, który go obsługuje.
supercat

0

Patrzę na to ogólnie z funkcjonalnej perspektywy czystych funkcji. Czy musi to być metoda instancji? Jeśli nie, możesz skorzystać na zmuszeniu użytkownika do przekazania zmiennych i nie manipulowaniu stanem bieżącej instancji. (Cóż, nadal możesz zmieniać stan, ale chodzi o to, aby zgodnie z projektem tego nie robić). Generalnie projektuję metody instancji jako publiczne elementy członkowskie i staram się, aby prywatne elementy członkowskie były statyczne. Jeśli to konieczne (możesz później łatwiej wyodrębnić je do innych klas.


-1

W takich przypadkach staram się przenosić metodę do biblioteki statycznej lub utils, więc nie mieszam pojęcia „obiektu” z pojęciem „klasy”

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.