Kiedy należy stosować klasy częściowe C #?


Odpowiedzi:


422

Największym zastosowaniem klas częściowych jest ułatwienie życia generatorom / projektantom kodów. Klasy częściowe pozwalają generatorowi po prostu wyemitować kod, który muszą wyemitować i nie muszą zajmować się edycją pliku przez użytkownika. Użytkownicy mogą również dodawać adnotacje do klasy z nowymi członkami, mając drugą klasę częściową. Zapewnia to bardzo czyste ramy dla rozdzielenia problemów.

Lepszym sposobem na to jest sprawdzenie, jak projektanci funkcjonowali przed częściowymi zajęciami. Projektant WinForm wyplułby cały kod w regionie z silnie sformułowanymi komentarzami na temat nie modyfikowania kodu. Musiał wstawić wszelkiego rodzaju heurystykę, aby znaleźć wygenerowany kod do późniejszego przetworzenia. Teraz może po prostu otworzyć plik designer.cs i mieć wysoki stopień pewności, że zawiera tylko kod odpowiedni dla projektanta.


70
Kusiło cię, by dać ci -1 za to, że dałeś mi koszmary o tym, jak złe były rzeczy przed częściowymi lekcjami :)
Jon B

9
@Jon :) Myślę, że wszyscy mieliśmy koszmary.
JaredPar

18
Kiedyś napisałem generator kodu, który produkuje ponad 36 000 wierszy (a prawdopodobnie znacznie więcej, nie pamiętam dokładnie), a moje edytory zostały zablokowane, gdy źródło zostało otwarte. Klasy częściowe pozwoliły mi zobaczyć wytworzony kod bez 4 GB pamięci RAM.
Luca

6
Chciałbym powiedzieć, że jest to jedyne zastosowanie dla klas częściowych w kodzie produkcyjnym. Chociaż akceptuję to może być przydatne do refaktoryzacji.
Gordon McAllister

5
@Gordon - odpowiedź HumerGu to kolejna, o której moim zdaniem trudno jest się kłócić. Klasy częściowe mogą być bardzo przydatne do implementacji interfejsów w języku C # i utrzymywania elementów interfejsu wyraźnie oddzielonych od członków klasy: stackoverflow.com/questions/3601901/hyhy-use-partial-classes/…
STW

260

Innym zastosowaniem jest podzielenie implementacji różnych interfejsów, np .:

partial class MyClass : IF1, IF2, IF3
{
    // main implementation of MyClass
}


partial class MyClass
{
    // implementation of IF1
}

partial class MyClass
{
    // implementation of IF2
}

6
Słuszna uwaga! Jest to coś, co zrobiłem wcześniej i o czym zapomniałem, ale zdecydowanie jest to dobry sposób, aby członkowie interfejsu byli wyraźnie widoczni (szczególnie w języku C #, ponieważ VB.NET używa Implementssłowa kluczowego do oznaczenia metody należy do interfejsu)
STW

2
bardzo fajny punkt, każdy z interfejsów może zostać zaimplementowany przez programistę. To także dobry sposób na łatwe znalezienie implementacji interfejsu.
kokabi

3
skąd wiadomo, który jest dla IF1 lub IF2 .. według kolejności deklaracji klas?
kuldeep

17
Dobre zastosowanie, ale zły przykład. Dlaczego och, dlaczego zdefiniowałbyś wszystkie interfejsy w jednej klasie częściowej i zaimplementowałeś te same interfejsy w innych klasach częściowych? ..
inkredibl

4
Ha, właśnie sprawdziłem to pytanie, aby zobaczyć, czy oddzielne implementacje interfejsu były standardowym zastosowaniem dla klas częściowych. Cieszę się, że inni uważają to za dobry pomysł. Zgadzam się z @inkredibl co do umieszczenia definicji interfejsu wraz z klasą częściową, która ją implementuje.
Kim

170

Oprócz innych odpowiedzi ...

Uważam, że są one pomocne jako odskocznia w refaktoryzacji klas bożych. Jeśli klasa ma wiele obowiązków (szczególnie jeśli jest to bardzo duży plik kodu), uważam za korzystne dodanie 1x częściowej klasy na odpowiedzialność jako pierwszego przejścia do organizacji, a następnie refaktoryzacji kodu.

Pomaga to znacznie, ponieważ może pomóc w zwiększeniu czytelności kodu bez faktycznego wpływu na zachowanie. Może również pomóc w określeniu, kiedy odpowiedzialność można łatwo zrefaktoryzować lub jest ona ściśle związana z innymi aspektami.

Jednak - żeby być jasnym - jest to nadal zły kod, na końcu rozwoju nadal potrzebujesz jednej odpowiedzialności na klasę ( NIE na klasę częściową). To tylko odskocznia :)


