Denne artikkelen er en speilartikkel om maskinoversettelse, vennligst klikk her for å hoppe til originalartikkelen.

Utsikt: 20516|Svare: 0

[Tips] Førtisju måter å optimalisere et C#-program på

[Kopier lenke]
Publisert på 15.03.2018 10:41:59 | | |

1. Erstatt tilgjengelige felt med attributter

1、. .NET databinding støtter kun databinding, og du kan få fordelene med databinding ved å bruke attributter.
2. I tilgang til egenskapen kan du bruke lock for å legge til støtte for multitråding.

2. lesebeskyttet (kjøretidskonstant) og const (kompileringstidskonstant)

1. const kan kun brukes for primitive typer, enum og strenger, mens skrivebeskyttet kan være hvilken som helst type;
2. const vil bli erstattet med en spesifikk konstant ved kompilering, slik at hvis både const og readonly-verdier brukes i referansen, vil endringen til readonly endre den opprinnelige intensjonen med designet, som er behovet for å rekompilere den endrede sammensetningen for å rereferere den nye konstantverdien.
3. Const er mer effektivt enn skrivebeskyttet, men mister fleksibiliteten ved anvendelse.

3. IS og AS

1. Begge er typekonverteringer under kjøring, siden operatorer kun kan brukes i referansetyper, mens den kan bruke verdier og referansetyper;
2. Den vanlige praksisen er å bruke IS for å bestemme typen, og deretter velge å bruke som eller en sterk typekonverteringsoperator (konvertering definert av en operatør) selektivt.

4. ConditionalAttribute i stedet for #if #endif条件编译

1. ConditionalAttribute brukes kun på metodenivå, og andre elementer som typer, attributter osv. er ugyldige. Og #if #endif则不受此限制;
2. ConditionalAttribute kan legge til flere ELLER (ELLER)-operasjoner for kompilasjonsbetingelser, og #if #endif则可以添加与(OG) [her kan fullstendig defineres som et annet separat symbol];
3. Definisjonen av ConditioanlAttribute kan plasseres i en separat metode for å gjøre programmet mer fleksibelt.

5. Gi ToString()-metoden

1. Den kan gi detaljert informasjon til brukerne på en mer vennlig måte;
2. Bruk metoden IFormatter.ToString() for å gi mer fleksibel tilpasning, og hvis du legger til IFormatProvider og ICustomFormatter-grensesnittene, vil det gi mer mening å tilpasse meldingsutdataen.

6. Forskjellen mellom verdi og referansetype

1. Verdityper støtter ikke polymorfisme, som egner seg for lagring av data operert av applikasjoner, mens referanser støtter polymorfisme, som er egnet for å definere applikasjonsatferd.
2. For matriser definert som verdityper kan ytelsen til programmet forbedres betydelig;
3. Verditypen har mindre fragmentering av heap-minne, minneavfall og indirekte tilgangstid, og returen i metoden skjer i form av replikasjon for å unngå å eksponere den interne strukturen for omverdenen.
4. Verdityper brukes i følgende scenarier: Ansvarsområdene til typene brukes hovedsakelig for datalagring; Offentlige grensesnitt er fullstendig definert av noen datamedlems-tilgangsattributter; Det finnes aldri underklasser; Det finnes aldri polymorf oppførsel.

7. Verdityper bør implementeres så konstante og atomære typer som mulig

1. Gjøre koden vår enklere å skrive og vedlikeholde;
2. Tre strategier for initialisering av konstanter: i konstruksjon; plantemetode; Konstruer en foranderlig hjelperklasse (f.eks. StringBuilder).

8. Sørg for at 0 er verdig gyldig status

1. Standardtilstanden til verditypen skal være 0;
2. 0 av enum-typen skal ikke være ugyldig; I FlagsAttribute er det å sikre at 0-verdien er gyldig tilstand;
3. Når strengen er tom, kan en streng returneres. Tom streng for tom.

9. Multiple representasjonsforhold med lik vurdering

