sql >> Databasteknik >  >> RDS >> Database

Är strängoperatorn "+" så enkel?

Introduktion

En strängdatatyp är en av de grundläggande datatyperna, tillsammans med numeriska (int, long, double) och logiska (booleska). Du kan knappast föreställa dig åtminstone ett användbart program som inte använder denna typ.

På .NET-plattformen presenteras strängtypen som en oföränderlig strängklass. Dessutom är den starkt integrerad i CLR-miljön och stöds även av C#-kompilatorn.

Denna artikel ägnas åt sammanlänkning – en operation som utförs på strängar lika ofta som additionsoperationen på siffror. Du kanske tänker:"Vad finns det att säga?", trots allt vet vi alla om strängoperatorn "+", men som det visade sig har den sina egna egenskaper.

Språkspecifikation för strängoperator "+"

C#-språkspecifikationen tillhandahåller tre överbelastningar för strängoperatorn "+":

string operator + (string x, string y)

string operator + (string x, object y)

string operator + (object x, string y)

Om en av operanderna för strängsammansättning är NULL, infogas den tomma strängen. Annars representeras alla argument, som inte är en sträng, som en sträng genom att anropa den virtuella metoden ToString. Om ToString-metoden returnerar NULL, infogas en tom sträng. Det bör noteras att enligt specifikationen bör denna operation aldrig returnera NULL.

Beskrivningen av operatorn är tillräckligt tydlig, men om vi tittar på implementeringen av klassen String hittar vi en tydlig definition av endast två operatorer "==" och "!=". En rimlig fråga uppstår:vad händer bakom kulisserna av strängsammansättning? Hur hanterar kompilatorn strängoperatorn "+"?

Svaret på denna fråga visade sig inte vara så svårt. Låt oss ta en närmare titt på den statiska String.Concat-metoden. String.Concat-metoden sammanfogar en eller flera instanser av String-klassen eller vyer som String-värden för en eller flera instanser av Object. Det finns följande överbelastningar av denna metod:

public static String Concat (String str0, String str1)

public static String Concat (String str0, String str1, String str2)

public static String Concat (String str0, String str1, String str2, String str3)

public static String Concat (params String[] values)

public static String Concat (IEnumerable <String> values)



public static String Concat (Object arg0)

public static String Concat (Object arg0, Object arg1)

public static String Concat (Object arg0, Object arg1, Object arg2)

public static String Concat (Object arg0, Object arg1, Object arg2, Object arg3, __arglist)



public static String Concat <T> (IEnumerable <T> values)

Detaljer

Anta att vi har följande uttryck s =a + b, där a och b är strängar. Kompilatorn konverterar den till ett anrop av en Concat statisk metod, dvs.

s = string.Concat (a, b)

Strängsammansättningsoperationen, som alla andra additionsoperationer i C#-språket, är vänsterassociativ.

Allt är klart med två rader, men vad händer om det finns fler rader? Uttrycket s =a + b + c, givet operationens vänsterassociativitet, skulle kunna ersättas med:

s = string.Concat(string.Concat (a, b), c)

Men med tanke på överbelastningen som kräver tre argument, kommer den att omvandlas till:

s = string.Concat (a, b, c)

Den liknande situationen är med sammanlänkningen av fyra strängar. För att sammanfoga 5 eller fler strängar har vi strängen.Concat överbelastning (params sträng[]), så det är nödvändigt att ta hänsyn till overheaden som är associerad med minnesallokering för en array.

Det bör också noteras att strängsammansättningsoperatorn är helt associativ :det spelar ingen roll i vilken ordning vi sammanfogar strängar, så uttrycket s =a + (b + c), trots den uttryckligen angivna prioriteten för sammankopplingsexekveringen, ska behandlas enligt följande

s = (a + b) + c = string.Concat (a, b, c)

istället för det förväntade:

s = string.Concat (a, string.Concat (b, c))

Sammanfattning av det föregående:strängsammansättningsoperationen representeras alltid från vänster till höger och anropar den statiska String.Concat-metoden.

Optimera kompilatorn för bokstavliga strängar

C#-kompilatorn har optimeringar relaterade till bokstavliga strängar. Till exempel är uttrycket s ="a" + "b" + c, givet vänsterassociativiteten för "+"-operatorn, ekvivalent med s =("a" + "b") + c konverteras till

s = string.Concat ("ab", c)

Uttrycket s =c + "a" + "b", trots vänsterassociativiteten för sammankopplingsoperationen (s =(c + "a") + "b"), omvandlas till

s = string.Concat (c, "ab")

I allmänhet spelar inte bokstavernas position någon roll, kompilatorn sammanfogar allt den kan och försöker först därefter välja en lämplig överbelastning av Concat-metoden. Uttrycket s =a + "b" + "c" + d konverteras till