23
Bardzo miło: „... pod koniec rozwoju nadal chcesz jednej odpowiedzialności na klasę ( NIE na klasę częściową) ...”
kokabi

Dla mnie nie jest to dobry styl kodowania, ale może sprawić, że złe kody będą wyglądały lepiej.
tematyczny

W pełni się z tym zgadzam. To dobry krok w kierunku naprawienia złego kodu. Klasa boga to pogoda klasy boga, która jest rozproszona na wiele plików lub nie.
Jimbo

84
  1. Wielu programistów korzystających z częściowych klas Wielu programistów może z łatwością pracować na tej samej klasie.
  2. Generator kodu Klasy częściowe są używane głównie przez generator kodu do oddzielenia różnych problemów
  3. Metody częściowe Za pomocą klas częściowych można również zdefiniować metody częściowe, w których programista może po prostu zdefiniować metodę, a drugi programista może to zaimplementować.
  4. Tylko częściowa deklaracja metody Nawet kod zostanie skompilowany tylko z deklaracją metody, a jeśli implementacja metody nie jest obecna, kompilator może bezpiecznie usunąć ten fragment kodu i nie wystąpi błąd czasu kompilacji.

    Aby zweryfikować punkt 4. Po prostu utwórz projekt winform i dołącz ten wiersz za konstruktorem Form1 i spróbuj skompilować kod

    partial void Ontest(string s);

Oto kilka punktów do rozważenia przy wdrażaniu klas częściowych:

  1. Użyj częściowego słowa kluczowego w każdej części częściowej klasy.
  2. Nazwa każdej części klasy częściowej powinna być taka sama, ale nazwa pliku źródłowego dla każdej części klasy częściowej może być inna.
  3. Wszystkie części klasy częściowej powinny znajdować się w tej samej przestrzeni nazw.
  4. Każda część klasy częściowej powinna znajdować się w tym samym zestawie lub bibliotece DLL, innymi słowy nie można utworzyć klasy częściowej w plikach źródłowych z innego projektu biblioteki klas.
  5. Każda część klasy częściowej musi mieć taką samą dostępność. (tj .: prywatny, publiczny lub chroniony)
  6. Jeśli odziedziczysz klasę lub interfejs na klasie częściowej, zostanie ona odziedziczona przez wszystkie części tej klasy częściowej.
  7. Jeśli część klasy częściowej jest zapieczętowana, wówczas cała klasa zostanie zapieczętowana.
  8. Jeśli część klasy częściowej jest abstrakcyjna, wówczas cała klasa będzie uważana za klasę abstrakcyjną.

1
Czy istnieje problem z edycją częściowej klasy utworzonej z Entity Framework? Chcę zmienić nazwy niektórych klas, utworzone z tabeli.
MarceloBarbosa,

Mam te same obawy. Chcę poznać korzyści „Jeśli w ogóle”, jakie ma klasa częściowa podczas budowania modeli, które Entity Framework zasadniczo wykorzysta do zbudowania mojej bazy danych z perspektywy / podejścia / implementacji Code First ... co masz.
Chef_Code

@JimBalter Prosimy przejść przez ten link msdn.microsoft.com/en-us/library/6b0scde8(v=vs.110).aspx . Oznacza to, że jeśli nie ma żadnej implementacji, kompilator usunie fragment kodu i nie otrzyma błędu czasu kompilacji.
hellowahab

Jeśli odziedziczysz klasę lub interfejs na klasie częściowej, zostanie ona odziedziczona przez wszystkie części tej klasy częściowej.
Czerwony groszek

56