1. ReferenceEquals() avgjør at referansene er like, og det må være sant når begge refererer til samme objekt.
2. Den statiske Equals()-metoden brukes først for å gjøre referansevurdering, og deretter for å vurdere verditypen;
3. For vurderingen av referansetypen kan du bruke omskrivingsmetoden Equals() når du bruker verdisemantikk.
4. Når Equals()-metoden omskrives, bør også GetHashCode()-metoden skrives om, og operatorer==()-operasjonen skal gis samtidig.

10. Forstå svakhetene ved GetHashCode()-metoden

1. GetHashCode() brukes kun på hashverdier for hash-baserte **-definerte nøkler, som HashTable eller Dictionary;
2. GetHashCode() skal følge de tilsvarende tre reglene: to like objekter skal returnere samme hashkode; bør være en instansinvariant; Hash-funksjonen skal gi en tilfeldig fordeling over alle heltall.

11. Gi prioritet til bruk av foreach loop-setninger

1. Foreach kan eliminere kompilatorens sjekk av array-grensen til for-løkken;
2. Den sirkulære variabelen til foreach er skrivebeskyttet, og det finnes en eksplisitt transformasjon som kaster et unntak når objekttypen til **-objektet er feil;
3. ** som kreves for å bruke for hver er: ha den offentlige GetEnumberator()-metoden; IEnumberable-grensesnittet er eksplisitt implementert. IEnumerator-grensesnittet er implementert;
4. foreach kan gi fordelene med ressursstyring, fordi hvis kompilatoren kan bestemme det IDisposable grensesnittet, kan den bruke det optimaliserte try... til slutt blokkere;

12. Initialiseringen av standardfeltet er bedre enn tildelingssetningen

1. Feltlevetiden initialiserer verditypen til 0 og referansetypen til null som standard.
2. Å initialisere det samme objektet flere ganger vil redusere utførelseseffektiviteten til koden.
3. Å legge initialiseringen av feltet i konstruktøren er gunstig for unntakshåndtering.

13. Bruk den statiske konstruktøren til å initialisere statiske medlemmer

1. Den statiske konstruktøren vil bli utført før noen metode, variabel eller attributt i en klasse er aksessert;
2. Statiske felt vil også kjøre før den statiske konstruktøren, og den statiske konstruktøren er gunstig for unntakshåndtering.

14. Bruk konstruktørkjeden (i. NET 4.0 løser allerede dette problemet med valgfrie parametere)

1. Bruk dette til å overlate initialiseringsarbeidet til en annen konstruktør, og bruk base for å kalle konstruktøren av baseklassen;
2. Operasjonssekvensen for typeinstanser er: sett alle statiske felt til 0; Utførelse av statiske feltinitialisatorer; en statisk konstruktør som utfører basisklassen; Statiske konstruktører som utfører den nåværende typen;
Sett alle instansfelt til 0; Kjør instansfeltinitialisatorer; Kjør den riktige basisklasse-instanskonstruktøren; Kjør instanskonstruktøren av den nåværende typen.

15. Bruk using og try/finale-setninger for å rydde opp i ressurser

I Dispose()-metoden til IDisposable-grensesnittet kan GC.SuppressFinalize() brukes til å varsle søppelsamleren om at den siste operasjonen ikke lenger utføres.

16. Minimer minneavfall

1. Det tar ekstra prosessortid å tildele og ødelegge objekter på en heap;
2. Teknikker for å redusere antall tildelte objekter: ofte brukte lokale variabler fremmes til felt; Gir en klasse som lagrer vanlige instanser av Singleton-objekter som uttrykker spesifikke typer.
3. Bruk StringBuilder for å utføre komplekse strengoperasjoner.

17. Minimer pakking og utpakking

1. Vær oppmerksom på den implisitte konverteringen av en type til System.Object, og verditypen bør ikke erstattes med System.Object-typen;
2. Å bruke grensesnitt i stedet for typer kan unngå boksing, det vil si å implementere verdityper fra grensesnitt, og deretter kalle medlemmer gjennom grensesnitt.

