Denna artikel är en spegelartikel om maskinöversättning, klicka här för att hoppa till originalartikeln.

Utsikt: 20516|Svar: 0

[Tips] Fyrtiosju sätt att optimera ett C#-program

[Kopiera länk]
Publicerad på 2018-03-15 10:41:59 | | |

1. Ersätt tillgängliga fält med attribut

1、. .NET-databindning stöder endast databindning, och du kan få fördelarna med databindning genom att använda attribut.
2. I åtkomsten till egenskapen kan du använda lock för att lägga till stöd för multitrådning.

2. läsbart (körtidskonstant) och const (kompileringstidskonstant)

1. const kan endast användas för primitiva typer, enum och strängar, medan readonly kan vara vilken typ som helst;
2. const kommer att ersättas med en specifik konstant vid kompileringstillfället, så att om både const och readonly-värden används i referensen, kommer ändringen till readonly att ändra designens ursprungliga avsikt, vilket är behovet av att kompilera om den ändrade sammansättningen för att rereferera det nya konstantvärdet.
3. Const är mer effektivt än skrivskyddat, men förlorar flexibiliteten i tillämpningen.

3. IS och AS

1. Båda är typkonverteringar vid körning, eftersom operatorer endast kan användas i referenstyper, medan den kan använda värden och referenstyper;
2. Den vanliga praxisen är att använda IS för att bestämma typen, och sedan välja att använda som eller en stark typkonverteringsoperator (konvertering definierad av en operatör) selektivt.

4. ConditionalAttribute istället för #if #endif条件编译

1. ConditionalAttribute används endast på metodnivå, och andra objekt som typer, attribut etc. är ogiltiga. Och #if #endif则不受此限制;
2. ConditionalAttribute kan lägga till flera ELLER (ELLER)-operationer för kompileringsvillkor, och #if #endif则可以添加与(OCH) [här kan definieras fullständigt som en separat symbol];
3. Definitionen av ConditioanlAttribute kan placeras i en separat metod för att göra programmet mer flexibelt.

5. Tillhandahåll ToString()-metoden

1. Den kan ge detaljerad information till användare på ett mer användarvänligt sätt;
2. Använd metoden IFormatter.ToString() för att erbjuda mer flexibel anpassning, och om du lägger till gränssnitten IFormatProvider och ICustomFormatter blir det mer logiskt att anpassa meddelandeutgången.

6. Skillnaden mellan värde och referenstyp

1. Värdetyper stöder inte polymorfism, vilket är lämpligt för att lagra data som drivs av applikationer, medan referenser stöder polymorfism, vilket är lämpligt för att definiera applikationsbeteende.
2. För arrayer definierade som värdetyper kan programmets prestanda förbättras avsevärt;
3. Värdetypen har mindre fragmentering av heap-minne, minnesskräp och indirekt åtkomsttid, och dess återförande i metoden sker i form av replikation för att undvika att den interna strukturen exponeras för omvärlden.
4. Värdetyper används i följande scenarier: Typernas ansvar används främst för datalagring; Publika gränssnitt definieras helt av vissa åtkomstattribut för datamedlemmar; Det finns aldrig underklasser; Det finns aldrig polymorft beteende.

7. Värdetyper bör implementeras så konstanta och atomära typer som möjligt

1. Göra vår kod lättare att skriva och underhålla;
2. Tre strategier för att initialisera konstanter: i konstruktionen; växtmetoden; Konstruera en muterbar hjälpklass (t.ex. StringBuilder).

8. Säkerställ att 0 är värd giltig status

1. Standardtillståndet för värdetypen ska vara 0;
2. 0:an av enum-typen ska inte vara ogiltig; I FlagsAttribute är det att säkerställa att värdet 0 är giltigt tillstånd;
3. När strängen är tom kan en sträng returneras. Tom sträng för tom.

9. Relationer med flera representationer av lika omdöme