Jednym z wielkich zastosowań jest oddzielenie generowanego kodu od odręcznego kodu należącego do tej samej klasy.

Na przykład, ponieważ LINQ do SQL używa klas częściowych, możesz napisać własną implementację niektórych funkcji (takich jak relacje wiele do wielu), a te fragmenty niestandardowego kodu nie zostaną zastąpione podczas ponownego generowania kodu.

To samo dotyczy kodu WinForms. Cały kod wygenerowany przez Projektanta znajduje się w jednym pliku, którego zazwyczaj nie dotykasz. Twój ręcznie napisany kod trafia do innego pliku. W ten sposób, gdy zmienisz coś w Projektancie, twoje zmiany nie zostaną zdmuchnięte.


21

Prawdą jest, że Partial Class jest używana do automatycznego generowania kodu, jednym z zastosowań może być utrzymanie dużego pliku klasy, który może zawierać tysiące wierszy kodu. Nigdy nie wiesz, że Twoja klasa może skończyć z 10 tysiącami linii i nie chcesz tworzyć nowej klasy o innej nazwie.

public partial class Product
{
    // 50 business logic embedded in methods and properties..
}

public partial class Product
{
    // another 50 business logic embedded in methods and properties..
}
//finally compile with product.class file.

Innym możliwym zastosowaniem może być to, że więcej niż jeden programista może pracować na tej samej klasie, ponieważ są one przechowywane w różnych miejscach. Ludzie mogą się śmiać, ale nigdy nie wiadomo, że czasem może być garstka.

Produkt1.cs

public partial class Product
{
    //you are writing the business logic for fast moving product
}

Produkt2.cs

public partial class Product
{
    // Another developer writing some business logic...
}

Mam nadzieję, że to ma sens!


13

Klasy częściowe obejmują wiele plików.

Jak można użyć częściowego modyfikatora deklaracji klasy C #?

Dzięki klasom częściowym możesz fizycznie podzielić klasę na wiele plików. Jest to często wykonywane przez generatory kodu.

Przykład

W przypadku normalnych klas C # nie można zadeklarować klasy w dwóch osobnych plikach w tym samym projekcie. Ale z partialmodyfikatorem możesz.

Jest to przydatne, jeśli jeden plik jest często edytowany, a drugi jest generowany komputerowo lub rzadko edytowany.

Oto przykład, aby wyjaśnić:

class Program
{
    static void Main()
    {
        A.A1();
        A.A2();
    }
}

Zawartość pliku A1.cs: C #

using System;

partial class A
{
    public static void A1()
    {
        Console.WriteLine("A1");
    }
}

Zawartość pliku A2.cs: C #

using System;

partial class A
{
    public static void A2()
    {
        Console.WriteLine("A2");
    }
}

Wynik:

A1
A2

Częściowe jest tutaj wymagane.

Jeśli usuniesz partialmodyfikator, pojawi się błąd zawierający ten tekst:

[Przestrzeń nazw ” <global namespace>zawiera już definicję A„].

Wskazówka:

Aby to naprawić, możesz użyć partialsłowa kluczowego lub zmienić jedną z nazw klas.

Jak kompilator C # radzi sobie z klasami częściowymi?

Jeśli zdemontujesz powyższy program (używając IL Disassembler), zobaczysz, że pliki A1.cs i A2.cs zostaną wyeliminowane. Przekonasz się, że klasa A jest obecna.

Klasa A będzie zawierać metody A1 i A2 w tym samym bloku kodu. Dwie klasy zostały połączone w jedną.

Skompilowany wynik A1.cs i A2.cs: C #

internal class A
{
    // Methods
    public static void A1()
    {
        Console.WriteLine("A1");
    }

    public static void A2()
    {
        Console.WriteLine("A2");
    }
}

Podsumowanie

  • Klasy częściowe mogą uprościć niektóre sytuacje programowania w języku C #.
  • Są często używane w programie Visual Studio podczas tworzenia programów Windows Forms / WPF.
  • Wygenerowany maszynowo kod C # jest osobny.
  • Lub Możesz znaleźć cały opis tutaj .

2
Dobry przykład i dobrze udokumentowany.
Chef_Code