18. Implementer standard Dispose-modus

1. For å bruke ikke-minneressurser må den ha en finalizer, garbage collector vil legge til de implementerte finalizer-objektene i termineringskøen etter å ha fullført minneobjektene som ikke har terminert dem, og deretter vil garbage collector starte en ny tråd for å kjøre finalizerne på disse objektene. Dette kan unngå problemet med minnelekkasje forårsaket av at ubehandlede minneressurser ikke frigjøres.
2. Bruk av IDisposable.Dispose()-metoden krever fire arbeidsaspekter: frigivelse av alle uadministrerte ressurser; Frigjør alle forvaltede ressurser; Sett en statusmarkør for å indikere om Dispose() er utført; Kall GC.SuppressFinalize(this) for å avbryte objektets termineringsoperasjon;
3. Legg til en beskyttet virtuell metode Dispose() til typen som trenger polymorfisme, og den avledede klassen frigjør sin oppgave ved å omskrive denne metoden.
4. I typen som krever et IDisoposable grensesnitt, bør vi implementere en terminator selv om vi ikke trenger en.

19. Definer og implementer grensesnitt over arvetyper

1. Ikke-relaterte typer kan sammen implementere et felles grensesnitt, og det er enklere å implementere et grensesnitt enn arv;
2. Grensesnittet er relativt stabilt, det kapsler inn et sett funksjoner i et grensesnitt som andre typer implementeringskontrakter, mens basisklassen kan utvides over tid.

20. Skille mellom grensesnittimplementering og omskriving av virtuelle metoder

1. Når man implementerer et grensesnitt i baseklassen, må den avledede klassen bruke nytt for å skjule bruken av baseklassemetoden;
2. Metoden til basisklassegrensesnittet kan erklæres som en virtuell metode, og deretter implementeres i den avledede klassen.

21. Bruk tillit for å uttrykke tilbakeringinger

1. Delegaten selv gir ingen unntaksfangst, så ethvert multicast-delegatanrop vil avslutte hele samtalekjeden.
2. Ved å vise og kalle hvert delegasjonsmål på delegatkjeden, kan du unngå at multicast-delegater returnerer kun utdataene til den siste delegaten.

22. Bruk hendelser for å definere eksterne grensesnitt

1. Det bør erklæres som en felles hendelse, og la kompilatoren lage add- og remove-metoder for oss.
2. Bruk System.ComponentModel.EventHandlerList-beholderen for å lagre hver hendelseshåndterer, og bruk den til å skjule kompleksiteten i alle hendelser når typen inneholder et stort antall hendelser.

23. Unngå å returnere referanser til interne klasseobjekter

1. Siden tilgangen til et verditypeobjekt vil lage en kopi av objektet, vil attributtene ved å definere en verditype ikke endre tilstanden inne i typeobjektet i det siste;
2. Konstanttyper kan unngå å endre tilstanden til objektet;
3. Definer grensesnittet for å begrense tilgangen til en delmengde for å minimere skaden på objektets indre tilstand.
4. Definer et wrapper-objekt for å begrense tilgangen til et annet objekt;
5. Når kundekoden endrer de interne dataelementene, kan Observer-modusen implementeres, slik at objektet kan verifisere eller samsvare med endringene.

24. Deklarativ programmering er bedre enn imperativ programmering

Muligheten for å gjøre feil i flere lignende håndskrevne algoritmer kan unngås, og klar og lesbar kode tilbys.

25. Implementer typer så serialiserbare som mulig

1. Typen representerer ikke en UI-kontroll, vindu eller skjema, og typen bør støtte serialisering;
2. Når man legger til det deserialiserte attributtet NonSerializedAttribute, kan standardverdien lastes inn med OnDeserialization()-metoden som implementerer IDeserializationCallback;
3. I versjonskontroll kan du bruke ISerializable-grensesnittet for fleksibel kontroll, og tilby en serialiseringskonstruktør for å initialisere objekter i henhold til dataene i strømmen, og også kreve tillatelse fra SerializationFormatter-unntak ved implementering.
4. Hvis du trenger å lage en avledet klasse, må du oppgi en hook-metode for den avledede klassen.