1. ReferenceEquals() bestämmer att referenserna är lika, och det måste vara sant när båda refererar till samma objekt.
2. Den statiska Equals()-metoden används för att göra referensbedömning först och sedan för att bedöma värdetypen;
3. För bedömning av referenstypen kan du använda metoden omskrivning Equals() när du använder värdesemantik.
4. När Equals()-metoden skrivs om ska även GetHashCode()-metoden skrivas om, och operationen operatorr==() bör tillhandahållas samtidigt.

10. Förstå bristerna i GetHashCode()-metoden

1. GetHashCode() tillämpas endast på hashvärden för hashbaserade **-definierade nycklar, såsom HashTable eller Dictionary;
2. GetHashCode() bör följa motsvarande tre regler: två lika objekt ska returnera samma hashkod; bör vara en instansinvariant; Hashfunktionen bör ge en slumpmässig fördelning över alla heltal.

11. Ge prioritet till användningen av foreach loop-satser

1. foreach kan eliminera kompilatorns kontroll av arraygränsen för for-loopen;
2. Den cirkulära variabeln för foreach är skrivskyddad, och det finns en explicit transformation, som kastar ett undantag när objekttypen för **-objektet är felaktig;
3. ** som krävs för att använda för each är: ha den publika GetEnumberator()-metoden; IEnumberable-gränssnittet är explicit implementerat. IEnumerator-gränssnittet är implementerat;
4. foreach kan ge fördelarna med resurshantering, eftersom om kompilatorn kan bestämma det IDISPOSABLE-gränssnittet kan den använda det optimerade försöket... slutligen blocka;

12. Initialiseringen av standardfältet är bättre än tilldelningssatsen

1. Fältets livslängd initialiserar värdetypen till 0 och referenstypen till null som standard.
2. Att initialisera samma objekt flera gånger minskar kodens exekveringseffektivitet.
3. Att lägga initialiseringen av fältet i konstruktorn är gynnsamt för undantagshantering.

13. Använd den statiska konstruktorn för att initiera statiska medlemmar

1. Den statiska konstruktorn kommer att exekveras innan någon metod, variabel eller attribut för en klass nås;
2. Statiska fält kommer också att köras före den statiska konstruktorn, och den statiska konstruktorn är gynnsam för undantagshantering.

14. Använd konstruktörkedjan (i. NET 4.0 löser redan detta problem med valfria parametrar)

1. Använd detta för att överlämna initialiseringsarbetet till en annan konstruktör, och använd bas för att anropa basklassens konstruktör;
2. Operationssekvensen för typinstanser är: sätt alla statiska fält till 0; Exekvering av statiska fältinitialiserare; en statisk konstruktör som exekverar basklassen; Statiska konstruktorer som kör den aktuella typen;
Sätt alla instansfält till 0; Kör instansfältinitialiserare; Kör den lämpliga basklassinstanskonstruktören; Exekverar instanskonstruktören av den aktuella typen.

15. Använd using och try/finally satser för att rensa upp resurser

I Dispose()-metoden i IDisposable-gränssnittet kan GC.SuppressFinalize() användas för att meddela skräpsamlaren att den slutgiltiga operationen inte längre utförs.

16. Minimera minnesskräp

1. Det tar extra processortid att fördela och förstöra objekt på en heap;
2. Tekniker för att minska antalet tilldelade objekt: ofta använda lokala variabler främjas till fält; Tillhandahåller en klass som lagrar vanliga instanser av Singleton-objekt som uttrycker specifika typer.
3. Använd StringBuilder för att utföra komplexa strängoperationer.

17. Minimera packning och upppackning

1. Var uppmärksam på den implicita konverteringen av en typ till System.Object, och värdetypen bör inte ersättas med System.Object-typen;
2. Att använda gränssnitt istället för typer kan undvika boxning, det vill säga att implementera värdetyper från gränssnitt och sedan anropa medlemmar via gränssnitt.

