W moim rozumieniu partial
słowo kluczowe nie pozwala na podział klasy na kilka plików źródłowych. Czy jest jakiś inny powód do tego niż organizacja kodu? Widziałem to używane w generowanych klasach interfejsu użytkownika.
Wydaje się, że to zły powód, aby utworzyć całe słowo kluczowe. Jeśli klasa jest wystarczająco duża, aby wymagać wielu plików, prawdopodobnie robi zbyt wiele. Pomyślałem, że być może można go użyć do częściowego zdefiniowania klasy, którą inny programista może dokończyć, ale lepiej byłoby stworzyć klasę abstrakcyjną.
c#
design
language-design
Michael K.
źródło
źródło
partial
oznacza tylko coś, co nastąpi wcześniejclass
. Możesz użyć go jako nazwy identyfikatora w innych częściach kodu itp.Odpowiedzi:
Jest to bardzo przydatne w każdym scenariuszu, w którym jedna część klasy jest generowana przez jakieś niestandardowe narzędzie, ponieważ pozwala na dodanie niestandardowej logiki do generowanego kodu bez dziedziczenia wygenerowanej klasy. Btw. istnieją również częściowe metody z tego samego powodu.
Nie chodzi tylko o interfejs użytkownika, ale także o inne technologie, takie jak Linq-To-Sql lub Entity Framework.
źródło
Jak mówisz, często służy do oddzielania generowanego kodu. Często nie ma to nic wspólnego z rozmiarem klas / plików.
Zaletą oddzielania generowanego kodu jest styl. Wygenerowany kod może być dość brzydki i nieczytelny i nie spełniłby wielu standardów kodowania (i kontroli StyleCop), ale to jest OK, nikt nie musi go czytać ani utrzymywać bezpośrednio. Tak więc, jeśli „ukryjesz” go w innym pliku, możesz skoncentrować się na upewnieniu się, że reszta klasy jest zgodna ze standardem, przejdzie testy StyleCop i tak dalej.
Innym obszarem, w którym go używałem, jest klasa, w której implementuje się wiele interfejsów, całkiem fajnie może być rozdzielenie implementacji na osobne pliki, chociaż jest to raczej kwestia osobistych preferencji, nigdy nie widziałem, żeby wymagały to jakiekolwiek standardy kodowania ( lub zapobiec).
źródło
Jeden z programistów, w którym pracuję, wpadł na całkiem niezłe zastosowanie kilka tygodni temu w refaktoryzacji wielkich klas Bożych, które wymknęły się spod kontroli i mają wiele publicznych metod: oddzielając logiczne funkcje każdego elementu klasę na osobne klasy cząstkowe. Można fizycznie oddzielić klasę na bardziej atomowe jednostki, które powinny być klasami, bez przerywania istniejącej funkcjonalności, pozwalając zobaczyć, co jest wspólne, a co nie. Dzięki temu jako pierwszemu etapowi możesz łatwiej rozdzielić częściowe na ich własne niezależne klasy i zaimplementować je w całej bazie kodu. Myślałem, że to fajny pomysł.
Ogólnie jednak myślę, że powinny być one używane tylko do rozszerzania klas generowanych maszynowo podczas pisania nowego kodu.
źródło
Mogę wymyślić kilka przydatnych scenariuszy, w których częściowe mają sens, większość z nich wykorzystuję w swoich projektach:
Aby oddzielić wygenerowany kod Tool / IDE / Designer od kodu, który utrzymujesz. Dobrym przykładem jest
Form.Designer.cs
plik zawierający kod wygenerowany przez projektanta dla aplikacji formularzy Windows. Wiele innych formatów .NET ma również kod generowany przez narzędzie, który może zostać potencjalnie zregenerowany podczas tworzenia projektu, a zatem wszystkie niestandardowe zmiany zostaną usunięte. Rozdzielenie pomoże ci zachować kod i zmiany przed takimi automatycznymi modyfikacjami.Podczas implementowania wielu interfejsów z dużą ilością kodu w implementacji. I mają tendencję do korzystania z oddzielnego pliku częściowe dla każdego takiego interfejsu, nazywając to tak:
{Class}.{Interface}.cs
. Łatwo jest mi zobaczyć w IDE, które interfejs{Class}
implementuje i jak.Gdy klasa musi zawierać jedną lub więcej klas zagnieżdżonych , zwłaszcza z wystarczającą ilością kodu, aby można je było umieścić w osobnym pliku. Trzymałbym się powyższego wzoru i używałbym
{Class}.{NestedClass}.cs
konwencji nazewnictwa dla każdej zagnieżdżonej klasy. Podobna praktyka jest już wspomniana w odpowiedzi Virtlink .Kiedy piszę
static
klasy, w których będą przechowywane metody rozszerzeń . Często zdarza się, że udostępnia się tę samą logikę metody rozszerzenia podobnym klasom lub interfejsom - na przykładReverse
w kolekcjach ogólnych i nie-ogólnych. Umieściłbym wszystkie metody rozszerzenia dla pojedynczej klasy lub interfejsu w osobnej części klasy statycznej. Na przykład miałbym wszystkie metody rozszerzeniaIList
interfejsu w jednym miejscu i te same metody, które sąIList<T>
w innym pliku. Innym podejściem byłoby umieszczenie tej samej metody (wszystkich jej przeciążeń) w tej samej częściowej, ze wszystkimi możliwymi klasami dlathis
parametru - na przykład mając wszystkieReverse
implementacje w jednym pliku. Zależy to od tego, który z nich lepiej uzasadniałby separację pod względem objętości kodu lub pewnych wewnętrznych konwencji, których ty lub twoja organizacja możecie się trzymać.Nie używam tego, ale widziałem ludzi z C / C ++, którzy lubią podejście, które tu opiszę: utwórz częściowe dla klasy tylko z częściowymi metodami . Przypomina to sposób C / C ++ do definiowania interfejsów i oddzielania deklaracji metod od implementacji.
Separacja według czysto logicznych problemów . Jeśli zdarzy ci się pracować z dużą klasą, która łączy w sobie więcej niż jeden logiczny zestaw operacji, możesz rozdzielić każdy związany z logiką kod na osobną część. Zwykle istnienie takich klas jest sprzeczne z zasadą rozdzielania obaw , ale często obserwuje się rzeczywisty przypadek, szczególnie w przypadku starszych baz kodowych. Inny użytkownik Steve Evers wspomniał o nich w swojej odpowiedzi na to pytanie , odnosząc się do nich pod nazwą bóg obiektów. Osobiście zastosowałbym podejście klas cząstkowych do podzielenia kodu przed dokonaniem refaktoryzacji tak naprawdę dużych plików, aby ułatwić mi pracę i uczynić refaktoryzację bardziej przejrzystą. Zmniejszy to również konflikty, które potencjalnie spowoduję, gdy zaangażowane będą systemy kontroli wersji, takie jak SVN.
źródło
Nikt o tym nie wspominał: używam
partial
do umieszczania zagnieżdżonych klas we własnych plikach.Wszystkie moje pliki kodu zawierają tylko jedną klasę, strukturę, interfejs lub wyliczenie. Znacznie łatwiej jest znaleźć definicję obiektu, gdy nazwy plików pokazują nazwę rzeczy, której szukasz. A ponieważ Visual Studio próbuje dopasować foldery projektu do przestrzeni nazw, nazwy plików powinny pasować do klas.
Oznacza to również, że klasa
NestedClass
zagnieżdżona wewnątrzMyClass
będzie mieć swój własny plik w moich projektach:MyClass.NestedClass.cs
.źródło
Z wyjątkiem przy użyciu kodu wygenerowanego, mam tylko widział je stosować w celu ukrycia dla obiektów boga . Próba zrozumienia nowej bazy kodu lub poruszania się po wielu plikach źródłowych, które są tym samym obiektem, jest bardzo denerwująca.
Więc kiedy pytasz
Why use partial classes?
, odpowiadam: chyba że używasz wygenerowanego kodu, nie rób tego.źródło
Organizacja kodu jest jedynym powodem, ale idzie głębiej, niż się wydaje. Jeśli masz częściowe klasy, w których części są generowane, możesz łatwo:
źródło
Istnieje również kilka miejsc, w których generowane / dorozumiane klasy są zadeklarowane jako częściowe, więc jeśli Dev musi je rozszerzyć, mają pełny dostęp bez konieczności bałagania się o dziedziczenie i nadpisywanie w całym miejscu. Spójrz na wygenerowane klasy w obszarze temp asp.net po uruchomieniu witryny sieci Web po raz pierwszy w IIS, jeśli chcesz spróbować złapać kilka przykładów.
źródło
Mogę wymyślić dla nich brudne zastosowanie.
Załóżmy, że masz klasy, które potrzebują wspólnej funkcjonalności, ale nie chcesz wstawiać tej funkcji do łańcucha dziedziczenia nad nimi. Lub masz zestaw klas, które używają wspólnej klasy pomocniczej.
Zasadniczo chcesz zrobić wielokrotne dziedziczenie, ale C # nie lubię. Więc używasz częściowego, aby stworzyć coś, co zasadniczo jest #include w C / C ++;
Umieść całą funkcjonalność w klasie lub użyj klasy pomocnika. Następnie skopiuj pomocnika X razy i zmień jego nazwę na częściową klasę A, B, C. i częściowo ułóż na swoich klasach A, B, C.
Zastrzeżenie: Tak, to jest złe. Nigdy tego nie rób - zwłaszcza jeśli spowoduje to, że inni będą na ciebie źli.
źródło