26. Bruk IComparable- og IComparer-grensesnitt for å implementere sorteringsrelasjoner

1. IComparable-grensesnittet brukes til å implementere den mest naturlige sorteringsrelasjonen for typer, overbelaste fire sammenligningsoperatorer, og tilby en overbelastet versjon av CompareTo()-metoden for å akseptere spesifikke typer som parametere.
2. IComparer brukes til å gi sorteringsrelasjoner som er forskjellige fra IComparable, eller til å gi oss sorteringsrelasjoner som typen selv sier ikke er implementert.

27. Unngå ICloneable grensesnitt

1. For verdityper er det ikke nødvendig å støtte ICloneable-grensesnitt, bare bruk standard tildelingsoperasjon;
2. For baseklasser som kan trenge å støtte ICloneable-grensesnitt, bør en beskyttet replikasjonskonstruktør opprettes for dem, og IConeable-grensesnitt bør unngås.

28. Unngå tvangsomgjøringsoperatører

Å bruke konstruktører i stedet for konverteringsoperatorer kan gjøre konverteringen klarere, noe som lett kan føre til rare feil på grunn av midlertidige objekter som brukes etter konverteringen.

29. Vurder kun å bruke den nye modifikatoren når akkumulering av nye versjoner skaper problemer

30. Implementer CLS-kompatible samlinger så mye som mulig
1. For å lage en kompatibel samling må to regler følges: parameterne og returverditypene som brukes av alle offentlige og beskyttede medlemmer av samlingen må være kompatible med CLS; Ethvert offentlig og beskyttet medlem som ikke er kompatibelt med CLS må ha et CLS-kompatibelt alternativ;
2. Du kan omgå CLS-kompatibilitetstypesjekken ved å eksplisitt implementere grensesnittet, og CLSCompliantAttribute vil ikke sjekke CLS-kompatibiliteten til private medlemmer.

31. Implementer en kort og konsis metode så mye som mulig

1. JIT-kompilatoren kompilerer i enheter av metoder, og metoder som ikke kalles vil ikke bli kompilert av JIT;
2. Hvis koden til Case-setningen i den lengre Switch erstattes med én metode om gangen, vil tiden som er spart av JIT-kompilatoren bli multiplisert;
3. Korte og konsise metoder og valg av færre lokale variabler kan oppnå optimalisert registerbruk;
4. Jo færre kontrollgrener i metoden, desto enklere er det for JIT-kompilatoren å legge variabler i registre.

32. Oppnå små størrelser og høye sammenhengende sammenheng så mye som mulig

1. Legge alle offentlige klasser og felles base-klasser i noen assemblies, plassere verktøyklassene som gir funksjoner for offentlige klasser i samme assembly, pakke de relevante offentlige grensesnittene i egne assemblies, og til slutt behandle klassene som ligger over hele den horisontale posisjonen i applikasjonen;
2. I prinsippet bør to typer komponenter opprettes: den ene er en liten og aggregert samling med en spesifikk funksjon, og den andre er en stor og bred sammensetning med felles funksjoner.

33. Begrens synligheten til typene

1. Å bruke grensesnitt for å eksponere funksjonene til typer kan gjøre det enklere for oss å lage interne klasser uten å begrense deres tilgjengelighet utenfor assemblyen;
2. Jo færre offentlige typer som eksponeres for omverdenen, desto flere muligheter har du for fremtidig utvidelse og endringsimplementeringer.

34. Lag et stor-granulært web-API

Dette minimerer hyppigheten og belastningen av transaksjoner mellom maskiner, og legger store operasjoner og detaljerte utførelser på serveren.

35. Omskriving er bedre enn hendelsesprosessorer