18. Implementera standardläget för bortkastning

1. För att använda icke-minnesresurser måste den ha en finalizer, garbage collectorn lägger till de implementerade finalizerobjekten i termineringskön efter att ha slutfört minnesobjekten som inte terminerat dem, och sedan startar garbage collectorn en ny tråd för att köra finalizers på dessa objekt. Detta kan undvika problemet med minnesläckage orsakat av att ohanterade minnesresurser inte frigörs.
2. Att använda metoden IDisposable.Dispose() kräver fyra arbetsaspekter: frigivning av alla ohanterade resurser; Frigör alla hanterade resurser; Sätt en statusmarkör för att visa om Dispose() har utförts; Anropa GC.SuppressFinalize(this) för att avbryta objektets termineringsoperation;
3. Lägg till en skyddad virtuell metod Dispose() till typen som behöver polymorfism, och den härledda klassen frigör sin uppgift genom att skriva om denna metod.
4. I den typ som kräver ett IDisoposable gränssnitt bör vi implementera en terminator även om vi inte behöver en.

19. Definiera och implementera gränssnitt över arvstyper

1. Orelaterade typer kan gemensamt implementera ett gemensamt gränssnitt, och det är lättare att implementera ett gränssnitt än arv;
2. Gränssnittet är relativt stabilt, det kapslar in en uppsättning funktioner i ett gränssnitt som andra typer av implementeringskontrakt, medan basklassen kan utökas över tid.

20. Skilja mellan gränssnittsimplementering och omskrivning av virtuella metoder

1. När man implementerar ett gränssnitt i basklassen måste den härledda klassen använda nytt för att dölja användningen av basklassmetoden;
2. Metoden för basklassgränssnittet kan deklareras som en virtuell metod och sedan implementeras i den härledda klassen.

21. Använd förtroende för att uttrycka återkopplingar

1. Delegaten själv tillhandahåller ingen undantagsfångst, så varje multicast-delegatanrop avslutar hela samtalskedjan.
2. Genom att visa och anropa varje delegeringsmål i delegatkedjan kan du undvika att multicast-delegater bara returnerar utdata från den senaste delegaten.

22. Använd händelser för att definiera externa gränssnitt

1. Det bör deklareras som en gemensam händelse, och låta kompilatorn skapa add- och remove-metoder åt oss.
2. Använd behållaren System.ComponentModel.EventHandlerList för att lagra varje händelsehanterare, och använd den för att dölja komplexiteten hos alla händelser när typen innehåller ett stort antal händelser.

23. Undvik att returnera referenser till interna klassobjekt

1. Eftersom åtkomsten till ett värdetypobjekt skapar en kopia av objektet, kommer attributen för att definiera en värdetyp inte att ändra tillståndet inuti typobjektet alls;
2. Konstanta typer kan undvika att ändra objektets tillstånd;
3. Definiera gränssnittet för att begränsa åtkomsten till en delmängd för att minimera skadan på objektets interna tillstånd.
4. Definiera ett wrapper-objekt för att begränsa åtkomsten till ett annat objekt;
5. När kundkoden ändrar de interna dataelementen kan Observer-läget implementeras, så att objektet kan verifiera eller motsvara ändringarna.

24. Deklarativ programmering är bättre än imperativ programmering

Möjligheten att göra misstag i flera liknande handskrivna algoritmer kan undvikas och tydlig och läsbar kod tillhandahålls.

25. Implementera typer så serialiserbara som möjligt

1. Typen representerar inte en UI-kontroll, ett fönster eller en form, och typen bör stödja serialisering;
2. När man lägger till det deserialiserade attributet NonSerializedAttribute kan standardvärdet laddas med metoden OnDeserialization() som implementerar IDeserializationCallback;
3. I versionshantering kan du använda ISerializable-gränssnittet för flexibel kontroll, och tillhandahålla en serialiseringskonstruktor för att initiera objekt enligt data i strömmen, samt kräva tillstånd från SerializationFormatter-undantag vid implementering.
4. Om du behöver skapa en härledd klass måste du tillhandahålla en hook-metod för den härledda klassen.

