Database
 sql >> Teknologi Basis Data >  >> RDS >> Database

Apakah operator string "+" begitu sederhana?

Pengantar

Tipe data string adalah salah satu tipe data fundamental, bersama dengan numerik (int, long, double) dan logis (Boolean). Anda hampir tidak dapat membayangkan setidaknya satu program berguna yang tidak menggunakan jenis ini.

Pada platform .NET, tipe string disajikan sebagai kelas String yang tidak dapat diubah. Selain itu, sangat terintegrasi ke dalam lingkungan CLR dan juga didukung oleh compiler C#.

Artikel ini dikhususkan untuk penggabungan – operasi yang dilakukan pada string sesering operasi penambahan pada angka. Anda mungkin berpikir:"Apa yang harus dikatakan?", Bagaimanapun, kita semua tahu tentang operator string "+", tetapi ternyata, ia memiliki kebiasaannya sendiri.

Spesifikasi bahasa untuk operator string “+”

Spesifikasi bahasa C# menyediakan tiga kelebihan beban untuk operator string “+”:

string operator + (string x, string y)

string operator + (string x, object y)

string operator + (object x, string y)

Jika salah satu operan rangkaian string adalah NULL, string kosong dimasukkan. Jika tidak, argumen apa pun, yang bukan string, direpresentasikan sebagai string dengan memanggil metode virtual ToString. Jika metode ToString mengembalikan NULL, string kosong dimasukkan. Perlu dicatat bahwa menurut spesifikasi, operasi ini tidak boleh mengembalikan NULL.

Deskripsi operator cukup jelas, namun jika kita melihat implementasi kelas String, kita menemukan definisi yang jelas dari hanya dua operator “==” dan “!=”. Sebuah pertanyaan yang masuk akal muncul:apa yang terjadi di balik layar rangkaian string? Bagaimana compiler menangani operator string “+”?

Jawaban atas pertanyaan ini ternyata tidak terlalu sulit. Mari kita lihat lebih dekat metode String.Concat statis. Metode String.Concat menggabungkan satu atau lebih instance dari kelas String atau dilihat sebagai nilai String dari satu atau lebih instance Object. Ada kelebihan berikut dari metode ini:

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)

Detail

Misalkan kita memiliki ekspresi berikut s =a + b, di mana a dan b adalah string. Kompiler mengubahnya menjadi panggilan metode statis Concat, yaitu

s = string.Concat (a, b)

Operasi penggabungan string, seperti operasi penjumlahan lainnya dalam bahasa C#, adalah asosiatif kiri.

Semuanya jelas dengan dua baris, tetapi bagaimana jika ada lebih banyak baris? Ekspresi s =a + b + c, diberikan asosiatif kiri dari operasi, dapat diganti dengan:

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

Namun, mengingat overloading yang membutuhkan tiga argumen, itu akan diubah menjadi:

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

Situasi yang sama adalah dengan rangkaian empat string. Untuk menggabungkan 5 string atau lebih, kami memiliki string.Concat overloading (params string[]), jadi perlu memperhitungkan overhead yang terkait dengan alokasi memori untuk sebuah array.

Perlu diperhatikan juga bahwa operator rangkaian string sepenuhnya asosiatif :tidak masalah dalam urutan mana kita menggabungkan string, jadi ekspresi s =a + (b + c), meskipun prioritas eksekusi rangkaian yang ditunjukkan secara eksplisit, akan diproses sebagai berikut

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

bukannya yang diharapkan:

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

Jadi, simpulkan hal di atas:operasi penggabungan string selalu direpresentasikan dari kiri ke kanan dan memanggil metode String.Concat statis.

Mengoptimalkan compiler untuk string literal

Kompiler C# memiliki pengoptimalan yang berkaitan dengan string literal. Misalnya, ekspresi s =“a” + “b” + c, diberikan asosiatif kiri dari operator “+”, sama dengan s =(“a” + “b”) + c diubah menjadi

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

Ekspresi s =c + “a” + “b”, terlepas dari asosiatif kiri dari operasi penggabungan (s =(c + “a”) + “b”) diubah menjadi

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

Secara umum, posisi literal tidak masalah, kompiler menggabungkan semua yang dia bisa, dan baru kemudian mencoba memilih kelebihan yang sesuai dari metode Concat. Ekspresi s =a + “b” + “c” + d diubah menjadi

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