s = string.Concat (a, "bc", d)

Optimering associerad med tomma och NULL-strängar bör också nämnas. Kompilatorn vet att om du lägger till en tom sting inte påverkar resultatet av sammanlänkningen, så uttrycket s =a + “” + b konverteras till

s = string.Concat (a, b),

istället för det förväntade

s = string.Concat (a, "", b)

På liknande sätt, med const-strängen, vars värde är NULL, har vi:

const string nullStr = null;

s = a + nullStr + b;

konverteras till

s = string.Concat (a, b)

Uttrycket s =a + nullStr konverteras till s =a ?? "", om a är en sträng och anropet av strängen.Concat-metoden(a), om a inte är en sträng, till exempel, s =17 + nullStr, konverteras den till s =sträng.Concat (17) .

En intressant funktion förknippad med optimeringen av bokstavlig bearbetning och vänsterassociativiteten för strängoperatorn "+".

Låt oss överväga uttrycket:

var s1 = 17 + 17 + "abc";

Med tanke på vänsterassociativiteten är det likvärdigt med

var s1 = (17 + 17) + "abc"; // сalling the string.Concat method (34, "abc")

Som ett resultat, vid kompilering, läggs siffrorna till, så att resultatet blir 34abc.

Å andra sidan uttrycket

var s2 = "abc" + 17 + 17;

motsvarar

var s2 = ( "abc" + 17) + 17; // calling the string.Concat method ("abc", 17, 17)

resultatet blir abc1717.

Så där, samma sammanlänkningsoperator leder till olika resultat.

String.Concat VS StringBuilder.Append

Det är nödvändigt att säga några ord om denna jämförelse. Låt oss överväga följande kod:

string name = "Timur";

string surname = "Guev";

string patronymic = "Ahsarbecovich";

string fio = surname + name + patronymic;

Den kan ersättas med koden med StringBuilder:

var sb = new StringBuilder ();

sb.Append (surname);

sb.Append (name);

sb.Append (patronymic);

string fio = sb.ToString ();

Men i det här fallet kommer vi knappast att få fördelar av att använda StringBuilder. Förutom att koden har blivit mindre läsbar har den blivit mer eller mindre effektiv, eftersom implementeringen av Concat-metoden beräknar längden på den resulterande strängen och allokerar minne endast en gång, till skillnad från StringBuilder som inte vet något om längden av den resulterande strängen.

Implementering av Concat-metoden för 3 strängar:

public static string Concat (string str0, string str1, string str2)

{

if (str0 == null && str1 == null && str2 == null)

return string.Empty;

if (str0 == null)

str0 = string.Empty;

if (str1 == null)

str1 = string.Empty;

if (str2 == null)

str2 = string.Empty;

string dest = string.FastAllocateString (str0.Length + str1.Length + str2.Length); // Allocate memory for strings

string.FillStringChecked (dest, 0, str0); /

string.FillStringChecked (dest, str0.Length, str1);

string.FillStringChecked (dest, str0.Length + str1.Length, str2);

return dest;

}

Operator “+” i Java

Några ord om strängoperatorn "+" i Java. Även om jag inte programmerar i Java, är jag ändå intresserad av hur det fungerar där. Java-kompilatorn optimerar operatorn "+" så att den använder StringBuilder-klassen och anropar append-metoden.

Den tidigare koden konverteras till

String fio = new StringBuilder(String.valueOf(surname)).append(name).append (patronymic).ToString()

Det är värt att notera att de avsiktligt vägrade från sådan optimering i C#, Eric Lippert har ett inlägg om detta ämne. Poängen är att sådan optimering inte är optimeringen som sådan, det är kod omskrivning. Dessutom anser skaparna av C#-språket att utvecklare bör vara bekanta med aspekterna av att arbeta med String-klassen och, om nödvändigt, byta till StringBuilder.

Förresten, Eric Lippert var den som arbetade med optimering av C#-kompilatorn förknippad med sammanlänkning av strängar.

Slutsats

Kanske, vid första anblicken, kan det tyckas konstigt att String-klassen inte definierar operatorn "+" förrän vi tänker på kompilatorns optimeringskapacitet relaterad till synligheten av ett större kodfragment. Till exempel, om operatorn "+" definierades i klassen String, skulle uttrycket s =a + b + c + d leda till skapandet av två mellanliggande strängar, ett enda anrop av strängen.Concat (a, b, c, d) metoden gör det möjligt att utföra sammanlänkningen mer effektivt.


  1. Bulk infoga fält med fast bredd

  2. Hur man skapar en tabell med en främmande nyckel i SQL

  3. Ansluter PHP på Linux till Microsoft Access på en Windows-resurs

  4. Ansluter RazorSQL till Salesforce.com