26. Använd IComparable- och IComparer-gränssnitt för att implementera sorteringsrelationer

1. IComparable-gränssnittet används för att implementera den mest naturliga sorteringsrelationen för typer, överbelasta fyra jämförelseoperatorer och tillhandahålla en överbelastad version av CompareTo()-metoden för att acceptera specifika typer som parametrar.
2. IComparer används för att tillhandahålla sorteringsrelationer som skiljer sig från IComparable, eller för att ge oss sorteringsrelationer som typen själv säger inte är implementerad.

27. Undvik ICloneable-gränssnitt

1. För värdetyper finns det inget behov av att stödja ICloneable-gränssnittet, använd bara standardtilldelningsoperationen;
2. För basklasser som kan behöva stödja ICloneable-gränssnitt bör en skyddad replikeringskonstruktör skapas för dem, och IConeable-gränssnitt bör undvikas.

28. Undvik tvångsomvandlingar

Att använda konstruktörer istället för konverteringsoperatorer kan göra konverteringsarbetet tydligare, vilket lätt kan leda till konstiga buggar på grund av tillfälliga objekt som används efter konverteringen.

29. Överväg endast att använda den nya modifieraren när ackumuleringen av nya versioner orsakar problem

30. Implementera CLS-kompatibla assemblies så mycket som möjligt
1. För att skapa en kompatibel assembler måste två regler följas: parametrarna och returvärdestyperna som används av alla offentliga och skyddade medlemmar i assemblern måste vara kompatibla med CLS; Varje offentlig och skyddad medlem som inte är kompatibel med CLS måste ha ett CLS-kompatibelt alternativ;
2. Du kan kringgå CLS-kompatibilitetstypkontrollen genom att explicit implementera gränssnittet, och CLSCompliantAttribute kommer inte att kontrollera CLS-kompatibiliteten hos privata medlemmar.

31. Implementera en kort och koncis metod så mycket som möjligt

1. JIT-kompilatorn kompilerar i enheter av metoder, och metoder som inte anropas kommer inte att kompileras av JIT;
2. Om koden för Case-satsen i den längre Switch ersätts med en metod i taget, kommer den tid som JIT-kompilatorn sparar att multipliceras;
3. Korta och koncisa metoder samt att välja färre lokala variabler kan uppnå optimerad registeranvändning;
4. Ju färre kontrollgrenar i metoden, desto lättare är det för JIT-kompilatorn att lägga variabler i register.

32. Uppnå små storlekar och hög sammanhållning så mycket som möjligt

1. Placera alla publika klasser och common base-klasser i vissa assemblies, placera verktygsklasser som tillhandahåller funktioner för publika klasser i samma assembly, paketera relevanta publika gränssnitt i egna assemblies, och slutligen bearbeta de klasser som finns över hela den horisontella positionen i applikationen;
2. I princip bör två typer av komponenter skapas: en är en liten och aggregerad samling med en specifik funktion, och den andra är en stor och bred sammansättning med gemensamma funktioner.

33. Begränsa typernas synlighet

1. Att använda gränssnitt för att exponera funktioner för typer kan göra det enklare för oss att skapa interna klasser utan att begränsa deras tillgänglighet utanför assembleren;
2. Ju färre offentliga typer som exponeras mot omvärlden, desto fler möjligheter har du för framtida expansion och förändringsimplementationer.

34. Skapa ett stor-granulärt webb-API

Detta minimerar frekvensen och belastningen av transaktioner mellan maskiner, vilket ger servern stora operationer och finjusterade exekveringar.

35. Omskrivning är bättre än händelseprocessorer