1
To najprostsze wytłumaczenie naśladować imo.
Yusha,

12

utrzymuj wszystko tak czyste, jak to możliwe, podczas pracy z dużymi klasami lub podczas pracy w zespole, możesz edytować bez zastępowania (lub zawsze zatwierdzania zmian)


11

Głównym zastosowaniem klas częściowych jest wygenerowany kod. Jeśli spojrzysz na sieć WPF (Windows Presentation Foundation), zdefiniujesz interfejs użytkownika za pomocą znaczników (XML). Ten znacznik jest skompilowany na częściowe klasy. Wypełniacie kod własnymi częściowymi klasami.


8

Jeśli masz wystarczająco dużą klasę, która nie nadaje się do skutecznego refaktoryzacji, podzielenie jej na wiele plików pomaga utrzymać porządek.

Na przykład, jeśli masz bazę danych witryny zawierającą forum dyskusyjne i system produktów, a nie chcesz tworzyć dwóch różnych klas dostawców (NIE to samo co klasa proxy, żeby być czystym), możesz: utwórz pojedynczą klasę częściową w różnych plikach, takich jak

MyProvider.cs - podstawowa logika

MyProvider.Forum.cs - metody odnoszące się konkretnie do forum

MyProvider.Product.cs - metody dla produktów

To tylko kolejny sposób na uporządkowanie.

Ponadto, jak powiedzieli inni, jest to jedyny sposób na dodanie metod do wygenerowanej klasy bez ryzyka zniszczenia twoich dodatków przy następnym generowaniu klasy. Jest to przydatne w przypadku kodu generowanego na podstawie szablonu (T4), ORM itp.


2
Byłbym zwolennikiem częściowego jako kroku do refaktoryzacji (cały punkt mojej odpowiedzi), ale nie sugerowałbym ich jako rzeczywistego rozwiązania do pisania czystego kodu. Jeśli klasa częściowa jest wyraźnie oddzielona od innych problemów klasy, to dlaczego nie włożyć dodatkowego wysiłku, aby wypromować ją do samodzielnej klasy?
STW,

@STW: Może być tak, że wiele instancji obiektów jest tworzonych i używanych do różnych zadań. Rozdzielenie różnych zadań na różne klasy wymagałoby śledzenia, które instancje zostały użyte do jakich zadań - potencjalnie znacznie większe przedsięwzięcie niż zwykłe przenoszenie bloków kodu między modułami źródłowymi.
supercat

4
@ supercat - Rozumiem całkowicie, ale należy podjąć się tego rodzaju spaghetti . Mam mnóstwo blizn po wyczyszczeniu dokładnie tego rodzaju kodu i nigdy nie zalecałbym pozostawienia go za sobą. Tego rodzaju mesy gwarantują ciągłe tworzenie problemów, a długoterminowa wypłata jest ogromna w porównaniu do zwykłego ignorowania problemu. Taki kod nie „pachnie”, cuchnie jak śmietnik.
STW,

1
@ supercat - starałem się to zakwalifikować za pomocą „Jeśli częściowa jest czysto oddzielona od innych problemów ... to jest to niewielki wysiłek”. Przejście przez ból związany z rozplątywaniem zwykle zaoszczędzi dużo na długoterminowej konserwacji, jeśli nie Rogaine
STW

2
Nawiasem mówiąc, bawię się obecnie próbując zmodyfikować Roslyn, i jest napisane przy szerokim użyciu częściowych klas. Wiele i wiele głównych klas w Roslyn jest definiowanych jako klasy częściowe w wielu plikach. Roslyn został napisany przez ludzi, których przynajmniej uważam za bardzo sprytnych programistów C #.
RenniePet

8

Jako alternatywa dla dyrektyw prekompilatora.

