"Nice to know" om strings

by DotNetNerd 1. November 2007 15:30
For ikke ret lang tid siden gik det op for mig hvor lidt den gennemsnitlige programmør egentlig ved om den datatype der nok bruges allermest - altså strings. Jeg skal på ingen måde gøre mig bedre end andre for min viden omkring operationer på strings var heller hverken værre eller bedre end de fleste andres, før jeg læste "CLR via C#".

Derfor vil jeg lige skrive lidt "nice to know" information om strenge, dog startende med ting de fleste nok i nogen grad er klar over bare for at få alle up to speed.

1. Strings er immutable, hvilket vil sige at når en streng først er oprettet på heapen kan dens indhold på ingen måde ændres. Operationer med strings vil altid medfører at en ny string skabes. Dette er hovedårsagen til klassen StringBuilder som istedet arbejder på et char-array således at der ikke skabes en string før ToString() kaldes. Der er dog naturligvis også et overhead ved brug af StringBuilder, så to gode råd er at bruge den hvis mere end 2 konkatineringer foretages, og at angive en størrelse i constructoren så vidt det er muligt - da det vil betyde at arrayet redimentioneres så få gange som muligt.

2. .NET frameworket giver mulighed for noget der kaldes string interning, som går ud på at en string oprettes i en intern hashtable. På den måde undgår man at have flere ens strenge idet der vil returneres en reference til den eksisterende streng hvis man interner en streng der allerede findes - se metoderne string.Intern og string.IsInterned. Dette skal dog benyttes sparsomt, da en interned string sandsynligvis ikke vil blive garbage collected før app domainet lukker!

3. På grund af string interning - og fordi det giver pænere kode - er string.Empty at foretrække frem for "" sådan at man slipper for at oprette et streng objekt blot for at angive en tom streng. Ved sammenligning med en tom streng anbefales det dog istedet at man enten bruger string.IsNullOrEmpty, som er en pæn måde at checke både for null og empty, eller "myString.Length = 0" - som faktisk er den hurtigste måde at checke for empty rent performancemæssigt.

4. Som standard bruger == operatoren en Ordinal algoritme til sammenligning af strenge. Det vil sige at der ikke tages højde for Culture, men at der er forskel på små og store bogstaver. Med andre ord kan man opnå en pæn hastighedsoptimering ved specifikt at bruge en algoritme som OrdinalIgnoreCase til at sammenligne strenge der kun bruges i kode, og man kan opnå en bedre sammenligning af Culture specifik kode ved at bruge CurrentCulture / CurrentCultureIgnoreCase. Faktisk anbefaler Microsoft at man altid bruger Equals metoden med specifik angivelse af StringComparison enumeration, som beskriver hvilken algoritme der bruges, da koden derved er mere beskrivende for hvilken sammenligning man ønsker.

Hvis du vil se hvor stor forskellen rent faktisk er på algoritmernes hastighed er her en test udført af en af Microsofts egne udviklere: http://blogs.msdn.com/noahc/archive/2007/06/29/string-equals-performance-comparison.aspx

5. string.ToUpperInvariant har modtaget særbehandling i frameworket, således at den er optimeret i forhold til ToLower/ToLowerInvariant/ToUpper, derfor kan den med fordel benyttes som den foretrukne løsning hvis man ønsker at lave en streng hvor alle tegn er ens cased.

Tags:

Who am I?

My name is Christian Holm Diget, and I work as an independent consultant, in Denmark, where I write code, give advice on architecture and help with training. On the side I get to do a bit of speaking and help with miscellaneous community events.

Some of my primary focus areas are code quality, programming languages and using new technologies to provide value.

Microsoft Certified Professional Developer

Microsoft Most Valuable Professional

Month List