1. Om en händelseprocessor kastar ett undantag kommer andra processorer på händelsekedjan inte att anropas, men detta kommer inte att hända med den omskrivna virtuella metoden.
2. Omskrivning är mycket effektivare än associativa händelseprocessorer, som behöver iterera över hela förfrågningslistan, vilket tar mer CPU-tid.
3. Händelser kan besvaras vid körning, med större flexibilitet, och flera svar kan kopplas till samma händelse.
4. Den vanliga regeln är att hantera en härledd händelse, och omskrivningsmetoden är bättre.

36. Fair use. .NET-körtidsdiagnostik

1. System.Diagnostics.Debug\Trace\EventLog tillhandahåller alla verktyg som behövs för att programmet ska lägga till diagnostisk information i runtimen, och applikationen kan skriva till systemets händelselogg när EventLog tillhandahåller ingrediensen;
2. Slutligen, skriv inte ditt eget diagnostiska bibliotek, .NET FCL har redan det kärnbibliotek vi behöver.

37. Använd standardkonfigurationsmekanismer

1、. System.Windows.Application-klassen i .NET-ramverket definierar egenskaperna för att vi ska kunna etablera en gemensam konfigurationsväg;
2. Application.LocalAppDataPath och Application.userDataPath kommer att generera sökvägsnamnen för den lokala datakatalogen och användardata;
3. Skriv inte data i ProgramFiles och Windows systemkataloger, dessa platser kräver högre säkerhetsbehörigheter, förvänta dig inte att användare har skrivbehörigheter.

38. Anpassa och stöd databindning

1. De två objekten BindingMananger och CurrencyManager genomför dataöverföringen mellan kontrollen och datakällan;
2. Fördelar med databindning: att använda databindning är mycket enklare än att skriva egen kod; Den bör användas för omfattningar som inte är textdata – andra visningsegenskaper kan också begränsas; För Windowos Forms-databindningar, möjligheten att hantera multipel kontrollsynkronisering av checkrelaterade datakällor;
3. När objektet inte stöder de nödvändiga attributen kan du stödja databindning genom att blockera det aktuella objektet och sedan lägga till det önskade objektet.

39. Använda. .NET-validering

1. Det finns fem kontroller i ASP.NET för att verifiera giltighet, och du kan använda CustomValidator för att härleda en ny klass för att lägga till din egen autentisator.
2. Windows-validering kräver en sub-System.Windows.Forms.Control.Validating för att skriva en händelsehanterare.

40. Välj rätt ** efter behoven

1. Matrisen har två uppenbara defekter: den kan inte ändras dynamiskt; Att ändra storlek tar tid;
2. ArrayList blandar egenskaperna hos endimensionella arrayer och länkade listor, Queue och Stack är specialarrayer baserade på Array;
3. När programmet är mer flexibelt att lägga till och ta bort objekt kan det skapa mer robusta typer, och när man skapar en klass som simulerar ** bör det implementera indexerare och IEnumberable-gränssnitt för det.

41. DataSet är bättre än anpassad struktur

1. DataSets har två nackdelar: interaktionen mellan DataSets med XML-serialiseringsmekanism och non-.NET kod är inte särskilt bra; DataSet är en mycket mångsidig container;
2. Starka typer av DataSets bryter mot fler designregler, och deras utvecklingseffektivitet är mycket högre än för de mer eleganta designen som skrivits av sig själva.

42. Använd egenskaper för att förenkla reflektion

Genom att designa och implementera funktionsklasser som tvingar utvecklare att deklarera dynamiskt användbara typer, metoder och attribut kan du minska applikationsfel under körning och förbättra användarnöjdheten i programvaran.

43. Undvik att överanvända reflexer

1. Parametrarna och returvärdena som används av Invoke-medlemmarna är System.Object, som konverterar typer vid körning, men risken för problem har blivit mer sannolik.
2. Gränssnittet gör att vi får ett tydligare och mer underhållbart system, och reflektion är en mycket kraftfull sen bindningsmekanism. .NET-ramverket använder det för att implementera databindning för Windows-kontroller och webbkontroller.