Jeśli użyjesz dyrektyw prekompilatora (mianowicie #IF DEBUG), to skończysz z jakimś srogo wyglądającym kodem zmieszanym z twoim faktycznym kodem Release.

Możesz utworzyć oddzielną klasę częściową, aby zawierała ten kod i albo zawinąć całą klasę częściową w dyrektywę, albo pominąć przesłanie tego pliku kodu do kompilatora (robiąc to samo).


Monogame używa tej strategii.
Zamboni

6

Odwołania do usług to kolejny przykład, w którym klasy częściowe są przydatne do oddzielenia generowanego kodu od kodu utworzonego przez użytkownika.

Możesz „rozszerzyć” klasy usług bez konieczności ich zastępowania podczas aktualizacji odwołania do usługi.


6

Innym zastosowaniem, które widziałem, jest

Rozszerzenie dużej klasy abstrakcyjnej dotyczącej logiki dostępu do danych,

Mam różne pliki o nazwach Post.cs, Comment.cs, Pages.cs ...

in Post.cs 

public partial class XMLDAO :BigAbstractClass
{
// CRUD methods of post..
}


in Comment.cs 

public partial class XMLDAO :BigAbstractClass
{
// CRUD methods of comment..
}

in Pages.cs 

public partial class XMLDAO :BigAbstractClass
{
// CRUD methods of Pages..
}

6

Większość ludzi zauważa, że partialnależy tego używać tylko w przypadku klasy, która ma wygenerowany plik kodu lub interfejsów. Nie zgadzam się, a oto dlaczego.

Na przykład spójrzmy na klasę C # System.Math ... to klasa . Nie próbowałbym wpychać ponad 70 metod do tego samego pojedynczego pliku kodu. Utrzymanie tego byłoby koszmarem.

Umieszczenie każdej metody matematycznej w oddzielnych plikach klas częściowych i wszystkich plików kodu w folderze Math w projekcie byłoby znacznie czystszą organizacją.

To samo mogłoby / dotyczyłoby wielu innych klas, które mają dużą różnorodność funkcji. Na przykład klasa do zarządzania API PrivateProfile mogłaby skorzystać z podziału na czysty zestaw plików klas częściowych w jednym folderze projektu.

Osobiście podzieliłem również to, co większość ludzi nazywa klasami „pomocników” lub „narzędzi użytkowych” na pojedyncze pliki częściowe dla każdej metody lub grupy funkcjonalnej metody. Na przykład w jednym projekcie klasa pomocnicza łańcucha ma prawie 50 metod. Byłby to długi, nieporęczny plik kodu, nawet przy użyciu regionów. Znacznie łatwiej jest utrzymać używanie poszczególnych plików klas częściowych dla każdej metody.

Byłbym ostrożny przy stosowaniu klas częściowych i utrzymywałby przy tym cały układ pliku kodu w całym projekcie. Takie jak umieszczanie dowolnych publicznych wyliczeń i prywatnych członków klasy w pliku Common.cs lub pliku o podobnej nazwie w folderze, zamiast rozkładania ich na pliki, chyba że są one specyficzne tylko dla pliku częściowego, w którym się znajdują.

Pamiętaj, że dzieląc klasę na osobne pliki, tracisz także możliwość korzystania z paska podziału edytora tekstów, który umożliwia jednoczesne wyświetlanie dwóch różnych sekcji bieżącego pliku.


4

Klasy częściowe umożliwiają dodanie funkcjonalności do odpowiednio zaprojektowanego programu poprzez dodanie plików źródłowych. Na przykład można zaprojektować program do importowania plików, aby można było dodawać różne typy znanych plików, dodając moduły, które je obsługują. Na przykład główny konwerter typów plików może zawierać małą klasę:

Częściowa klasa publiczna zzFileConverterRegistrar
    Rejestr zdarzeń (ByVal mainConverter jako zzFileConverter)
    Sub registerAll (ByVal mainConverter as zzFileConverter)
        RaiseEvent Register (mainConverter)
    Napis końcowy
Klasa końcowa

Każdy moduł, który chce zarejestrować jeden lub więcej typów konwertera plików, może zawierać coś takiego:

Częściowa klasa publiczna zzFileConverterRegistrar
    Private Sub RegisterGif (ByVal mainConverter as zzFileConverter) Obsługuje rejestrację
        mainConverter.RegisterConverter („GIF”, GifConverter.NewFactory))
    Napis końcowy
Klasa końcowa

