it-swarm-eu.dev

Proč používat dílčí třídy?

Podle mého pochopení klíčové slovo partial nedělá nic jiného, ​​než umožňuje rozdělení třídy mezi několik zdrojových souborů. Existuje nějaký důvod to udělat jinak než pro organizaci kódu? Viděl jsem to pro to použito v generovaných třídách uživatelského rozhraní.

Zdá se, že je špatný důvod vytvořit celé klíčové slovo. Pokud je třída dostatečně velká na to, aby vyžadovala více souborů, pravděpodobně to dělá příliš mnoho. Myslel jsem, že byste to mohli použít k částečnému definování třídy pro dokončení někým jiným programátorem, ale bylo by lepší vytvořit abstraktní třídu.

72
Michael K

Je to velmi užitečné v každém scénáři, kde je jedna část třídy generována nějakým vlastním nástrojem, protože umožňuje přidat vlastní logiku do vygenerovaného kódu bez zdědění generované třídy. Mimochodem. ze stejného důvodu existují také částečné metody.

Nejde jen o uživatelské rozhraní, ale také o jiné technologie, jako je Linq-To-Sql nebo Entity Framework.

113
Ladislav Mrnka

Jak říkáte, často se používá k oddělení vygenerovaného kódu. S velikostí tříd/souborů často nemá nic společného.

Výhodou oddělení vygenerovaného kódu je styl. Generovaný kód může být docela ošklivý a nečitelný a selhal by v mnoha kódovacích standardech (a kontrolách StyleCop), ale to je v pořádku, nikdo jej nemusí číst ani udržovat přímo. Pokud je tedy „skryjete“ v jiném souboru, můžete se zaměřit na to, zda je zbytek třídy až standardní, projde kontrolou StyleCop a tak dále.