44. Skapa specifika undantagsklasser för applikationen

1. Den enda anledningen till att olika undantagsklasser behövs är för att låta användare enkelt ta olika angreppssätt på olika fel när de skriver catch-processorer;
2. När det kan finnas olika reparationsbeteenden bör vi skapa en mängd olika undantagsklasser, genom att tillhandahålla alla konstruktorer som stöds av undantagsbasklassen kan vi skapa en fullt fungerande undantagsklass för applikationen och använda attributet InnerException för att spara all felinformation som genereras av lägre felnivåer.

45. Prioritera onormala säkerhetsgarantier

1. Stark undantagsgaranti ger den bästa balansen mellan återställning från undantag och förenklad undantagshantering, och programmets tillstånd förblir oförändrat när operationen avbryts på grund av undantaget.
2. Gör defensiv kopiering av data som ska ändras, modifiera den defensiva kopian av dessa data, operationen i mitten kan orsaka ett undantag, och den tillfälliga kopian och originalobjektet kommer att utbytas;
3. Terminatorer, Dispose()-metoder och målmetoder bundna till delegater bör säkerställa att de under inga omständigheter kastar undantag.

46. Minimera interoperabiliteten

1. Det finns tre kostnader för interoperabilitet: kostnaden för datauppräkning mellan hanterade och ohanterade heaps, kostnaden för att växla mellan hanterad kod och ohanterad kod, samt utvecklingsarbetet för utvecklare som arbetar med hybrida miljöer;
2. Att använda den blitable typen i interop kan effektivt replikera fram och tillbaka mellan hanterade och ohanterade miljöer utan att påverkas av objektets interna struktur.
3. Använd funktionen In/Out för att säkerställa de mest lämpliga onödiga multipliseringarna, och förbättra prestandan genom att deklarera hur datan enumereras.
4. Använd COM Interop för att implementera interoperabilitet med COM-komponenter på det enklaste sättet, använd P/Invoke för att anropa Win32 API, eller använd /CLR-switchen i C++-kompilatorn för att blanda hanterad och ohanterad kod;

47. Ge prioritet till säkerhetskoder

1. Undvik åtkomst till ohanterat minne så mycket som möjligt, och isolerad lagring kan inte förhindra åtkomst från hanterad kod och betrodda användare.
2. När assemblies körs på webben, överväg att använda isolerad lagring, och när vissa algoritmer kräver högre säkerhetsbehörigheter bör dessa koder isoleras i en separat assembly.

48. Behärska relevanta verktyg och resurser

1. Använd NUnit för att etablera automatiska enhetstester (integrerat i VS2010);
2. FXCop-verktyget kommer att hämta IL-koden i assembleren, analysera den mot heterogena kodningsregler och bästa praxis, och slutligen rapportera överträdelsen.
3. ILDasm är ett IL-demonteringsverktyg som kan hjälpa oss att få insikt i detaljer;
4. Shared Source CLI är en implementeringskällkod som innehåller .NET-ramverkets kärna och C#-kompilatorn.




Föregående:Service Fabric - Stateful Service-konceptet
Nästa:.net/c# SynchronizationContext för detaljer
Friskrivning:
All programvara, programmeringsmaterial eller artiklar som publiceras av Code Farmer Network är endast för lärande- och forskningsändamål; Ovanstående innehåll får inte användas för kommersiella eller olagliga ändamål, annars kommer användarna att bära alla konsekvenser. Informationen på denna sida kommer från internet, och upphovsrättstvister har inget med denna sida att göra. Du måste helt radera ovanstående innehåll från din dator inom 24 timmar efter nedladdning. Om du gillar programmet, vänligen stöd äkta programvara, köp registrering och få bättre äkta tjänster. Om det finns något intrång, vänligen kontakta oss via e-post.

Mail To:help@itsvse.com