Alasan di balik implementasi C # String.Split () yang tidak intuitif


10

Dalam C # jika saya ingin membagi stringdengan yang lain stringsaya harus melakukan sesuatu seperti itu:

testString.Split(new string[] { "anotherString" }, StringSplitOptions.None);

Dari String.SplitDokumentasi MSDN yang kelebihan beban kita bisa melihat implementasinya dan mengapa panggilan seperti itu harus dilakukan.

Berasal dari Python , Sulit bagi saya untuk memahami dengan benar mengapa panggilan seperti itu diperlukan. Maksud saya, saya dapat menggunakan Regex.Splituntuk mendapatkan sintaksis yang mirip dari implementasi Python tetapi saya harus melakukannya dengan biaya kinerja yang lebih rendah (waktu setup) untuk sesuatu yang sederhana .

Jadi pada dasarnya, pertanyaan saya adalah mengapa kita tidak bisa begitu saja:

testString.Split("anotherString");

Perhatikan bahwa saya tidak menyarankan prototipe atau implementasi apa pun. Saya mengerti mengapa Anda tidak dapat mengimplementasikan versi di atas mengingat API saat ini. Tujuan saya adalah untuk memahami mengapa API semacam itu dapat dibuat dengan mempertimbangkan manfaat yang dihasilkan oleh sintaks di atas. Sampai sekarang, fleksibilitas tampaknya menjadi tujuan arus String.Splityang masuk akal, tetapi jujur ​​saya benar-benar berpikir ada semacam peningkatan kinerja di suatu tempat. Saya kira saya salah.


3
Saya juga memikirkan hal ini. Spekulasi saya adalah bahwa mereka tidak berusaha keras untuk mendesain API yang satu ini. Dan jika mereka menyadari kesalahan mereka, sudah terlambat.
Euforia