Zauważ, że główna klasa konwertera plików nie jest „odsłonięta” - po prostu odsłania małą klasę kodu pośredniczącego, do której moduły dodatkowe mogą się zaczepić. Istnieje niewielkie ryzyko konfliktu nazw, ale jeśli procedura „rejestru” każdego modułu dodatkowego zostanie nazwana zgodnie z typem pliku, z którym ma do czynienia, prawdopodobnie nie powinien stanowić problemu. Można by umieścić identyfikator GUID w nazwie podprogramu rejestracyjnego, jeśli martwiłby się takimi rzeczami.

Edytuj / uzupełnienie Żeby było jasne, celem tego jest zapewnienie środków, dzięki którym różne osobne klasy mogą powiadomić o nich główny program lub klasę. Jedyną rzeczą, jaką główny konwerter plików zrobi z zFileConverterRegistrar, jest utworzenie jednej jego instancji i wywołanie metody registerAll, która wywoła zdarzenie Register. Każdy moduł, który chce przechwycić to zdarzenie, może wykonać dowolny kod w odpowiedzi (to cały pomysł), ale nie ma nic, co mógłby zrobić moduł, niewłaściwie rozszerzając klasę zzFileConverterRegistrar poza zdefiniowaniem metody, której nazwa odpowiada nazwie innego . Z pewnością byłoby możliwe, aby jedno niepoprawnie napisane rozszerzenie złamało inne niepoprawnie napisane rozszerzenie, ale rozwiązaniem tego jest dla każdego, kto nie chce, aby jego rozszerzenie zostało po prostu napisane poprawnie.

Można bez użycia klas częściowych mieć gdzieś wewnątrz głównej klasy konwertera plików trochę kodu, który wyglądałby tak:

  RegisterConverter („GIF”, GifConvertor.NewFactory)
  RegisterConverter („BMP”, BmpConvertor.NewFactory)
  RegisterConverter („JPEG”, JpegConvertor.NewFactory)

ale dodanie innego modułu konwertera wymagałoby przejścia do tej części kodu konwertera i dodania nowego konwertera do listy. Przy użyciu metod częściowych, które nie są już konieczne - wszystkie konwertery zostaną uwzględnione automatycznie.


to działa, ale to prosty plugin-system dynamicznie załadować te moduły byłyby znacznie ładniejszy i pomogłoby wyeliminować ryzyko modułów zgorszenie siebie (to może załadować moduły w czasie wykonywania, a nie wymagając ponownej kompilacji)
STW

Ryzyko wzajemnego uszkodzenia modułów można całkiem dobrze zminimalizować, jeśli nie zrobią one nic z klasą zz_, z wyjątkiem przechwytywania zdarzenia Register i wywoływania procedury, aby się zarejestrować. Jakie widzisz zagrożenia, których nie byłoby w przypadku wtyczki? Wtyczki są świetne, jeśli oczekuje się, że użytkownik końcowy „włączy” nowe moduły. Czasami jednak chce się umieścić całą funkcjonalność w jednym pliku exe. Przydaje się możliwość podłączenia plików źródłowych bez konieczności ręcznego dodawania odwołania do nowo dodanych plików.
supercat

1
ryzyko jest dość dobrze ograniczone w twojej linii „... jeśli nie zrobią nic [...] oprócz ...”, bezpieczeństwo i stabilność spoczywają całkowicie na deweloperze zgodnie z konwencją i zapewniają 0% gwarancji. Jeśli twoim przypadkiem użycia jest ich kompilacja (całkowicie poprawna, wystarczy kompromis sumienia), to dlaczego nie zdefiniować modułów w osobnych klasach i zaimplementować jakiś IModuleinterfejs?
STW,

To brzmi jak przypadek „sprytnego” zepsucia. To nie są „moduły”, są pojedynczą klasą z wieloma zachowaniami i obowiązkami połączonymi w jedną w czasie kompilacji. Jest o wiele lepszych sposobów na zrobienie tego - możesz użyć Reflection, aby przeskanować skompilowany zestaw w poszukiwaniu klas, które się implementują IModule, możesz użyć frameworka takiego jak MEF (tylko jeden z wielu) itp.
STW

3

Klasy częściowe pomogły ostatnio w kontroli źródła, w której wielu programistów dodawało do jednego pliku, w którym nowe metody były dodawane do tej samej części pliku (zautomatyzowane przez Resharper).

