2011-10-24 37 views
19

Jestem całkiem nowy dla C#, więc trzymaj się mnie.C# classes - Dlaczego tak wiele metod statycznych?

Jedną z pierwszych rzeczy, które zauważyłem w C# jest to, że wiele klas jest ciężkich metodą statyczną. Na przykład ...

Dlaczego go:

Array.ForEach(arr, proc) 

zamiast:

arr.ForEach(proc) 

I dlaczego jest to:

Array.Sort(arr) 

zamiast:

arr.Sort() 

Zapraszam do wskazania mi niektórych Najczęściej zadawanych pytań w Internecie. Jeśli szczegółowa odpowiedź znajduje się gdzieś w jakiejś książce, z zadowoleniem przyjmuję wskazówkę do tego również. Szukam ostatecznej odpowiedzi w tej sprawie, ale twoje spekulacje są mile widziane.

Odpowiedz

8

Zakładając, że this answer jest poprawna, metody instancji wymagają dodatkowego miejsca w "tabeli metod". Tworzenie statycznych metod statycznych mogło być wczesną decyzją oszczędzającą miejsce.

To, wraz z unikaniem wskaźnika this, sprawdzi, czy odwołania Amitd mogą zapewnić znaczny wzrost wydajności dla czegoś tak wszechobecnego jak tablice.

+0

Pytanie/odpowiedź, z którą się łączyłeś, jest tym, czego szukałem. Dzięki! Kilka minut temu odkryłem "List" i ta klasa działa w sposób, jakiego oczekiwałem. Odpowiedź tam dostaje się, dlaczego Array i List są zaprojektowane inaczej. – dharmatech

+0

W rzeczywistości, jeśli jeden z administratorów chce oznaczyć to jako duplikat pytania, z którym się łączyłeś, byłoby to ze mną w porządku. – dharmatech

11

Ponieważ są to klasy użytkowe. Konstrukcja klasowa to po prostu sposób na grupowanie ich razem, biorąc pod uwagę, że nie ma żadnych wolnych funkcji w języku C#.

+0

Nie nazwałbym "Tablicą" klasy użytkowej. Jest to abstrakcyjna klasa bazowa, z której wyprowadzane są wszystkie tablice ... co wydaje się dobrym miejscem do tworzenia tych metod instancji. Myślę, że to dobre pytanie. – Daniel

+0

@Daniel Może Array nie jest klasą użyteczną jako taką, ale statyczne metody, które oferuje, z pewnością wyglądają jak metody narzędziowe, które zostały w niej zgrupowane. – Christian

+0

nie zgadzają się, że wyraźnie odwołują się do własnego obiektu, więc naprawdę powinny być metodami, prawdopodobnie nadal można je zmienić na metody rozszerzające, ale może to mieć zbyt niski koszt/korzyść. –

0

Klasa Array nie jest generyczna i nie można jej w pełni generować, ponieważ złamałoby to kompatybilność wsteczną. Trwa magia, w której tablice implementują IList<T>, ale to tylko dla tablic jednowymiarowych z dolną granicą tablic 0 - "list-ish".

Zgaduję, że metody statyczne są jedynym sposobem dodania ogólnych metod, które działają nad dowolnym kształtem tablicy, niezależnie od tego, czy kwalifikuje się ona do wspomnianej wyżej magii kompilatora.

+1

Zawsze byłeś w stanie leczyć dowolną macierz type ('string []', 'int []', etc) jako instancja 'Array', więc nie sądzę, że argument _lack of generics_ hold. – Daniel

+0

@Daniel: Chodzi mi o to, że tablice nie mają * żadnych * metod instancji, w których podpis zawiera typ elementu. 'List ' i takie do - to sprawia, że ​​myślę, że wyjaśnienie "funkcji narzędziowych" nie zawiera wody. Wygląda więc na to, że tablice są w jakiś sposób "specjalne". A ponieważ "specjalność" to brak metod instancji z parametrem typu odbiorcy w metodach * ogólnych *, mój wniosek jest taki, że tablice, w ogólnym przypadku, po prostu nie są generyczne. – millimoose

1

Klasyczne motywy przeciw statyczny:

  1. Trudno przetestować
  2. Not wątku bezpieczny
  3. zwiększa rozmiar kodu w pamięci

1) C# ma kilka narzędzi, które sprawiają, że testowanie metody statyczne są stosunkowo łatwe. Porównanie narzędzi szyderstwa języka C#, z których niektóre obsługują szykanie statyczne: https://stackoverflow.com/questions/64242/rhino-mocks-typemock-moq-or-nmock-which-one-do-you-use-and-why

