1. Cseréld le az elérhető mezőket attribútumokra
1、. A .NET adatkötés csak az adatkötést támogatja, és az adatkötés előnyeit attribútumok használatával is elérheted. 2. A hozzáférés és beállítás funkciójában a lock segítségével többszálas támogatást adhatsz hozzá.
2. olvasható (futási idejű állandó) és const (fordítási idejű állandó)
1. Const csak primitív típusokhoz, enumokhoz és stringekhez használható, míg a readonly bármilyen típus lehet; 2. A CONST a fordításkor egy adott állandóval kerül lecserélve, így ha a hivatkozásban mind a const, mind csak olvasható értéket használják, akkor a csak olvasható értékre való váltás megváltoztatja a tervezés eredeti célját, vagyis a módosított assembly újrafordítását, hogy az új állandó értéket újra kell fordítani. 3. A CONST hatékonyabb, mint csak olvasható, de elveszíti az alkalmazás rugalmasságát.
3. IS és AS
1. Mindkettő típusátalakítás futásidőben, mivel az operátorok csak referenciatípusokban használhatók, míg az értékeket és referenciatípusokat használhatja; 2. A szokásos gyakorlat az, hogy az IS típust használjuk a típus meghatározására, majd szelektíven választják az IS (az operátor által meghatározott átalakítást) vagy egy erős típusátalakító operátort (az operátor által meghatározott átalakítást).
4. ConditionalAttribute helyett #if #endif条件编译
1. A ConditionalAttribute csak a metódus szintjén használatos, és más elemek, mint a típusok, attribútumok stb. érvénytelenek. És #if #endif则不受此限制; 2. A ConditionalAttribute több OR (OR) műveletet is hozzáadhat fordítási feltételekhez, és a #if #endif则可以添加与(AND) [itt teljesen definiálható egy másik különálló szimbólumként]; 3. A ConditioanlAttribute definíció külön módszerben helyezhető, hogy a program rugalmasabb legyen.
5. Adja meg a ToString() módszert
1. Barátságosabb módon nyújthat részletes információkat a felhasználóknak; 2. Használd az IFormatter.ToString() módszert rugalmasabb testreszabáshoz, és ha hozzáadod az IFormatProvider és ICustomFormatter interfészeket, akkor sokkal értelmesebb lesz az üzenetkimenet testreszabása.
6. Az érték és a referenciatípus közötti különbség
1. Az értéktípusok nem támogatják a polimorfizmust, amely alkalmas alkalmazások által működtetett adatok tárolására, míg a hivatkozások polimorfizmust támogatnak, amely alkalmas az alkalmazás viselkedésének meghatározására. 2. Értéktípusként definiált tömbök esetén a program teljesítménye jelentősen javítható; 3. Az értéktípus kevesebb halommemória fragmentációja, memóriahulladék és közvetett hozzáférési idő van, és a módszerben visszaküldése replikáció formájában történik, hogy elkerüljék a belső struktúra kitárását a külvilág számára. 4. Az értéktípusokat az alábbi esetekben használják: A típusok felelőssége elsősorban adattárolásra szolgál; A nyilvános interfészeket teljesen bizonyos adattagi hozzáférési attribútumok határozzák meg; Soha nincsenek alosztályok; Soha nincs polimorf viselkedés.
7. Az értéktípusokat a lehető legállandóbb és atomos típusokkal kell megvalósítani.
1. Megkönnyítsé a kód írását és karbantartását; 2. Három stratégia a konstanssok inicializálására: a konstrukcióban; növénymódszer; Építs egy módosítható segítő osztályt (pl. StringBuilder).
8. Győződj meg róla, hogy a 0 érvényes státuszt érdemel
1. Az értéktípus alapértelmezett állapota 0; 2. Az enum típus 0-ja nem lehet érvénytelen; A FlagsAttribute esetében az a feladat, hogy biztosítsa, hogy a 0 érték érvényes állapotú legyen; 3. Amikor a húr üres, vissza lehet adni egy szálat. Üres zsinór az üresért.
9. Egyenlő ítélőképességű többféle reprezentációs viszonyok
1. ReferenceEquals() határozza meg, hogy a hivatkozások egyenlőek, és igaznak kell lennie, ha mindkettő ugyanarra az objektumra utal. 2. A statikus Equals() módszert használják először referencia ítélethozatalra, majd az értéktípus megítélésére; 3. A referenciatípus megítéléséhez használhatod az Equals() újraírás módszert értékszemantika esetén. 4. Az Equals() metódus újraírása során a GetHashCode() metódust is újra kell írni, és az operater==() műveletet egyszerre kell megadni.
10. Értsd meg a GetHashCode() módszer hiányosságait
1. A GetHashCode() csak hash-alapú ** definiált kulcsok, például HashTable vagy Dictionary hash értékekre alkalmazható; 2. A GetHashCode()-nak a megfelelő három szabályt kell követnie: két egyenlő objektumnak ugyanazt a hash kódot kell visszaadnia; példányinvariánsnak kell lennie; A hash függvénynek véletlenszerű eloszlást kell előállítania minden egész számon.
11. Elsőbbséget adjunk a foreach ciklus állítások használatának
1. foreach megszüntetheti a fordító által az for hurok tömbhatárának ellenőrzését; 2. A foreach kör alakú változója csak olvasható, és van egy explicit transzformáció, amely kivételt eredményez, ha a ** objektum objektumtípusa hibás; 3. A **, amely minden számára szükséges: legyen nyilvános GetEnumberator() módszer; Az IEnumerálható interfész kifejezetten meg van valósítva. IEnumerator interfész megvalósítható; 4. Foreach élvezheti az erőforrás-menedzsment előnyeit, mert ha a fordító meg tudja határozni az IDisposable felületet, akkor használhatja az optimalizált try... végül blokkolni;
12. Az alapértelmezett mező inicializálása jobb, mint az assign állítás
1. A pálya élettartama alapértelmezés szerint 0-ra, a referencia típust pedig nullra inicializálja. 2. Ugyanaz az objektum többszöri inicializálása csökkenti a kód végrehajtási hatékonyságát. 3. A mező inicializációjának a konstruktorba helyezése elősegíti a kivételkezelést.
13. Használd a statikus konstruktort a statikus tagok inicializálására
1. A statikus konstruktor végrehajtásra kerül, mielőtt bármely osztály metódusát, változóját vagy attribútumját elérnénk; 2. A statikus mezők a statikus konstruktor előtt is futnak, és a statikus konstruktor elősegíti a kivételkezelést.
14. Használd a konstruktor láncot (in. A NET 4.0 már megoldja ezt a problémát opcionális paraméterekkel)
1. Használd ezt, hogy átadd az inicializációs munkát egy másik konstruktornak, és az alap segítségével hívd meg az alaposztály konstruktorát; 2. A típuspéldányok műveleti sorrendje: állítsuk be az összes statikus mezőt 0-ra; Statikus mező inicializálók végrehajtása; egy statikus konstruktor, amely végrehajtja az alap osztályt; Statikus konstruktorok, amelyek a jelenlegi típust hajtják végre; Állítsuk be az összes példánymezőt 0-ra; Végrehajtsa az instance field inicializátorokat; A megfelelő alap osztály instance constructort hajtsa végre; Hajtsd végre a jelenlegi típusú instance constructort.
15. Használj using és try/finally utasításokat az erőforrások tisztításához
Az IDisposable interfész Dispose() módszerében a GC.SuppressFinalize() segítségével értesítheti a szemétgyűjtőt, hogy a végső művelet már nem történik el.
16. Minimalizáld a memóriahulladékot
1. Több processzor időbe telik az objektumok elosztásához és megsemmisítéséhez egy halomban; 2. A hozzárendelt objektumok számának csökkentésére szolgáló technikák: gyakran használt helyi változókat mezőké emelnek; Egy osztályt biztosít, amely tárolja a Singleton objektumok gyakori példányait, amelyek specifikus típusokat fejeznek ki. 3. Használd a StringBuildert összetett string műveletek végrehajtásához.
17. Minimalizáld a csomagolást és kipakolást
1. Figyelj a típus implicit átalakítására System.Object-re, és az értéktípust nem szabad a System.Object típusra cserélni; 2. Felületek használata típusok helyett elkerülheti a boxolást, vagyis az értéktípusok interfészekből történő megvalósítását, majd a tagok interfészeken keresztül történő hívását.
18. A szabványos Megszüntetési mód bevezetése
1. Nem memória erőforrások használatához szükség van egy véglegesítőre, a szemétgyűjtő hozzáadja a megvalósított véglegesítő objektumokat a befejezési sorhoz, miután befejezte azokat a memóriaobjektumokat, amelyek nem fejezték be őket, majd a szemétgyűjtő új szálat indít a véglegesítők futtatásához ezeken az objektumokon. Ez elkerülheti a memóriaszivárgás problémáját, amelyet a kezeletlen memóriaforrások nem szabadulnak fel. 2. Az IDisposable.Dispose() módszer használata négy munkaterületet igényel: minden kezeletlen erőforrás felszabadítását; Szabadítsd fel az összes kezelt erőforrást; Állíts be egy státuszjelzőt, amely jelzi, hogy a Dispose() végrehajtás történt-e; Hívjuk a GC.SuppressFinalize(this) funkciót, hogy lemondjuk az objektum lezárási műveletét; 3. Adjunk egy védett virtuális módszert a Dispose() a polimorfizmust igénylő típushoz, és a származtatott osztály felszabadítja a feladatát azzal, hogy átírja ezt a metódust. 4. Olyan típusban, amely IDisopozable interfészt igényel, akkor is kell terminátort implementálni, még ha nincs is rá szükség.
19. Definiálni és valósítani az interfészeket az öröklési típusokon keresztül
1. Nem kapcsolódó típusok közösen valósíthatnak meg egy közös interfészt, és könnyebb egy interfészt megvalósítani, mint az öröklés; 2. Az interfész viszonylag stabil, egy interfészben található függvényhalmazt kapszulál más típusú implementációs szerződésekként, míg az alaposztály idővel bővíthető.
20. Különbségtétel az interfész megvalósítása és a virtuális módszer újraírása között
1. Amikor egy interfészt implementálnak az alap osztályban, a vezetett osztálynak új módszert kell használnia, hogy elrejtse az alap osztály metódusának használatát; 2. Az alaposztály interfész módszere virtuális metódusként deklarálható, majd a származtatott osztályban valósítható meg.
21. Használd a bizalmat visszahívások kifejezésére
1. A delegált maga nem biztosít kivétel rögzítést, így bármilyen multicast delegált hívás véget vet az egész hívásláncnak. 2. Az összes delegációs cél megjelenítésével és meghívásával elkerülheted, hogy a multicast küldöttek csak az utolsó delegált kimenetét adják vissza.
22. Használj eseményeket külső interfészek meghatározására
1. Ezt közös eseményként kell nyilvánítani, és hagyni, hogy a fordító létrehozza nekünk az add és renmove metóduszokat. 2. Használd a System.ComponentModel.EventHandlerList konténert az egyes eseménykezelők tárolására, és azzal elrejtsd az események összetettségét, ha a típus sok eseményt tartalmaz.
23. Kerüld a belső osztályobjektumokra való hivatkozások visszaküldését
1. Mivel egy értéktípus-objektum hozzáférése másolatot hoz létre az objektumból, az értéktípus meghatározásának attribútumai egyáltalán nem változtatják meg az állapotot a típus objektumon belül; 2. Állandó típusok elkerülhetik az objektum állapotának megváltoztatását; 3. Definiálja az interfészt, hogy korlátozza a hozzáférést egy részhalmazhoz, minimalizálva az objektum belső állapotának károsodását. 4. Definiáljon egy wrapper objektumot, amely korlátozza a hozzáférést egy másik objektumhoz; 5. Amikor az ügyfél kódja megváltoztatja a belső adatelemeket, megvalósítható az Observer mód, így az objektum ellenőrizheti vagy megfelelhet a változásoknak.
24. A deklaratív programozás jobb, mint imperatív programozás
Elkerülhető a hibák lehetősége több, hasonló kézzel írt algoritmusban, és világos, olvasható kódot biztosítunk.
25. A típusok minél serializálhatóbb megvalósítása
1. A típus nem UI vezérlőt, ablakot vagy űrlapot képvisel, és a típusnak támogatnia kell a serializációt; 2. Amikor hozzáadjuk a NonSerializedAttribute deserializált attribútumját, az alapértelmezett értéket az IDeserializationCallback implementáló OnDeserialization() metódus töltheti be; 3. Verzióvezérlésben az ISerializable interfészt használhatod rugalmas vezérléshez, és egy serializációs konstruktort biztosíthatsz objektumok inicializálására az adatfolyam adatai szerint, valamint a megvalósításhoz a SerializationFormatter kivételek engedélye szükséges. 4. Ha létre kell hozni egy származtatott osztályt, akkor a vezetett osztályhoz hook módszert kell megadnod.
26. Használd az IComparable és IComparer interfészeket a rendezési kapcsolatok megvalósításához
1. Az IComparable interfész a típusok legtermészetesebb rendezési viszonyának megvalósítására szolgál, négy összehasonlító operátort túlterhelve, és a CompareTo() módszer túlterhelt változatát biztosítja, amely bizonyos típusokat paraméterként fogad el. 2. Az IComparer olyan rendezési kapcsolatok biztosítására szolgál, amelyek eltérnek az IComparable-tól, vagy olyan rendezési kapcsolatok biztosítására, amelyeket maga a típus nem valósít meg.
27. Kerüld az ICloneable interfészeket
1. Értéktípusok esetén nincs szükség ICloneable interfész támogatására, csak az alapértelmezett hozzárendelési műveletet használjuk; 2. Az alaposztályok esetében, amelyeknek ICloneable interfészeket kell támogatniuk, védett replikációs konstruktort kell létrehozni hozzájuk, és az IConeable interfészeket kerülni kell.
28. Kerüld a kényszerített átalakítási operátorokat
Konstruktorok használata az átalakító operátorok helyett világosabbá teheti az átalakítást, ami könnyen furcsa hibákhoz vezethet az átmeneti objektumok miatt, amelyeket az átalakítás után használnak.
29. Csak akkor vegyük figyelembe az új módosító használatát, ha az új verziók felhalmozódása problémát okoz
30. A CLS-kompatibilis összeállítások minél többit implementálják 1. Kompatibilis assembly létrehozásához két szabályt kell követni: a nyilvános és védett assembly tagjai által használt paramétereknek és visszaküldési értéktípusoknak kompatibilisnek kell lenniük a CLS-szel; Minden nyilvános és védett tagnak, amely nem kompatibilis a CLS-szel, rendelkeznie kell CLS-kompatibilis alternatívával; 2. A CLS kompatibilitási típus-ellenőrzést kifejezett interfész megvalósításával megkerülheted, és a CLSCompliantAttribute nem fogja ellenőrizni a privát tagok CLS kompatibilitását.
31. A lehető legrövidebb és tömör módszer alkalmazása
1. A JIT fordító metódusegységekben fordít, és a nem hívott metódusok nem lesznek a JIT által fordítva; 2. Ha a hosszabb Switchben a Case utasítás kódját egyszerre egy metódusra cserélik, a JIT fordító által megtakarított idő megszorozódik; 3. Rövid és tömör módszerek, valamint kevesebb helyi változó kiválasztása optimalizált regiszterhasználatot eredményezhet; 4. Minél kevesebb vezérlőág a metódusban, annál könnyebb a JIT fordítónak változókat behelyezni a regiszterekbe.
32. A lehető legnagyobb méret és a magas kohéziós összeállítások megvalósítása
1. Helyezzük be az összes nyilvános és common base osztályt néhány összeállításba, helyezzük be a nyilvános osztályokat szolgáló eszközosztályokat ugyanabba az összeállításba, csomagoljuk a releváns nyilvános interfészeket saját összeállításaikba, és végül dolgozzuk fel azokat az osztályokat, amelyek az alkalmazásban a vízszintes pozícióban találhatók; 2. Elvileg kétféle komponenst kell létrehozni: az egyik egy kis és összesített összeállítás egy adott funkcióval, a másik pedig egy nagy és széles összeállítás közös funkciókkal.
33. A típusok láthatóságának korlátozása
1. Az interfészek használata a típusok funkcióinak feltárására megkönnyítheti a belső osztályok létrehozását anélkül, hogy korlátoznánk azok elérhetőségét a assembly külső részén; 2. Minél kevesebb nyilvános típus van kitéve a külvilágnak, annál több lehetőséged van a jövőbeli bővítésre és változtatásokra való bevezetésre.
34. Hozz létre egy nagyszabású webes API
Ez minimalizálja a gépek közötti tranzakciók gyakoriságát és terhelését, nagy műveleteket és finom végrehajtásokat helyezve a szerverre.
35. Az újraírás jobb, mint az eseményfeldolgozók
1. Ha egy eseményfeldolgozó kivételt dob, az eseménylánc többi processzorát nem hívják meg, de ez nem történik meg az átírt virtuális metódussal. 2. Az újraírás sokkal hatékonyabb, mint az asszociatív eseményfeldolgozók, amelyeknek az egész kéréslistán át kell iterálniuk, ami több CPU-időt vesz igénybe. 3. Az eseményekre futás közben reagálhatnak, nagyobb rugalmassággal, és több válasz is kapcsolódik ugyanahhoz az eseményhez. 4. A szokásos szabály, hogy egy származtatott eseményt kezelünk, és az újraírási módszer jobb.
36. Tisztességes felhasználás. .NET futási idejű diagnosztika
1. A System.Diagnostics.Debug\Trace\EventLog minden szükséges eszközt biztosít a program számára a futtatóidejű diagnosztikai információk hozzáadásához, és az alkalmazás írhat a rendszer eseménynaplójába, amikor az EventLog megadja az összetevőt; 2. Végül, ne írj saját diagnosztikai könyvtáradat, a .NET FCL-en már megvan a szükséges magkönyvtár.
37. Szabványos konfigurációs mechanizmusok alkalmazása
1、. A .NET keretrendszer System.Windows.Application osztálya határozza meg azokat a tulajdonságokat, amelyek közös konfigurációs útvonalat hozhatnak létre; 2. Az Application.LocalAppDataPath és az Application.userDataPath generálja a helyi adatkönyvtár és a felhasználói adatok útvonalneveit; 3. Ne írjon adatokat ProgramFiles és Windows rendszerkönyvtárakba, ezek a helyek magasabb biztonsági jogosultságokat igényelnek, ne várják el a felhasználóknak írási engedélyeket.
38. Testreszabás és támogatás az adatkötés támogatása
1. A BindingMananger és a CurrencyManager két objektuma valósítja meg az adatátvitelt a vezérlő és az adatforrás között; 2. Az adatkötés előnyei: az adatkötés használata sokkal egyszerűbb, mint saját kód megírása; Más távcsövekre is használható, nem csak szöveges adatelemekre – más megjelenítési tulajdonságok is korlátozhatók; Windowos Forms adatkötéseknél a többszörös vezérlésű szinkronizáció lehetősége a ellenőrzéshez kapcsolódó adatforrások esetében; 3. Ha az objektum nem támogatja a szükséges attribútumokat, az adatkötést támogathatod azzal, hogy blokkolod a jelenlegi objektumot, majd hozzáadod a kívánt objektumot.
39. Használd. .NET validáció
1. A ASP.NET öt vezérlő van az érvényesség ellenőrzésére, és a CustomValidatorral új osztályt vezethetsz le, hogy hozzáadhatod a saját hitelesítésedet. 2. A Windows validációhoz egy al-System.Windows.Forms.Control.Validating szükséges az eseménykezelő megírásához.
40. Válaszd ki a megfelelő ** a szükségletekhez igazodva
1. A tömbnek két nyilvánvaló hibája van: nem lehet dinamikusan átméretezni; A méretezés időigényes; 2. ArrayList egydimenziós tömbök és összekapcsolt listák jellemzőit keveri, a Queue és Stack speciális tömbök, amelyek a Tömbön alapulnak; 3. Amikor a program rugalmasabb az elemek hozzáadására és törlésére, robusztusabb típusokat tud létrehozni, és egy ** szimulációs osztály létrehozásakor, akkor indexereket és IEnumerable felületeket kell létrehoznia hozzá.
41. A DataSet jobb, mint az egyedi struktúra
1. A DataSet-eknek két hátránya van: az XML serializációs mechanizmust használó DataSetek és non-.NET kód közötti kölcsönhatás nem túl jó; A DataSet egy nagyon sokoldalú konténer; 2. Az erős DataSet-típusok több tervezési szabályt sértenek, és fejlesztési hatékonyságuk sokkal magasabb, mint az önmaguk által írt elegánsabb tervekké.
42. Jellemzők használata a reflexió egyszerűsítésére
Ha olyan funkcióosztályokat tervezünk és valósítunk meg, amelyek arra kényszerítik a fejlesztőket, hogy dinamikusan használható típusokat, módszereket és attribútumokat jelentsenek be, csökkentheted az alkalmazási futtatóidejű hibákat, és javíthatod a szoftver felhasználói elégedettségét.
43. Kerüld a reflexek túlzott használatát
1. Az Invoke tagok által használt paraméterek és visszatérési értékek a System.Object, amely futásidőben átalakítja a típusokat, de a problémák lehetősége egyre valószínűbbé vált. 2. Az interfész lehetővé teszi, hogy tisztább és karbantarthatóbb rendszert kapjunk, és a reflektorálás nagyon erős késői kötési mechanizmus. A .NET keretrendszer ezt használja adatkötés megvalósítására Windows és webes vezérlők számára.
44. Hozz létre speciális kivételosztályokat az alkalmazáshoz
1. Az egyetlen ok, amiért különböző kivételosztályokra van szükség, hogy a felhasználók könnyen különböző megközelítéseket alkalmazzanak a különböző hibákhoz catch processzorok írásakor; 2. Ha eltérő javítási viselkedések létezhetnek, különféle kivételosztályokat kell létrehozni, az összes olyan konstruktor megadásával létrehozhatunk egy teljesen funkcionális kivételosztályt az alkalmazáshoz, és az InnerException attribútumot használjuk az alacsonyabb szintű hibafeltételek által generált hibainformációk mentésére.
45. Elsőbbséget adjunk a rendellenes biztonsági garanciáknak
1. Az erős kivétel-garancia a legjobb egyensúlyt biztosítja a kivételből való helyreállítás és az egyszerűsített kivételkezelés között, és a program állapota változatlan marad, amikor a művelet a kivétel miatt megszakad. 2. Védekező másolást hajtsanak végre a módosítandó adatokról, módosítsák ezeknek az adatoknak a védelmi másolatát, a középső művelet kivételt okozhat, és az ideiglenes másolat és az eredeti objektum cserébe kerül; 3. A terminátorok, a Dispose() módszerek és a megbízottakhoz kötött cél metóriumok biztosítaniuk kell, hogy semmilyen körülmények között ne dobjanak kivételeket.
46. Az interoperabilitás minimalizálása
1. Az interoperabilitásnak három költsége van: az adatfelsorolás költsége a menedzselt és nem menedzselt halom között, a menedzselt és nem menedzselt kód közötti váltás költsége, valamint a hibrid környezetekkel foglalkozó fejlesztők fejlesztési munkája; 2. A blittable típus interop alkalmazása hatékonyan replikálhat a menedzselt és nem menedzselt környezetek között anélkül, hogy az objektum belső szerkezete befolyásolná. 3. Használja az Be/Kimenet funkciót a legmegfelelőbb, felesleges többszörös replikációk biztosítására, és javítsa a teljesítményt azzal, hogy bejelenti, hogyan kell felsorolni az adatokat. 4. Használd a COM Interop-ot a COM komponensekkel való interoperabilitás megvalósításához a legegyszerűbb módon, a P/Invoke segítségével hívjuk meg a Win32 API-t, vagy a C++ fordító /CLR kapcsolóját használd a menedzselt és nem menedzselt kód keverésére;
47. Elsőbbséget adjunk a biztonsági előírásoknak
1. Kerüld a kezeletlen memóriához való hozzáférést, és az elszigetelt tároló nem akadályozhatja meg a kezelt kód és a megbízható felhasználók hozzáférését. 2. Amikor az összeállítások weben futnak, fontold meg az izolált tárolás használatát, és ha bizonyos algoritmusok magasabb biztonsági engedélyeket követelnek, ezeket a kódokat külön assemblerben kell elkülöníteni.
48. Tanuld el a releváns eszközöket és forrásokat
1. Használd a NUnit automatikus egységteszteket (integrálva a VS2010-be); 2. Az FXCop eszköz megszerzi az IL kódot az összeállításban, elemzi azt a heterogén kódolási szabályok és legjobb gyakorlatok alapján, majd végül jelenti a szabálysértést. 3. Az ILDasm egy IL szétszerelő eszköz, amely segíthet betekintést nyerni a részletekbe; 4. A Shared Source CLI egy implementációs forráskód, amely tartalmazza a .NET keretrendszerkernelt és a C# fordítót. |