Další oblastí, kde jsem ji použil, je to, kde třída implementuje více rozhraní, může být docela pěkné oddělit implementaci do samostatných souborů, ačkoli je to spíš záležitost osobních preferencí, nikdy jsem neviděl žádné kódovací standardy, které vyžadují ( nebo tomu zabránit.

26
Steve

Jeden z vývojářů, kde pracuji, se před pár týdny pro ně docela dobře využil při refaktoringu obrovských tříd Boha, které se vymkly kontrole a mají spoustu veřejných metod: oddělením logických funkcí každého kousku třída do samostatných dílčích tříd můžete fyzicky rozdělit třídu do více atomových jednotek, které by měly být třídami, aniž by došlo k přerušení jakékoli existující funkčnosti, což vám umožní vidět, co je běžné a co není. S touto první fází pak můžete snadněji rozdělit dílčí části na jejich vlastní nezávislé třídy a implementovat je v celé kódové základně. Myslel jsem, že to byl pěkný nápad.

Obecně se však domnívám, že by se měly používat pouze k rozšíření strojem generovaných tříd při psaní nového kódu.

19
user23157

Dokážu vymyslet několik užitečných scénářů, ve kterých mají částice smysl, většina z nich používám ve svých projektech:

  • Oddělit kód vygenerovaný nástrojem/IDE/návrhářem od kódu, který udržujete. Dobrým příkladem je Form.Designer.cs soubor, který obsahuje návrhářem generovaný kód pro aplikace Windows formulářů. Mnoho dalších formátů .NET má také nějaký kód generovaný nástroji, který může být při sestavování projektu potenciálně regenerován, takže všechny vaše vlastní změny budou odstraněny. Oddělení vám pomůže chránit váš kód a změny před automatizovanými úpravami.

  • Když implementujete více rozhraní se spoustou kódu v implementaci. Mám sklon používat samostatný dílčí soubor pro každé takové rozhraní a pojmenovat ho takto: {Class}.{Interface}.cs. Je pro mě snadné vidět v IDE, které propojuje {Class} implementuje a jak.

  • Když třída musí obsahovat jednu nebo více vnořených tříd , zejména s dostatkem kódu v nich, který lze vložit do samostatného souboru. Držel jsem se výše uvedeného vzoru a použil {Class}.{NestedClass}.cs konvence pojmenování pro každou vnořenou třídu. Podobnou praxi již zmiňuje Virtlinkova odpověď .

  • Když píšu static třídy, které budou obsahovat metody rozšíření . Často se stane, že poskytneme stejnou logiku metody rozšíření podobným třídám nebo rozhraním - jako například Reverse v obecných a ne-obecných sbírkách. Všechny metody rozšíření pro jednu třídu nebo rozhraní bych dal do samostatné části statické třídy. Například bych měl všechny metody rozšíření pro rozhraní IList na jednom místě a stejné metody jako pro IList<T> v jiném souboru. Dalším přístupem by bylo umístit stejnou metodu (všechna její přetížení) do stejné části, se všemi možnými třídami parametru this - jako kdyby všechny _ implementace Reverse byly v jednom souboru. Záleží na tom, který z nich by lépe odůvodnil oddělení z hlediska objemu kódu nebo některých interních konvencí, na kterých se vy nebo vaše organizace mohou držet.

  • Nepoužívám to, ale viděl jsem některé lidi z C/C++, kteří mají rádi přístup popsaný zde: vytvořte částečné pro třídu pouze s částečnými metodami . To se podobá způsobu definování rozhraní C/C++ a oddělení deklarace metody od implementace.

  • Oddělení čistě logickými obavami . Pokud náhodou pracujete s velkou třídou, která kombinuje více než jednu logickou sadu operací sama o sobě, můžete každý logicky související kód rozdělit na samostatnou část. Obvykle existence takových tříd je v rozporu se zásadou oddělení obav, ale často se jedná o skutečný případ, zejména u starších kodebáz. Společný uživatel Steve Evers je zmínil v jeho odpověď na tuto otázk , odkazoval se na ně jménem god objects . Osobně bych použil přístup dílčích tříd, abych rozdělil kód dříve, než dojde k jakémukoli refactoringu takových opravdu velkých souborů, abych usnadnil svou práci a zpřehlednil refactorování. Tím se také sníží konflikty, které potenciálně způsobím, když se budou týkat systémy verzování, jako je SVN.

19
Ivaylo Slavov

Neviděl jsem to nikoho zmínil: Používám partial k vložení vnořených tříd do svých vlastních souborů.

Všechny mé kódové soubory obsahují pouze jednu třídu, strukturu, rozhraní nebo výčet. Je mnohem snazší najít definici objektu, když názvy souborů ukazují název hledané věci. A protože se Visual Studio pokouší přiřadit složky projektu k jmenným prostorům, názvy souborů by se měly shodovat s třídami.

To také znamená, že třída NestedClass vnořená uvnitř MyClass bude mít svůj vlastní soubor v mých projektech: MyClass.NestedClass.cs.

partial class MyClass
{
    private class NestedClass
    {
        // ...
    }
}

Až na to, že jsem vygenerovaný kód použil, viděl jsem pouze , jaké byly použity ve snaze zakrýt božské objekty . Snažit se pochopit novou kódovou základnu nebo procházet několika zdrojovými soubory, které jsou stejným objektem, je nepříjemné.

Takže když se zeptáte Why use partial classes? Odpovídám: pokud nepoužíváte vygenerovaný kód, ne.

10
Steven Evers

Organizace kódu je jediným důvodem, ale jde hlouběji, než se na první pohled zdá. Pokud máte dílčí třídy, ve kterých jsou generovány součásti, můžete snadno:

  • Znovu vygenerujte kód, aniž byste museli detekovat ruční změny ve třídách, do kterých píšete (abyste tyto části nepřepsali).
  • Vyloučit vygenerované dílčí třídy z pokrytí testu, řízení zdroje, metriky atd.
  • Použijte vygenerovaný kód, aniž byste vás nutili založit svou dědičnou strategii kolem ní (stále můžete dědit z jiných tříd).
6
Deckard

Dokážu pro ně použít špinavé použití.

Předpokládejme, že máte nějaké třídy, které potřebují běžnou funkčnost, ale nechcete ji vkládat do řetězce dědičnosti nad nimi. Nebo máte sadu tříd, které používají běžnou pomocnou třídu.

V podstatě chcete udělat vícenásobné dědictví, ale C # žádná podobná. Takže to, co děláte, je použití částečného k vytvoření toho, co je v podstatě #include v C/C++;

Vložte všechny funkce do třídy nebo použijte pomocnou třídu. Poté zkopírujte pomocníka Xkrát a přejmenujte jej na částečnou třídu A, B, C. a částečně vložte do svých tříd A, B, C.

Zřeknutí se odpovědnosti: Ano, to je zlé. Nikdy to nedělejte - zvláště pokud to na vás udělá další šílení.

1
Mark

Existuje také několik míst, kde jsou generované/implikované třídy deklarovány jako částečné, takže pokud je Dev potřebuje rozšířit, mají plný přístup, aniž by se museli zkazit zděděním a potlačením všude. Podívejte se na vygenerované třídy v oblasti temp.net asp.net po prvním spuštění webového formuláře pod IIS, pokud se chcete pokusit zachytit několik příkladů).

1
Bill