sql >> Database teknologi >  >> RDS >> Database

Er strengoperator "+" så enkel?

Introduktion

En strengdatatype er en af ​​de grundlæggende datatyper sammen med numeriske (int, long, double) og logiske (booleske). Du kan næppe forestille dig mindst et nyttigt program, der ikke bruger denne type.

På .NET-platformen præsenteres strengtypen som en uforanderlig String-klasse. Derudover er den stærkt integreret i CLR-miljøet og understøttes også af C#-kompileren.

Denne artikel er viet til sammenkædning – en operation udført på strenge lige så ofte som additionsoperationen på tal. Du tænker måske:"Hvad er der at sige?", vi kender trods alt alle til strengoperatoren "+", men som det viste sig, har den sine egne særheder.

Sprogspecifikation for strengoperator "+"

C#-sprogspecifikationen giver tre overbelastninger for strengoperatoren "+":

string operator + (string x, string y)

string operator + (string x, object y)

string operator + (object x, string y)

Hvis en af ​​operanderne af strengsammenkædning er NULL, indsættes den tomme streng. Ellers bliver ethvert argument, som ikke er en streng, repræsenteret som en streng ved at kalde den virtuelle ToString-metode. Hvis ToString-metoden returnerer NULL, indsættes en tom streng. Det skal bemærkes, at ifølge specifikationen bør denne handling aldrig returnere NULL.

Beskrivelsen af ​​operatoren er klar nok, men hvis vi ser på implementeringen af ​​String-klassen, finder vi en klar definition af kun to operatorer "==" og "!=". Et rimeligt spørgsmål opstår:hvad sker der bag kulisserne ved sammenkædning af strenge? Hvordan håndterer compileren strengoperatoren "+"?

Svaret på dette spørgsmål viste sig ikke at være så svært. Lad os se nærmere på den statiske String.Concat-metode. String.Concat-metoden forbinder en eller flere forekomster af String-klassen eller -visninger som String-værdier for en eller flere forekomster af Object. Der er følgende overbelastninger af denne metode:

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

Antag, at vi har følgende udtryk s =a + b, hvor a og b er strenge. Compileren konverterer det til et kald af en Concat statisk metode, dvs.

s = string.Concat (a, b)

Stringsammenkædningsoperationen, som enhver anden tilføjelsesoperation i C#-sproget, er venstreassociativ.

Alt er klart med to rækker, men hvad hvis der er flere rækker? Udtrykket s =a + b + c, givet operationens venstre-associativitet, kunne erstattes af:

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

Men givet overbelastningen, der kræver tre argumenter, vil den blive konverteret til:

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

Den lignende situation er med sammenkædning af fire strenge. For at sammenkæde 5 eller flere strenge har vi strengen.Concat overbelastning (params streng[]), så det er nødvendigt at tage højde for den overhead, der er forbundet med hukommelsesallokering for et array.

Det skal også bemærkes, at strengsammenkædningsoperatoren er fuldt associativ :det er ligegyldigt, i hvilken rækkefølge vi sammenkæder strenge, så udtrykket s =a + (b + c), på trods af den eksplicit angivne prioritet for udførelse af sammenkædning, skal behandles som følger

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

i stedet for det forventede:

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

Som opsummerer det foregående:strengsammenkædningsoperationen er altid repræsenteret fra venstre mod højre og kalder den statiske String.Concat-metode.

Optimering af compiler til bogstavelige strenge

C#-kompileren har optimeringer relateret til bogstavelige strenge. For eksempel, udtrykket s ="a" + "b" + c, givet venstre-associativiteten af ​​"+" operatoren, svarer til s =("a" + "b") + c er konverteret til

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

Udtrykket s =c + "a" + "b", på trods af venstreassociativiteten af ​​sammenkædningsoperationen (s =(c + "a") + "b"), konverteres til

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

Generelt betyder placeringen af ​​bogstaverne ikke noget, compileren sammenkæder alt, hvad den kan, og prøver først derefter at vælge en passende overbelastning af Concat-metoden. Udtrykket s =a + "b" + "c" + d konverteres til

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