Te naciski na git spowodowały konflikty scalania. Nie znalazłem sposobu, aby powiedzieć narzędziu do scalania, aby przyjęło nowe metody jako kompletny blok kodu.

Częściowe klasy pod tym względem pozwalają programistom trzymać się wersji swojego pliku, a my możemy je później scalić ręcznie.

przykład -

  • MainClass.cs - przechowuje pola, konstruktor itp
  • MainClass1.cs - nowy kod programistów podczas ich implementacji
  • MainClass2.cs - to kolejna klasa programistów dla ich nowego kodu.

3

Z MSDN :

1. W czasie kompilacji atrybuty definicji typu częściowego są scalane. Weźmy na przykład następujące deklaracje:

[SerializableAttribute]
partial class Moon { }

[ObsoleteAttribute]
partial class Moon { }

Odpowiadają one następującym deklaracjom:

[SerializableAttribute]
[ObsoleteAttribute]
class Moon { }

Poniższe elementy zostały scalone ze wszystkich definicji typu częściowego:

  • Komentarze XML

  • interfejsy

  • atrybuty parametrów typu ogólnego

  • atrybuty klasy

  • członkowie

2. Inną rzeczą, zagnieżdżone klasy częściowe mogą być również częściowe:

partial class ClassWithNestedClass
{
    partial class NestedClass { }
}

partial class ClassWithNestedClass
{
    partial class NestedClass { }
}

1

Oto lista niektórych zalet klas częściowych.

Możesz oddzielić kod projektu interfejsu użytkownika od kodu logiki biznesowej, aby był łatwy do odczytania i zrozumienia. Na przykład tworzysz aplikację internetową za pomocą programu Visual Studio i dodajesz nowy formularz internetowy, a następnie są dwa pliki źródłowe: „aspx.cs” i „aspx.designer.cs”. Te dwa pliki mają tę samą klasę ze słowem kluczowym częściowym. Klasa „.aspx.cs” ma kod logiki biznesowej, natomiast „aspx.designer.cs” ma definicję kontroli interfejsu użytkownika.

Podczas pracy z automatycznie generowanym źródłem kod można dodać do klasy bez konieczności ponownego tworzenia pliku źródłowego. Na przykład pracujesz z LINQ to SQL i tworzysz plik DBML. Teraz, kiedy przeciągasz i upuszczasz tabelę, tworzy ona klasę częściową w designer.cs, a wszystkie kolumny tabeli mają właściwości w klasie. Potrzebujesz więcej kolumn w tej tabeli, aby powiązać się z siatką interfejsu użytkownika, ale nie chcesz dodawać nowej kolumny do tabeli bazy danych, abyś mógł utworzyć osobny plik źródłowy dla tej klasy, który ma nową właściwość dla tej kolumny i będzie być klasą częściową. Wpływa to na mapowanie między tabelą bazy danych a jednostką DBML, ale można łatwo uzyskać dodatkowe pole. Oznacza to, że możesz napisać kod samodzielnie, bez bałagania się kodu generowanego przez system.

Więcej niż jeden programista może jednocześnie napisać kod dla klasy.

Możesz lepiej utrzymać swoją aplikację, kompaktując duże klasy. Załóżmy, że masz klasę z wieloma interfejsami, dzięki czemu możesz tworzyć wiele plików źródłowych w zależności od implementacji interfejsu. Łatwo jest zrozumieć i utrzymać interfejs zaimplementowany, w którym plik źródłowy ma klasę częściową.


1

Ilekroć mam klasę, która zawiera zagnieżdżoną klasę o dowolnym znaczącym rozmiarze / złożoności, zaznaczam klasę jako partiali umieszczam zagnieżdżoną klasę w osobnym pliku. Nazwa pliku zawierającego klasę zagnieżdżoną nazywam zgodnie z regułą: [nazwa klasy]. [Nazwa klasy zagnieżdżonej] .cs.

Poniższy blog MSDN wyjaśnia, jak używać klas częściowych z klasami zagnieżdżonymi w celu utrzymania: http://blogs.msdn.com/b/marcelolr/archive/2009/04/13/using-partial-classes-with-nested-classes-for- Maintenanceability.aspx