@Caleth Bisakah Anda menguraikan ini. mungkin saya salah tetapi saya tidak melihat apa yang ambiugous tentang hal itu. Mengapa saya tidak bisa melakukan testString.Split(",.;");dan testString.Split(new Char [] {',', '.', ';',);itu bukan hal yang sama.
scharette

@ Euphoric Saya pikir juga begitu, tapi itu akan sangat aneh. Semoga seseorang datang dengan jawaban yang lebih logis.
scharette

Anda dapat beralih menggunakan string seperti IEnumerable<char>prototipe tambahan yang Anda sarankan mungkin tampak ambigu dalam kasus-kasus tertentu (apakah Anda membatasi seluruh string atau membatasi oleh masing-masing karakternya?) Hanya tebakan.
John Wu

@ JohnWu Mungkin itu adalah masalah pribadi, Tapi untuk 99,9% kemunculan sintaksis seperti testString.Split("anotherString");, saya cukup percaya diri untuk mengatakan bahwa perilaku yang diharapkan adalah membatasi seluruh string ( anotherStringdalam hal ini).
scharette

Jawaban:


15

Kadang-kadang membagi lebih dari satu karakter / string berguna, sehingga API memungkinkan Anda untuk menyediakan array, memberi Anda fleksibilitas maksimum. Dalam kasus chars, Anda mendapatkan kesederhanaan sintaksis dan fleksibilitas karena parameter ditandai paramssehingga Anda dapat menulis Split('x')daripada Split(new[]{'x'}).

Jadi mengapa tidak ada opsi serupa untuk string, yang memungkinkan Anda untuk menulis Split("x")?

Ini mungkin konsekuensi yang tidak menguntungkan dari bagaimana API dirancang. Awalnya hanya dibiarkan membelah karakter. Pemisahan pada string ditambahkan pada 2.0, mungkin karena lebih kompleks untuk diimplementasikan. Tetapi tidak mungkin untuk menambah String.Split(string)atau String.Split(string[])kelebihan, karena ini akan membuat ekspresi testString.Split(null)ambigu dan kode ini tidak dapat dikompilasi lagi.

testString.Split(null) sebenarnya idiom yang cukup umum karena memisahkan string pada spasi, sehingga kerusakan seperti itu akan terlalu luas untuk bisa diterima.

Menggunakan null-parameter sebagai saklar untuk perilaku khusus umumnya dianggap desain yang buruk akhir-akhir ini, jadi saya pikir wajar untuk mengatakan API ini hanya cacat.

Tidak ada Split(string[], Int32)baik, mungkin karena alasan yang sama - itu akan menjadi ambigu dengan Split(char[], Int32)jika parameter pertama adalah null. Ada yang overloads sama dengan StringSplitOptionsparameter, tapi ini semua ditambahkan pada waktu yang sama di 2.0, sehingga tidak ada ambiguitas diperkenalkan pada kode yang ada.

Catatan

Untuk lebih jelasnya, ini hanya hipotesis saya, saya tidak tahu pemikiran sebenarnya oleh desainer .net framework.


1
Nah, apakah itu berguna? Meragukan itu. Dan itu hanya API-break, bukan ABI.
Deduplicator

2
@Deduplicator: Split (null) terpecah pada whitespace, jadi ini mungkin salah satu kasus penggunaan yang paling umum untuk split, meskipun desain API yang buruk menggunakan null seperti ini.
JacquesB

1
Saya pikir @Dupuplikator ingin mengatakan itu Split(null)tidak berguna jika Anda mengizinkan Split(""). Selain fakta bahwa itu akan memungkinkan sintaksis yang lebih baik, yang terakhir lebih verbose ...
scharette

1
@scharette: Tentu, tetapi tidak mungkin untuk mengubah sekarang, tanpa merusak kompatibilitas ke belakang.
JacquesB

1
sebuah catatan: dengan pratinjau C # 8 saat ini, dengan mematikan jenis dasar nullability String.Split(null)tidak lagi ambigu, sehingga mereka dapat menambahkan kelebihan
BgrWorker

2

Tidak menjadi penulis metode, saya tidak tahu mengapa set overload dipilih. Namun, ada dua hal yang perlu diperhatikan di sini:

  1. Jika Anda membelah satu karakter, maka public string[] Split(params char[] separatorversi) dapat digunakan sebagai berikut:

    var splitValues = testString.Split(',');

    sebagai char[]adalah paramsparameter.

  2. Anda dapat dengan mudah menambahkan metode ekstensi Anda sendiri di sini untuk mencapai apa yang Anda inginkan:

    public static class StringExtensions
    {
        public static string[] Split(this string source, string separator)
            => source.Split(new string[] { separator }, StringSplitOptions.None);
    }
    

    dan sekarang testString.Split("anotherString");akan bekerja untuk Anda.


1
Terima kasih untuk umpan baliknya. Meskipun jawaban Anda bermanfaat dan singkat, saya tidak setuju dengan Anda. Terutama poin kedua. Bukankah ada satu lagi alasan untuk membuatnya built-in? Yang perlu dilakukan adalah membiarkan komunitas membuat versi berbeda dari metode yang diharapkan semua orang (atau hampir semua orang) berperilaku dengan cara yang sama.
scharette

Omong-omong, tidak mencoba berdebat, maksud Anda sepenuhnya valid. Hanya berusaha memahami alasan di balik ini. Logikanya pasti ada alasan historis atau kinerja ...
scharette

@scharette: Alasannya adalah membuat metode ini menjadi tujuan umum. Sebaiknya Anda menemukan tanda tangan metode yang Anda pilih, itu tidak akan berfungsi untuk beberapa pembatas. Versi Microsoft akan bekerja untuk beberapa pembatas serta pembatas tunggal Anda.
Robert Harvey

@RobertHarvey Baiklah tidak mungkin keduanya? Katakanlah metode ekstensi dalam jawaban di atas adalah bagian dari Stringkelas, keduanya mungkin. Apakah aku salah ?
scharette

Saya pikir Anda tidak mengerti intinya. Kelebihan Anda hanya memungkinkan satu pembatas. Kelebihan Microsoft memungkinkan lebih dari satu. Anda tidak dapat menelepon kelebihan Anda beberapa kali dan mencapai hasil yang sama; bukan itu cara kerjanya.
Robert Harvey

1

Bahasa yang berbeda memiliki aturan yang agak berbeda untuk konversi implisit dan kelebihan beban, dan .NET Framework dirancang untuk dapat digunakan dengan salah satu dari mereka. Dalam Option Strict Offdialek VB.NET, nilai tipe Stringdapat diteruskan ke fungsi yang mengharapkan Char[]perilaku dengan yang setara dengan memanggil ToCharArray()string.

Saya pikir hal yang masuk akal untuk dilakukan adalah memiliki nama yang terpisah untuk Split(yang menerima satu Charatau String) dan SplitMulti(yang akan menerima Char[]atau String[]), tetapi .NET kadang-kadang tampaknya lebih suka menggunakan kelebihan beban sendirian untuk memilih berbagai jenis operasi. Sayangnya, saya tahu tidak ada cara untuk menggunakan String.Splituntuk mengakomodasi setiap skenario penggunaan yang akan membutuhkan membedakan berbagai jenis pembatas selain dengan membelah secara terpisah pada masing-masing.

Kelalaian lain adalah opsi untuk mempertahankan pembatas, baik termasuk mereka di akhir string sebelumnya, atau pada awal string berikut, atau memiliki elemen array bernomor ganjil menjadi pembatas sementara elemen genap bernomor adalah hal-hal di antara mereka.


1
.NET kadang-kadang tampaknya lebih suka menggunakan kelebihan beban saja untuk memilih berbagai jenis operasi. Benar sekali ...
scharette
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.