Optimeringer forbundet med tomme og NULL strenge bør også nævnes. Compileren ved, at tilføjelse af en tom brod ikke påvirker resultatet af sammenkædning, så udtrykket s =a + “” + b konverteres til

s = string.Concat (a, b),

i stedet for det forventede

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

På samme måde har vi med const-strengen, hvis værdi er NULL:

const string nullStr = null;

s = a + nullStr + b;

er konverteret til

s = string.Concat (a, b)

Udtrykket s =a + nullStr konverteres til s =a ?? "", hvis a er en streng, og kaldet af strengen.Concat-metode(a), hvis a ikke er en streng, f.eks. s =17 + nullStr, konverteres den til s =streng.Concat (17) .

En interessant funktion forbundet med optimering af bogstavelig behandling og venstreassociativiteten af ​​strengoperatoren "+".

Lad os overveje udtrykket:

var s1 = 17 + 17 + "abc";

taget venstre-associativiteten i betragtning, svarer det til

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

Som følge heraf tilføjes tallene på kompileringstidspunktet, så resultatet bliver 34abc.

På den anden side udtrykket

var s2 = "abc" + 17 + 17;

svarer til

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

resultatet bliver abc1717.

Så nå, den samme sammenkædningsoperator fører til forskellige resultater.

String.Concat VS StringBuilder.Append

Det er nødvendigt at sige et par ord om denne sammenligning. Lad os overveje følgende kode:

string name = "Timur";

string surname = "Guev";

string patronymic = "Ahsarbecovich";

string fio = surname + name + patronymic;

Den kan erstattes med koden ved hjælp af StringBuilder:

var sb = new StringBuilder ();

sb.Append (surname);

sb.Append (name);

sb.Append (patronymic);

string fio = sb.ToString ();

Men i dette tilfælde vil vi næppe få fordele ved at bruge StringBuilder. Udover at koden er blevet mindre læsbar, er den blevet mere eller mindre effektiv, da implementeringen af ​​Concat-metoden beregner længden af ​​den resulterende streng og tildeler hukommelse kun én gang, i modsætning til StringBuilder, der ikke ved noget om længden af den resulterende streng.

Implementering af Concat-metoden for 3 strenge:

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

Et par ord om strengoperator "+" i Java. Selvom jeg ikke programmerer i Java, er jeg alligevel interesseret i, hvordan det fungerer der. Java-kompileren optimerer "+"-operatoren, så den bruger StringBuilder-klassen og kalder append-metoden.

Den forrige kode er konverteret til

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

Det er værd at bemærke, at de med vilje nægtede en sådan optimering i C#, Eric Lippert har et indlæg om dette emne. Pointen er, at en sådan optimering ikke er optimeringen som sådan, det er kodeomskrivning. Desuden mener skaberne af C#-sproget, at udviklere bør være fortrolige med aspekterne ved at arbejde med String-klassen og om nødvendigt skifte til StringBuilder.

I øvrigt var Eric Lippert den, der arbejdede på optimering af C#-kompileren forbundet med sammenkædning af strenge.

Konklusion

Måske ved første øjekast kan det virke mærkeligt, at String-klassen ikke definerer operatoren "+", før vi tænker på optimeringskapaciteten af ​​compileren relateret til synligheden af ​​et større kodefragment. For eksempel, hvis "+"-operatoren blev defineret i String-klassen, ville udtrykket s =a + b + c + d føre til oprettelsen af ​​to mellemliggende strenge, et enkelt kald af strengen.Concat (a, b, c, d) metoden gør det muligt at udføre sammenkædningen mere effektivt.


  1. Docker PGMASTER PostgreSQL-versionsopdatering

  2. Hvor er Oracle Bug Database?

  3. Få forrige og næste række fra rækker valgt med (WHERE) betingelser

  4. Sammenfletning af sammenkædning af JSON(B)-kolonner i forespørgsel