1

Wiem, że to pytanie jest naprawdę stare, ale chciałbym dodać moje zdanie na temat częściowych zajęć.

Jednym z powodów, dla których osobiście używam klas częściowych, jest tworzenie powiązań dla programu, zwłaszcza maszyn stanu.

Na przykład OpenGL jest maszyną stanu, istnieje mnóstwo metod, które można zmienić globalnie, jednak z mojego doświadczenia wiąże coś podobnego do OpenGL, gdzie jest tak wiele metod, klasa może łatwo przekroczyć 10 000 LOC.

Zajęcia częściowe rozłożą to na mnie i pomogą mi szybko znaleźć metody.


0

Klasy częściowe zostały wprowadzone przede wszystkim w celu pomocy generatorom kodów, więc my (użytkownicy) nie tracimy całej naszej pracy / zmian w generowanych klasach, takich jak klasa .designer.cs ASP.NET przy każdej regeneracji, prawie wszystkie nowe narzędzia, które generują kod LINQ, EntityFrameworks, ASP.NET używają klas częściowych do generowania kodu, dzięki czemu możemy bezpiecznie dodawać lub zmieniać logikę tych wygenerowanych kodów, korzystając z klas i metod Partial, ale zachowaj ostrożność, zanim dodasz elementy do generowanego kodu za pomocą klas Partial łatwiej jest, jeśli zepsujemy kompilację, a najgorsze, jeśli wprowadzimy błędy czasu wykonywania. Aby uzyskać więcej informacji, sprawdź ten http://www.4guysfromrolla.com/articles/071509-1.aspx


0

Zwracam uwagę na dwa zastosowania, których nie znalazłem wyraźnie w odpowiedziach.

Grupowanie przedmiotów klasy

Niektórzy programiści używają komentarzy do oddzielania różnych „części” swojej klasy. Na przykład zespół może zastosować następującą konwencję:

public class MyClass{  
  //Member variables
  //Constructors
  //Properties
  //Methods
}

Dzięki klasom częściowym możemy pójść o krok dalej i podzielić sekcje na osobne pliki. Zgodnie z konwencją zespół może sufikować każdy plik odpowiednią sekcją. W powyższym przypadku mielibyśmy coś takiego: MyClassMembers.cs, MyClassConstructors.cs, MyClassProperties.cs, MyClassMethods.cs.

Jak wspomniano w innych odpowiedziach, to, czy warto podzielić klasę, prawdopodobnie zależy od tego, jak duża jest klasa w tym przypadku. Jeśli jest mały, prawdopodobnie łatwiej jest mieć wszystko w jednej klasie mistrzowskiej. Ale jeśli którakolwiek z tych sekcji stanie się zbyt duża, jej zawartość można przenieść do oddzielnej klasy częściowej, aby utrzymać klasę master w porządku. Konwencją w takim przypadku może być pozostawienie komentarza po powiedzeniu „Patrz częściowa klasa” po nagłówku sekcji, np .:

//Methods - See partial class

Zarządzanie zakresem używania instrukcji / przestrzeni nazw

Jest to prawdopodobnie rzadkie zjawisko, ale może wystąpić kolizja przestrzeni nazw między dwiema funkcjami bibliotek, których chcesz użyć. W jednej klasie możesz co najwyżej użyć klauzuli using dla jednej z nich. Po drugie potrzebujesz w pełni kwalifikowanej nazwy lub aliasu. W przypadku klas częściowych, ponieważ każda lista przestrzeni nazw i instrukcji jest inna, można podzielić dwa zestawy funkcji na dwa osobne pliki.


Istnieją mechanizmy rozwiązywania kolizji przestrzeni nazw, na przykład zmiana nazwy przestrzeni nazw za pomocą using Library1 = The.Namespace.You.Needlubglobal::Root.Of.Namespace
fjch1997

Tak, przypuszczam, że to słaby przypadek użycia. Ale trochę fajniej jest nie musieć w pełni kwalifikować nazw. Bardziej miły niezamierzony efekt uboczny niż powód używania klas częściowych.
Colm Bhandal,
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.