Pengoptimalan yang terkait dengan string kosong dan NULL juga harus disebutkan. Kompilator mengetahui bahwa menambahkan sting kosong tidak mempengaruhi hasil penggabungan, sehingga ekspresi s =a + “” + b diubah menjadi

s = string.Concat (a, b),

bukannya yang diharapkan

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

Demikian pula, dengan string const, yang nilainya NULL, kita memiliki:

const string nullStr = null;

s = a + nullStr + b;

diubah menjadi

s = string.Concat (a, b)

Ekspresi s =a + nullStr diubah menjadi s =a ?? “”, jika a adalah string, dan pemanggilan string.Metode concat(a), jika a bukan string, misalnya, s =17 + nullStr, diubah menjadi s =string.Concat (17) .

Fitur menarik yang terkait dengan optimalisasi pemrosesan literal dan asosiasi kiri operator string “+”.

Mari kita perhatikan ekspresi:

var s1 = 17 + 17 + "abc";

dengan mempertimbangkan asosiatif kiri, ini setara dengan

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

Akibatnya, pada saat kompilasi, angka ditambahkan, sehingga hasilnya adalah 34abc.

Sebaliknya, ekspresi

var s2 = "abc" + 17 + 17;

setara dengan

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

hasilnya adalah abc1717.

Jadi, ini dia, operator penggabungan yang sama menghasilkan hasil yang berbeda.

String.Concat VS StringBuilder.Append

Ada beberapa hal yang perlu disampaikan tentang perbandingan ini. Mari kita perhatikan kode berikut:

string name = "Timur";

string surname = "Guev";

string patronymic = "Ahsarbecovich";

string fio = surname + name + patronymic;

Itu dapat diganti dengan kode menggunakan StringBuilder:

var sb = new StringBuilder ();

sb.Append (surname);

sb.Append (name);

sb.Append (patronymic);

string fio = sb.ToString ();

Namun, dalam kasus ini, kita hampir tidak akan mendapatkan manfaat dari penggunaan StringBuilder. Terlepas dari kenyataan bahwa kode menjadi kurang terbaca, itu menjadi lebih atau kurang efektif, karena penerapan metode Concat menghitung panjang string yang dihasilkan dan mengalokasikan memori hanya sekali, berbeda dengan StringBuilder yang tidak tahu apa-apa tentang panjangnya. dari string yang dihasilkan.

Implementasi metode Concat untuk 3 string:

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 “+” di Jawa

Beberapa kata tentang operator string “+” di Java. Meskipun saya tidak memprogram di Jawa, namun saya tertarik dengan cara kerjanya di sana. Kompiler Java mengoptimalkan operator “+” sehingga menggunakan kelas StringBuilder dan memanggil metode append.

Kode sebelumnya diubah menjadi

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

Perlu dicatat bahwa mereka dengan sengaja menolak pengoptimalan semacam itu di C#, Eric Lippert memiliki posting tentang topik ini. Intinya adalah bahwa optimasi tersebut bukanlah optimasi seperti itu, itu adalah penulisan ulang kode. Selain itu, pembuat bahasa C# percaya bahwa pengembang harus terbiasa dengan aspek bekerja dengan kelas String dan, jika perlu, beralih ke StringBuilder.

Ngomong-ngomong, Eric Lippert adalah orang yang mengerjakan pengoptimalan kompiler C# yang terkait dengan penggabungan string.

Kesimpulan

Mungkin, sepintas, mungkin tampak aneh bahwa kelas String tidak mendefinisikan operator “+” sampai kita memikirkan kapasitas pengoptimalan kompilator terkait dengan visibilitas fragmen kode yang lebih besar. Misalnya, jika operator “+” didefinisikan di kelas String, ekspresi s =a + b + c + d akan mengarah pada pembuatan dua string perantara, satu panggilan string. Concat (a, b, c, d) metode memungkinkan melakukan penggabungan lebih efektif.


  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Penguncian dan Performa

  2. Bersenang-senang dengan Fitur Postgres Baru Django

  3. Plan Explorer 3.0 Webinar – Contoh dan Tanya Jawab

  4. Cara Berkomentar di SQL

  5. Perbaikan Bug R2 2008 yang Merusak RCSI