1. Hvis en hendelsesprosessor kaster et unntak, vil ikke andre prosessorer på hendelseskjeden bli kalt, men dette vil ikke skje med den omskrevne virtuelle metoden.
2. Omskriving er mye mer effektivt enn assosiative hendelsesprosessorer, som må iterere over hele forespørselslisten, noe som tar mer CPU-tid.
3. Hendelser kan besvares under kjøring, med større fleksibilitet, og flere svar kan knyttes til samme hendelse.
4. Den vanlige regelen er å håndtere en avledet hendelse, og omskrivingsmetoden er bedre.

36. Fair use. .NET-kjøretidsdiagnostikk

1. System.Diagnostics.Debug\Trace\EventLog gir alle verktøyene som trengs for at programmet skal legge til diagnostisk informasjon i kjøretiden, og applikasjonen kan skrive til systemhendelsesloggen når EventLog leverer ingrediensen;
2. Til slutt, ikke skriv ditt eget diagnostiske bibliotek, .NET FCL har allerede kjernebiblioteket vi trenger.

37. Bruk standard konfigurasjonsmekanismer

1、. System.Windows.Application-klassen i .NET-rammeverket definerer egenskapene for at vi skal etablere en felles konfigurasjonssti;
2. Application.LocalAppDataPath og Application.userDataPath vil generere stinavnene til den lokale datakatalogen og brukerdata;
3. Ikke skriv data i ProgramFiles og Windows systemkataloger, disse stedene krever høyere sikkerhetstillatelser, ikke forvent at brukere har skrivetillatelser.

38. Tilpass og støtt databinding

1. De to objektene BindingMananger og CurrencyManager realiserer dataoverføringen mellom kontrollen og datakilden;
2. Fordeler med databinding: å bruke databinding er mye enklere enn å skrive sin egen kode; Den bør brukes for andre omfang enn tekstdataelementer – andre visningsegenskaper kan også begrenses; For Windowos Forms-databindinger, muligheten til å håndtere synkronisering av flere kontroller av sjekkrelaterte datakilder;
3. Når objektet ikke støtter de nødvendige attributtene, kan du støtte databinding ved å blokkere det nåværende objektet og deretter legge til det ønskede objektet.

39. Bruk. .NET-validering

1. Det finnes fem kontroller i ASP.NET for å verifisere gyldighet, og du kan bruke CustomValidator for å utlede en ny klasse for å legge til din egen autentisator.
2. Windows-validering krever en sub-System.Windows.Forms.Control.Validating for å skrive en hendelseshåndterer.

40. Velg riktig ** etter behovene

1. Arrayet har to åpenbare feil: det kan ikke dynamisk endres i størrelse; Å endre størrelse er tidkrevende;
2. ArrayList blander egenskapene til endimensjonale arrays og lenkede lister, Kø og Stack er spesielle arrays basert på Array;
3. Når programmet er mer fleksibelt til å legge til og slette elementer, kan det lage mer robuste typer, og når det opprettes en klasse som simulerer **, bør det implementere indeksere og IEnumberable grensesnitt for det.

41. Datasett er bedre enn egendefinert struktur

1. DataSets har to ulemper: samspillet mellom DataSets som bruker XML-serialiseringsmekanisme og non-.NET kode er ikke særlig godt; DataSet er en svært allsidig beholder;
2. Sterke typer DataSets bryter flere designregler, og deres utviklingseffektivitet er mye høyere enn for de mer elegante designene skrevet av seg selv.

42. Bruk egenskaper for å forenkle refleksjon

Ved å designe og implementere funksjonsklasser som tvinger utviklere til å erklære dynamisk brukbare typer, metoder og attributter, kan du redusere applikasjonskjøringsfeil og forbedre brukertilfredsheten i programvaren.

43. Unngå overbruk av reflekser

1. Parameterne og returverdiene som brukes av Invoke-medlemmer er System.Object, som konverterer typer under kjøring, men muligheten for problemer har blitt mer sannsynlig.
2. Grensesnittet lar oss få et klarere og mer vedlikeholdbart system, og refleksjon er en svært kraftig sen bindingsmekanisme. .NET-rammeverket bruker det til å implementere databinding for Windows-kontroller og webkontroller.