2) Istnieją dobrze znane, wydajne sposoby tworzenia statycznych obiektów/logiki bez utraty bezpieczeństwa wątków w języku C#. Na przykład wykonawczego wzór Singleton ze statycznym klasy C# (można przejść do sposobu piątego jeśli niewystarczające możliwości nudnych) http://www.yoda.arachsys.com/csharp/singleton.html

3) Jak wspomniano @ K ballo każdy sposób przyczynia się do wielkości kodu w pamięci w języku C#, a nie metody instancji uzyskujące specjalne traktowanie.

To powiedziawszy, 2 konkretne przykłady, które wskazałeś, to tylko problem z obsługą starszego kodu dla statycznej klasy Array, zanim generics i jakiś inny kod został wprowadzony w C# 1.0 dniach, jak powiedział @Inerdia. Próbowałem odpowiedzieć, zakładając, że masz więcej kodu, o którym mówiłeś, być może włączając zewnętrzne biblioteki.

+2

Dlaczego miałbym testować metody ramowe? Czy odpowiadasz na pytanie lub po prostu mówisz o zdefiniowaniu metod statycznych, czy nie w swoim kodzie? – manojlds

+1

Pytanie zadawane, dlaczego tak wiele statyki w języku C#, a nie dlaczego tak wielu w ramach konkretnie. Te dwa przykłady okazały się bardzo starymi, dobrze przetestowanymi metodami ramowymi, ale założyłem, że pytanie dotyczy bibliotek C# i ogólnie kodu. Zwrócę również uwagę, że istnieją nowsze metody ramowe z mniejszym testowaniem, które mogą być warte napisania własnego testu, ponieważ kod nie zadziała zgodnie z oczekiwaniami - nie wszystko, co Microsoft robi, jest wolne od błędów. –

1

Postrzegana funkcjonalność.

Funkcje "użytkowe" różnią się od funkcji, do których cel OO ma służyć.

Pomyśl o przypadku z kolekcjami, we/wy, matematyką i prawie wszystkimi użytecznościami.

Z OO generalnie modelujesz swoją domenę. Żadna z tych rzeczy naprawdę nie pasuje do twojej domeny - to nie jest tak, że kodujesz i mówisz: "Och, musimy zamówić nowy hashtable, nasz jest pełny". Produkty użytkowe często po prostu nie pasują.

Dostajemy się blisko, ale nadal nie jest zbyt dużo, aby przekazać kolekcje (gdzie jest logika biznesowa? Gdzie umieszczasz metody, które manipulują twoją kolekcją i tym innym małym kawałkiem lub dwoma danymi, które zawsze przekazujesz z nim?)

To samo z liczbami i matematyką. Trudno jest mieć Integer.sqrt() i Long.sqrt() i Float.sqrt() - to po prostu nie ma sensu, ani "nowa Math(). Sqrt()". Jest wiele obszarów, których po prostu nie modeluje. Jeśli szukasz modelowania matematycznego, OO może nie być najlepszym rozwiązaniem. (Zrobiłem całkiem kompletną klasę "Complex" i "Matrix" w Javie i uczyniłem je całkiem OO, ale dzięki temu naprawdę nauczyłem się niektórych ograniczeń OO i Java - w końcu skończyłem "Używanie" klas z Groovy)

Nigdy nie widziałem niczego w pobliżu tak dobrze jak OO do modelowania logiki biznesowej, będąc w stanie zademonstrować związki między kodem a zarządzaniem relacjami między danymi i kodem.

Wracamy do innego modelu, gdy ma to więcej sensu.

5

także zobaczyć tę regułę z FXCOP

CA1822: Mark members as static

Opis reguły

Użytkownicy, że nie korzysta z danych instancji lub wywołania metody instancji może być oznaczone jako statyczny (Shared w języku Visual Basic) . Po oznaczeniu metod jako statyczne, kompilator będzie emitował strony wywołania wirtualnego do tych członków. Emitowanie stron wywołań innych niż wirtualne uniemożliwi sprawdzenie przy uruchomieniu dla każdego wywołania, które upewnia się, że wskaźnik bieżącego obiektu ma wartość inną niż null. Może to osiągnąć wymierny wzrost wydajności dla kodu wrażliwego na wydajność. W niektórych przypadkach brak dostępu do bieżącego obiektu obiektu reprezentuje problem z poprawnością.

Powiązane problemy