44. Opprett spesifikke unntaksklasser for applikasjonen

1. Den eneste grunnen til at ulike unntaksklasser trengs, er for å gjøre det enkelt for brukere å ta ulike tilnærminger til ulike feil når de skriver catch-prosessorer;
2. Når det kan være ulike reparasjonsatferder, bør vi lage en rekke forskjellige unntaksklasser; ved å tilby alle konstruktørene som støttes av unntaksbasisklassen, kan vi lage en fullt funksjonell unntaksklasse for applikasjonen, og bruke attributtet InnerException for å lagre all feilinformasjon generert av lavere feilbetingelser.

45. Gi prioritet til unormale sikkerhetsgarantier

1. Sterk unntaksgaranti gir den beste balansen mellom gjenoppretting fra unntak og forenklet unntakshåndtering, og programmets tilstand forblir uendret når operasjonen avbrytes på grunn av unntaket.
2. Foreta defensiv kopiering av dataene som skal endres, endre den defensive kopien av disse dataene, operasjonen i midten kan forårsake et unntak, og den midlertidige kopien og det opprinnelige objektet vil bli byttet;
3. Terminatorer, Dispose()-metoder og målmetoder bundet til delegater bør sørge for at de ikke kaster unntak under noen omstendigheter.

46. Minimer interoperabilitet

1. Det er tre kostnader ved interoperabilitet: kostnaden ved dataopptelling mellom administrerte og uadministrerte heaps, kostnaden ved å bytte mellom administrert kode og uadministrert kode, og utviklingsarbeidet til utviklere som arbeider med hybride miljøer;
2. Bruk av den blitable typen i interop kan effektivt replikere frem og tilbake mellom administrerte og ustyrte miljøer uten å bli påvirket av objektets interne struktur.
3. Bruk In/Out-funksjonen for å sikre de mest hensiktsmessige unødvendige multiple replikeringene, og forbedre ytelsen ved å erklære hvordan dataene er opplistet.
4. Bruke COM Interop for å implementere interoperabilitet med COM-komponenter på den enkleste måten, bruke P/Invoke for å kalle Win32 API, eller bruke /CLR-bryteren i C++-kompilatoren for å blande administrert og uadministrert kode;

47. Gi prioritet til sikkerhetsforskrifter

1. Unngå tilgang til uadministrert minne så mye som mulig, og isolert lagring kan ikke forhindre tilgang fra administrert kode og betrodde brukere.
2. Når assemblies kjører på nettet, bør du vurdere å bruke isolert lagring, og når visse algoritmer krever høyere sikkerhetstillatelser, bør disse kodene isoleres i en separat assembly.

48. Mestre relevante verktøy og ressurser

1. Bruke NUnit for å etablere automatiske enhetstester (integrert i VS2010);
2. FXCop-verktøyet vil hente IL-koden i assembleren, analysere den mot heterogene kodingsregler og beste praksis, og til slutt rapportere bruddet.
3. ILDasm er et IL-demonteringsverktøy som kan hjelpe oss å få innsikt i detaljer;
4. Shared Source CLI er en implementasjonskildekode som inneholder .NET-rammeverkets kjerne og C#-kompilator.




Foregående:Service Fabric - Stateful Service-konseptet
Neste:.net/c# SynchronizationContext for detaljer
Ansvarsfraskrivelse:
All programvare, programmeringsmateriell eller artikler publisert av Code Farmer Network er kun for lærings- og forskningsformål; Innholdet ovenfor skal ikke brukes til kommersielle eller ulovlige formål, ellers skal brukerne bære alle konsekvenser. Informasjonen på dette nettstedet kommer fra Internett, og opphavsrettstvister har ingenting med dette nettstedet å gjøre. Du må fullstendig slette innholdet ovenfor fra datamaskinen din innen 24 timer etter nedlasting. Hvis du liker programmet, vennligst støtt ekte programvare, kjøp registrering, og få bedre ekte tjenester. Hvis det foreligger noen krenkelse, vennligst kontakt oss på e-post.

Mail To:help@itsvse.com