Runtime: Memecah perubahan dengan string.IndexOf (string) dari .NET Core 3.0 -> .NET 5.0

Dibuat pada 22 Okt 2020  ·  76Komentar  ·  Sumber: dotnet/runtime

Deskripsi

Saya memperluas paket untuk mendukung .NET 5.0 dan mengalami perubahan yang merusak. Mengingat aplikasi konsol:

using System;

namespace ConsoleApp
{
    class Program
    {
        static void Main(string[] args)
        {
            var actual = "Detail of supported commands\n============\n## Documentation produced for DelegateDecompiler, version 0.28.0 on Thursday, 22 October 2020 16:03\n\r\nThis file documents what linq commands **DelegateDecompiler** supports when\r\nworking with [Entity Framework Core](https://docs.microsoft.com/en-us/ef/core/) (EF).\r\nEF has one of the best implementations for converting Linq `IQueryable<>` commands into database\r\naccess commands, in EF's case T-SQL. Therefore it is a good candidate for using in our tests.\r\n\r\nThis documentation was produced by compaired direct EF Linq queries against the same query implemented\r\nas a DelegateDecompiler's `Computed` properties. This produces a Supported/Not Supported flag\r\non each command type tested. Tests are groups and ordered to try and make finding things\r\neasier.\r\n\r\nSo, if you want to use DelegateDecompiler and are not sure whether the linq command\r\nyou want to use will work then clone this project and write your own tests.\r\n(See [How to add a test](HowToAddMoreTests.md) documentation on how to do this). \r\nIf there is a problem then please fork the repository and add your own tests. \r\nThat will make it much easier to diagnose your issue.\r\n\r\n*Note: The test suite has only recently been set up and has only a handful of tests at the moment.\r\nMore will appear as we move forward.*\r\n\r\n\r\n### Group: Unit Test Group\n#### [My Unit Test1](../TestGroup01UnitTestGroup/Test01MyUnitTest1):\n- Supported\n  * Good1 (line 1)\n  * Good2 (line 2)\n\r\n#### [My Unit Test2](../TestGroup01UnitTestGroup/Test01MyUnitTest2):\n- Supported\n  * Good1 (line 1)\n  * Good2 (line 2)\n\r\n\r\n\nThe End\n";

            var expected = "\n#### [My Unit Test2](";

            Console.WriteLine($"actual.Contains(expected): {actual.Contains(expected)}");
            Console.WriteLine($"actual.IndexOf(expected): {actual.IndexOf(expected)}");
        }
    }
}

Saya mendapatkan hasil yang berbeda berdasarkan runtime dari .NET Core 3.0 -> .NET 5.0:

.NET Core 3.0:

actual.Contains(expected): True
actual.IndexOf(expected): 1475

.NET 5.0:

actual.Contains(expected): True
actual.IndexOf(expected): -1

Konfigurasi

Windows 10 Pro Build 19041 x64
.NET Core 3.1.9
.NET 5.0.0-rc.2.20475.5

Regresi?

Ya, ini bekerja melalui .NET Core 3.1.9

area-System.Globalization question

Komentar yang paling membantu

@tarekgh , saya setuju bahwa hasil yang berbeda antara Contains dan IndexOf bukanlah masalahnya sendiri.

Masalahnya jelas IndexOf yang tidak dapat menemukan satu string khusus ASCII di dalam string khusus ASCII lainnya (saya tidak yakin pernah ada perilaku bergantung lokal yang dikenakan pada string khusus ASCII!).

Ini bukanlah sesuatu yang saya harapkan dari perubahan lokal / NLS / ICU; sebenarnya, saya tidak bisa memikirkan bahasa pemrograman / runtime lain yang berperilaku seperti itu.

Berikut kasus uji yang disederhanakan, rusak (maksud saya, memberi saya hasil yang sama sekali tidak terduga) di .NET 5 RC 2:

var actual = "\n\r\nTest";
var expected = "\nTest";

Console.WriteLine($"actual.IndexOf(expected): {actual.IndexOf(expected)}"); // => -1

Haruskah itu benar-benar berfungsi seperti itu? Juga kenapa? Apa sebenarnya yang coba dilakukannya?

Apakah itu benar-benar perubahan yang direncanakan?

Ya, beralih ke ICU adalah perubahan yang disengaja karena berbagai alasan.

Saya minta maaf, tapi saya tidak percaya ini adalah perubahan yang direncanakan, jadi saya ingin menekankan: Saya tidak dapat membayangkan ada orang _planning_ perubahan seperti itu. Seperti, orang-orang dari tim .NET duduk bersama dan berdiskusi:

Apakah string "\ n \ r \ nTest" berisi "\ nTest" dengan ICU diaktifkan? Tidak, jelas tidak!

Dan tidak ada yang mengeluh? Tidak mungkin!

Ini tidak terlihat seperti perubahan yang direncanakan atau diharapkan, dan malah terlihat seperti bug yang sangat serius, pemblokir kompatibilitas yang besar. Karena itu, aplikasi .NET baru dan porting tidak akan berfungsi dengan baik pada runtime baru, karena mereka tidak akan dapat menemukan substring di dalam string!

Mengapa ICU peduli dengan akhiran baris? Apakah beberapa lokal memiliki akhiran baris khusus lokalnya sendiri?

NB Ya, Anda dapat berargumen bahwa seseorang harus selalu memanggil beberapa varian dari budaya-independen IndexOf , seperti dengan bendera ordinal. Tetapi, jika Anda telah memutuskan untuk memecahnya _that_ keras di .NET 5, tidak bisakah Anda membuatnya menggunakan default ordinal yang waras? Saya pikir itu akan merusak aplikasi lebih sedikit daripada perubahan saat ini yang kita lihat di .NET 5 RC 2.

Juga, saya pikir kita semua mengerti bahwa, meskipun IndexOf selalu berperilaku dengan cara khusus budaya, ada _tons_ kode di alam liar yang menggunakan IndexOf tanpa bendera ordinal, dan kode itu _digunakan untuk bekerja_ (setidaknya dalam beberapa / kebanyakan kasus). Dan itu akan berhenti berfungsi setelah pembaruan .NET 5.

Semua 76 komentar

@tokopedia

Memberi tag pelanggan ke area ini: @tarekgh , @safern , @krwq
Lihat info di area-owners.md jika Anda ingin berlangganan.

Ini dengan desain seperti pada .NET 5.0 kami telah beralih menggunakan ICU daripada NLS. Anda dapat melihat di https://docs.microsoft.com/en-us/dotnet/standard/globalization-localization/globalization-icu untuk lebih jelasnya.

Anda memiliki opsi untuk menggunakan sakelar konfigurasi System.Globalization.UseNls untuk kembali ke perilaku lama tetapi kami tidak menyarankan melakukannya karena ICU lebih tepat dan menggunakan ICU akan memberikan konsistensi di seluruh OS.

lupa mengatakan, jika Anda ingin IndexOf berperilaku sebagai Contains , Anda harus menggunakan perbandingan Ordinal pada saat itu.

C# actual.IndexOf(expected, StringComparison.Ordinal)

Anda memiliki opsi untuk menggunakan sakelar konfigurasi System.Globalization.UseNls untuk kembali ke perilaku lama tetapi kami tidak menyarankan melakukan itu karena ICU lebih tepat dan bergerak maju menggunakan ICU akan memberikan konsistensi di seluruh OS.

Ya, jika Anda menjalankan kode ini di Unix yang menargetkan netcoreapp3.1 Anda akan melihat perilaku yang sama:

 santifdezm  DESKTOP-1J7TFMI  ~  experimental  indexof  $   /home/santifdezm/experimental/indexof/bin/Debug/netcoreapp3.1/linux-x64/publish/indexof
actual.Contains(expected): True
actual.IndexOf(expected): -1

dan sebagai @tarekgh dengan Ordinal perbandingan itu mengembalikan hasil yang diharapkan.

 santifdezm  DESKTOP-1J7TFMI  ~  experimental  indexof  $  /home/santifdezm/experimental/indexof/bin/Debug/net5.0/linux-x64/publish/indexof
actual.Contains(expected): True
actual.IndexOf(expected): 1475

Saya pikir ini gagal karena campuran \r\n dan \n dalam string sumber. Jika saya mengganti semua contoh \r\n dengan \n itu berfungsi. Hal yang sama juga berlaku jika saya menghasilkan semuanya \r\n . Hanya perpaduan tersebut yang menghasilkan hasil yang berbeda dari perbandingan di ICU.

Masalah seperti yang dilaporkan di Twitter adalah bahwa dalam runtime 5.0, panggilan berulang ke string.IndexOf dengan input yang sama memberikan hasil yang berbeda pada setiap panggilan.

https://twitter.com/jbogard/status/1319381273585061890?s=21

Edit: Di atas adalah kesalahpahaman.

@GrabYourPitchforks, bisakah kita memperbarui judul terbitan? Karena ini teknis perubahan yang merusak, tetapi ini terjadi pada Windows dan Unix ... bukan?

Saya ping Jimmy offline untuk klarifikasi. Mungkin saja saya salah memahami laporan terbitan aslinya. Forum 280-karakter tidak selalu efisien dalam mengkomunikasikan bug dengan jelas. ;)

Hanya untuk memperjelas, Contains API sedang melakukan operasi ordinal. IndexOf tanpa tanda perbandingan string adalah operasi linguistik dan bukan ordinal. Jika ingin membandingkan perilaku Contains dengan IndexOf, perlu menggunakan IndexOf(expected, StringComparison.Ordinal) .
Jika perlu mempelajari lebih lanjut tentang perbedaannya, https://docs.microsoft.com/en-us/dotnet/csharp/how-to/compare-strings adalah tautan yang berguna.

Saya menerima klarifikasi di Twitter. Aplikasi tidak memanggil IndexOf dalam satu lingkaran. Ini hanyalah laporan perbedaan perilaku standar 3.0 vs. 5.0.

@GrabYourPitchforks dapatkah Anda membagikan tautan https://docs.microsoft.com/en-us/dotnet/standard/globalization-localization/globalization-icu pada balasan twitter Anda dan menyebutkan bahwa kami memiliki tombol konfigurasi untuk kembali ke perilaku lama?

Saya menerima klarifikasi di Twitter. Aplikasi tidak memanggil IndexOf dalam satu lingkaran. Ini hanyalah laporan perbedaan perilaku standar 3.0 vs. 5.0.

Terima kasih, @GrabYourPitchforks ... berdasarkan ini, menutupnya sesuai desain.

Untuk menambahkan lebih banyak di sini, jika Anda ingin mendapatkan perilaku lama tanpa beralih kembali ke NLS, Anda dapat melakukannya

`` C #
CultureInfo.CurrentCulture.CompareInfo.IndexOf (aktual, diharapkan, CompareOptions.IgnoreSymbols)


or 

```C#
    actual.IndexOf(expected, StringComparison.Ordinal)

dari pada

C# actual.IndexOf(expected)

dan Anda harus mendapatkan perilaku yang diinginkan.

Saya tidak dapat melihat apa pun tentang \r\n vs \n dalam dokumentasi terkait ICU yang tertaut (https://docs.microsoft.com/en-us/dotnet/standard/globalization-localization/ globalisasi-icu).

Apakah itu benar-benar perubahan yang direncanakan?

@ForNeVeR akan sulit untuk membuat daftar setiap perbedaan antara ICU dan NLS. dokumen tersebut berbicara tentang perubahan utama dari peralihan ke ICU. Seperti yang saya tunjukkan sebelumnya, tidak benar membandingkan hasil Contains dengan IndexOf tanpa parameter Perbandingan String. Saya telah mencantumkan di atas beberapa cara Anda bisa mendapatkan perilaku sebelumnya jika diinginkan. Dari laporan masalah ini, menurut saya penggunaan IndexOf harus menggunakan opsi Ordinal dan tidak benar menggunakan perbandingan linguistik dalam kasus seperti itu. Penggunaan perbandingan linguistik dalam kasus seperti ini dapat bergantung pada budaya saat ini yang memungkinkan untuk memberikan hasil yang berbeda pada lingkungan yang berbeda.

Apakah itu benar-benar perubahan yang direncanakan?

Ya, beralih ke ICU adalah perubahan yang disengaja karena berbagai alasan. Windows saat ini mempromosikan menggunakan ICU melalui NLS. ICU adalah masa depan. Selain itu, ICU akan memberikan kesempatan untuk memiliki perilaku yang konsisten di seluruh Windows / Linux / OSX atau platform yang didukung. Menggunakan ICU akan memberikan kesempatan kepada aplikasi untuk menyesuaikan perilaku globalisasi jika diinginkan.

Seperti yang ditunjukkan dokumen, Anda masih memiliki opsi untuk beralih kembali ke perilaku lama jika Anda mau.

Aduh, dokumen yang dirujuk mengatakan bahwa perilaku ICU / NLS di Windows mungkin diam-diam beralih berdasarkan ketersediaan icu.dll di lingkungan sebenarnya. Ini mungkin kejutan besar untuk aplikasi mandiri yang dipublikasikan. Saya berharap .NET mengirimkan ICU untuk mengatasi masalah ini jika sakelar diputuskan, dan karena ICU tidak tersedia di semua lingkungan target. Ketergantungan runtime opsional ini membuat segalanya menjadi lebih lucu.

Saya berharap .NET mengirimkan ICU untuk mengatasi masalah ini jika sakelar diputuskan, dan karena ICU tidak tersedia di semua lingkungan target. Ketergantungan runtime opsional ini membuat segalanya menjadi lebih lucu.

ICU sekarang diterbitkan sebagai paket NuGet. Aplikasi dapat menggunakan paket tersebut agar aplikasi mandiri memastikan memiliki ICU. lihat bagian app-local di dokumen . Singkatnya, aplikasi memiliki kendali penuh atas perilaku yang ingin diperoleh.

@tarekgh , saya setuju bahwa hasil yang berbeda antara Contains dan IndexOf bukanlah masalahnya sendiri.

Masalahnya jelas IndexOf yang tidak dapat menemukan satu string khusus ASCII di dalam string khusus ASCII lainnya (saya tidak yakin pernah ada perilaku bergantung lokal yang dikenakan pada string khusus ASCII!).

Ini bukanlah sesuatu yang saya harapkan dari perubahan lokal / NLS / ICU; sebenarnya, saya tidak bisa memikirkan bahasa pemrograman / runtime lain yang berperilaku seperti itu.

Berikut kasus uji yang disederhanakan, rusak (maksud saya, memberi saya hasil yang sama sekali tidak terduga) di .NET 5 RC 2:

var actual = "\n\r\nTest";
var expected = "\nTest";

Console.WriteLine($"actual.IndexOf(expected): {actual.IndexOf(expected)}"); // => -1

Haruskah itu benar-benar berfungsi seperti itu? Juga kenapa? Apa sebenarnya yang coba dilakukannya?

Apakah itu benar-benar perubahan yang direncanakan?

Ya, beralih ke ICU adalah perubahan yang disengaja karena berbagai alasan.

Saya minta maaf, tapi saya tidak percaya ini adalah perubahan yang direncanakan, jadi saya ingin menekankan: Saya tidak dapat membayangkan ada orang _planning_ perubahan seperti itu. Seperti, orang-orang dari tim .NET duduk bersama dan berdiskusi:

Apakah string "\ n \ r \ nTest" berisi "\ nTest" dengan ICU diaktifkan? Tidak, jelas tidak!

Dan tidak ada yang mengeluh? Tidak mungkin!

Ini tidak terlihat seperti perubahan yang direncanakan atau diharapkan, dan malah terlihat seperti bug yang sangat serius, pemblokir kompatibilitas yang besar. Karena itu, aplikasi .NET baru dan porting tidak akan berfungsi dengan baik pada runtime baru, karena mereka tidak akan dapat menemukan substring di dalam string!

Mengapa ICU peduli dengan akhiran baris? Apakah beberapa lokal memiliki akhiran baris khusus lokalnya sendiri?

NB Ya, Anda dapat berargumen bahwa seseorang harus selalu memanggil beberapa varian dari budaya-independen IndexOf , seperti dengan bendera ordinal. Tetapi, jika Anda telah memutuskan untuk memecahnya _that_ keras di .NET 5, tidak bisakah Anda membuatnya menggunakan default ordinal yang waras? Saya pikir itu akan merusak aplikasi lebih sedikit daripada perubahan saat ini yang kita lihat di .NET 5 RC 2.

Juga, saya pikir kita semua mengerti bahwa, meskipun IndexOf selalu berperilaku dengan cara khusus budaya, ada _tons_ kode di alam liar yang menggunakan IndexOf tanpa bendera ordinal, dan kode itu _digunakan untuk bekerja_ (setidaknya dalam beberapa / kebanyakan kasus). Dan itu akan berhenti berfungsi setelah pembaruan .NET 5.

Masalahnya jelas IndexOf yang tidak dapat menemukan satu string khusus ASCII di dalam string khusus ASCII lainnya (saya tidak yakin pernah ada perilaku bergantung lokal yang dikenakan pada string khusus ASCII!).

Tidak benar bahwa ASCII tidak bergantung pada lokal. lihat tautan http://userguide.icu-project.org/collation/concepts sebagai contoh bagaimana perilaku karakter ASCII dapat berbeda untuk budaya yang berbeda.

For example, in the traditional Spanish sorting order, "ch" is considered a single letter. All words that begin with "ch" sort after all other words beginning with "c", but before words starting with "d".
Other examples of contractions are "ch" in Czech, which sorts after "h", and "lj" and "nj" in Croatian and Latin Serbian, which sort after "l" and "n" respectively.

Juga, saya ingin menjelaskan bahwa ICU mengambil data dan perilakunya dari Unicode Standard yang dipikirkan dengan baik oleh banyak ahli. @GrabYourPitchforks akan memposting lebih banyak detail tentang \r\n\ case yang kita bicarakan di sini. tetapi sementara itu, Anda dapat membiasakan diri dengan dokumen https://unicode.org/reports/tr29/ terutama di bagian yang menyebutkan berikut ini:

Do not break between a CR and LF. Otherwise, break before and after controls.
--
GB3 | CR | × | LF
GB4 | (Control \| CR \| LF) | ÷ |  
GB5 |   | ÷ | (Control \| CR \| LF)

Mengapa ICU peduli dengan akhiran baris? Apakah beberapa lokal memiliki akhiran baris khusus lokalnya sendiri?

Ini dibahas di paragraf terakhir.

Saya minta maaf, tetapi saya tidak percaya ini adalah perubahan yang direncanakan, jadi saya ingin menekankan: Saya tidak dapat membayangkan ada orang yang merencanakan perubahan seperti itu. Seperti, orang-orang dari tim .NET duduk bersama dan berdiskusi:
Ini tidak terlihat seperti perubahan yang direncanakan atau diharapkan, dan malah terlihat seperti bug yang sangat serius, pemblokir kompatibilitas yang besar. Karena itu, aplikasi .NET baru dan porting tidak akan berfungsi dengan baik pada runtime baru, karena mereka tidak akan dapat menemukan substring di dalam string!

Ini direncanakan bekerja dengan baik dan dipikirkan secara mendalam di dalamnya. Anda dapat melihat masalah https://github.com/dotnet/runtime/issues/826 yang telah kami publikasikan sejak lama dan membagikannya secara publik.
Saya juga ingin menekankan bahwa perilaku globalisasi dapat berubah kapan saja tidak hanya untuk .NET tetapi juga untuk OS dan platform lainnya. Ini juga alasan mengapa kami mendukung fitur lokal aplikasi ICU untuk mengizinkan aplikasi menggunakan versi ICU tertentu untuk memastikan perilaku yang mereka gunakan tidak akan berubah. Hal lain, Windows sendiri sedang dalam proses mempromosikan menggunakan ICU dan suatu hari perilaku ICU akan menjadi apa yang akan digunakan oleh mayoritas pengguna.

seperti dengan bendera ordinal. Tetapi, jika Anda telah memutuskan untuk memecahnya sekeras itu di .NET 5, tidak bisakah Anda membuatnya menggunakan default ordinal yang waras? Saya pikir itu akan merusak aplikasi lebih sedikit daripada perubahan saat ini yang kita lihat di .NET 5 RC 2.

Sebenarnya kami telah mencoba sebelumnya untuk menjadikan perilaku Ordinal sebagai default sebelumnya selama rilis Silverlight dan itu menyebabkan lebih banyak masalah daripada yang dilaporkan di sini. Kami mencari lebih banyak cara untuk membantu para pengembang agar sadar ketika memanggil sesuatu seperti IndexOf dan dengan sengaja menyediakan flag Perbandingan String untuk mengekspresikan maksudnya. Kami menyambut baik ide apa pun yang mungkin Anda keluarkan juga.

Juga, saya pikir kita semua memahami bahwa, meskipun IndexOf selalu berperilaku dengan cara khusus budaya, ada banyak kode di alam liar yang menggunakan IndexOf tanpa bendera ordinal, dan kode itu dulu berfungsi (dalam beberapa / kebanyakan kasus, setidaknya). Dan itu akan berhenti berfungsi setelah pembaruan .NET 5.

Itulah mengapa kami menyediakan tombol konfigurasi untuk beralih kembali ke perilaku lama jika Anda menginginkannya juga. lihat System.Globalization.UseNls

@tarekgh , terima kasih atas penjelasan

Untuk saat ini, saya pikir lebih baik saya menunggu detail tentang perilaku \r\n . Tidak jelas bagi saya bagaimana IndexOf menggunakan "Aturan Batas Klaster Grapheme" (dan apakah harus melakukannya) saat melakukan pencarian khusus ini).

Juga, bahkan jika spesifikasi Unicode relevan di sini (yang mungkin saja!), Dari membaca https://unicode.org/reports/tr29/ , saya tidak yakin itu melarang untuk mencocokkan \n . Saat saya membaca spesifikasi, dikatakan CR | × | LF , di mana × berarti "Tidak ada batasan (jangan izinkan istirahat di sini)". Jadi, ketika melanggar urutan \r\n\n , itu hanya melarang menempatkan "istirahat" antara karakter pertama dan kedua, tapi seharusnya tidak masalah untuk menempatkan "istirahat" sebelum yang ketiga, bukan? Jadi, saya membaca \r\n\n sebagai dua "kelompok grafem" yang terpisah, dan, meskipun IndexOf harus hanya mencocokkan cluster grafem penuh dan tidak pernah menyentuh bagian dari cluster, itu masih akan menemukan substring \nTest di dalam string \n\r\nTest .

Juga, apakah Anda memberi tahu bahwa runtime / bahasa pemrograman lain yang mengandalkan ICU dan / atau spesifikasi Unicode harus berperilaku sama dengan contoh khusus ini?

Kami mencari lebih banyak cara untuk membantu para pengembang agar sadar ketika memanggil sesuatu seperti IndexOf dan dengan sengaja menyediakan flag Perbandingan String untuk mengekspresikan maksudnya. Kami menyambut baik ide apa pun yang mungkin Anda keluarkan juga.

_ ( Penafian yang diperlukan: Saya bekerja untuk JetBrains pada beberapa proyek, termasuk ReSharper.) _

Awalnya saya tidak ingin membawa poin ini ke sini agar tidak terdengar seperti iklan, tapi saya rasa ini sangat relevan, jadi saya harus melakukannya. ReSharper secara default akan menampilkan peringatan berikut untuk kode pengguna yang memanggil IndexOf :
image

_ (harap diperhatikan bahwa saya tidak mengetahui diagnosis ReSharper ini sebelum terlibat dalam utas ini, jadi saya tidak berpartisipasi di sini hanya untuk menyampaikan argumen ini) _

Jadi, saya pikir akan menjadi ide yang sangat baik untuk menampilkan pemberitahuan seperti itu secara default di setiap alat lain, juga, atau bahkan mungkin sama sekali tidak menggunakan metode palsu ini dengan pemberitahuan seperti itu.

@Bayu_joo

Selain itu, meskipun spesifikasi Unicode relevan di sini (yang mungkin saja!), Dari membaca unicode.org/reports/tr29, saya tidak yakin itu melarang untuk mencocokkan yang terakhir \ n. Saat saya membaca spesifikasinya, tertulis CR | × | LF, di mana × berarti "Tanpa batas (jangan biarkan putus di sini)". Jadi, saat memutus urutan \ r \ n \ n, itu hanya melarang menempatkan "istirahat" antara karakter pertama dan kedua, tapi seharusnya tidak masalah untuk menempatkan "istirahat" sebelum yang ketiga, bukan? Jadi, saya membaca \ r \ n \ n sebagai dua "kelompok grafem" yang terpisah

Itu betul. \r\n\n akan menjadi 2 cluster sebagai \r\n dan \n .

dan, bahkan jika IndexOf harus hanya mencocokkan cluster grafem penuh dan tidak pernah menyentuh bagian cluster, ia masih akan menemukan substring \ nUji di dalam string \ n \ r \ nTest.

Itu tidak benar. \n\r\nTest akan dibagi menjadi beberapa bagian. \n , \r\n , dan Test . jelas \nTest tidak bisa menjadi bagian dari string ini. pikirkan tentang mengganti cluster \r\n dengan beberapa simbol X . sekarang string sumber akan menjadi \nXTest yang tidak berisi \nTest .

Juga, apakah Anda memberi tahu bahwa runtime / bahasa pemrograman lain yang mengandalkan ICU dan / atau spesifikasi Unicode harus berperilaku sama dengan contoh khusus ini?

jika menggunakan tingkat kekuatan susunan default, maka jawabannya adalah ya. ICU dapat memungkinkan perubahan tingkat kekuatan yang dapat mempengaruhi hasil. Misalnya, seperti yang saya sebutkan sebelumnya, melakukan sesuatu seperti:

CultureInfo.CurrentCulture.CompareInfo.IndexOf(actual, expected, CompareOptions.IgnoreSymbols)

akan mengubah tingkat kekuatan dan akan membuat operasi mengabaikan simbol (yang akan mengubah perilaku \n dan \r karena akan diabaikan pada saat itu)

Juga, saya telah menulis aplikasi C asli ICU murni dan menjalankan kasus yang sama:

void SearchString(const char *target, int32_t targetLength, const char *source, int32_t sourceLength)
{
    static UChar usource[100];
    static UChar utarget[100];

    u_charsToUChars(source, usource, sourceLength);
    u_charsToUChars(target, utarget, targetLength);

    UErrorCode status = U_ZERO_ERROR;
    UStringSearch* pSearcher = usearch_open(utarget, targetLength, usource, sourceLength, "en_US", nullptr, &status);
    if (!U_SUCCESS(status))
    {
        printf("usearch_open failed with %d\n", status);
        return;
    }

    int32_t index = usearch_next(pSearcher, &status);
    if (!U_SUCCESS(status))
    {
        printf("usearch_next failed with %d\n", status);
        return;
    }

    printf("search result = %d\n", index);
    usearch_close(pSearcher);
}


int main()
{
    SearchString("\nT", 2, "\r\nT", 3);
    SearchString("\nT", 2, "\n\nT", 3);
}

aplikasi ini akan menampilkan hasil:

search result = -1
search result = 1

yang identik dengan perilaku yang Anda lihat dengan .NET.

Untuk saat ini, saya pikir lebih baik saya menunggu detail tentang perilaku \ r \ n khusus ini. Tidak jelas bagi saya bagaimana IndexOf menggunakan "Aturan Batas Klaster Grapheme" (dan apakah harus melakukan itu) saat melakukan pencarian khusus ini).

Untuk memastikan pengelompokan mempengaruhi operasi pemeriksaan. Jika Anda melihat http://unicode.org/reports/tr29/tr29-7.html , dengan jelas dinyatakan sebagai berikut:

Grapheme clusters include, but are not limited to, combining character sequences such as (g + °), digraphs such as Slovak “ch”, and sequences with letter modifiers such as kw. Batas cluster grafem penting untuk pemeriksaan , regular-expressions, and counting “character” positions within text. Word boundaries, line boundaries and sentence boundaries do not occur within a grapheme cluster. In this section, the Unicode Standard provides a determination of where the default grapheme boundaries fall in a string of characters. This algorithm can be tailored for specific locales or other customizations, which is what is done in providing contracting characters in collation tailoring tables.

Saya tidak yakin apakah akan ada detail lebih lanjut tetapi saya akan membiarkan @GrabYourPitchforks berkomentar jika dia memiliki lebih banyak untuk ditambahkan di sini.

Jadi, saya pikir akan menjadi ide yang sangat baik untuk menampilkan pemberitahuan seperti itu secara default di setiap alat lain, juga, atau bahkan mungkin sama sekali tidak menggunakan metode palsu ini dengan pemberitahuan seperti itu.

Terima kasih!
Ini adalah arah yang sama yang kita pikirkan juga.

Demi kepentingan saya sendiri, saya membandingkan berbagai kelebihan beban antar versi:

| Metode | netcoreapp3.1 | net5.0 |
| ------------------------------------------------- --------------- | ----------------- | ---------- |
| actual.Contains(expected) | Benar | Benar |
| actual.IndexOf(expected) | 1475 | -1 |
| actual.Contains(expected, StringComparison.CurrentCulture) | Benar | Salah |
| actual.IndexOf(expected, StringComparison.CurrentCulture) | 1475 | -1 |
| actual.Contains(expected, StringComparison.Ordinal) | Benar | Benar |
| actual.IndexOf(expected, StringComparison.Ordinal) | 1475 | 1475 |
| actual.Contains(expected, StringComparison.InvariantCulture) | Benar | Salah |
| actual.IndexOf(expected, StringComparison.InvariantCulture) | 1475 | -1 |

Harap sertakan penganalisis untuk ini.

Ini sepertinya salah satu perubahan yang, meskipun bagus dalam jangka panjang, sekaligus membuat sejumlah besar churn setelah .NET 5 diluncurkan. Jadi jika perilaku metode ini berbeda antara .NET 5 dan .NET Core 3.1, apa yang akan terjadi ketika .NET 5 memanggil objek yang ditentukan di dalam pustaka .NET Standard 2.0 yang memanipulasi string diteruskan ke dalamnya dari situs panggilan .NET? Apakah perilaku lama digunakan atau perilaku baru?

@Aaronontheb perilaku baru. Saya melihat ini awalnya dari pernyataan di NUnit3, yang menargetkan netstandard2.0 . Setelah meningkatkan, pengujian saya mulai gagal ketika saya hanya mengubah kerangka target.

Itu tidak bagus - tidak dapat mengontrol perpustakaan lama yang saya rujuk jika saya ingin meningkatkan.

Berapa banyak aplikasi yang tidak akan mendeteksinya dalam pengujian unit dan memasukkannya ke dalam produksi?
Apakah tim .NET mempertimbangkan rasa sakit dan masalah serta biaya yang dapat ditimbulkan?

Itu tidak bagus - tidak dapat mengontrol perpustakaan lama yang saya rujuk jika saya ingin meningkatkan.

Perangkap yang bagus!
senang membuang waktu dengan berburu serangga aneh 🎉
tetapi mengapa InvariantGlobalization tidak membantu mengatasi masalah ini?

Harap sertakan penganalisis untuk ini.

Ya. Dan jangan lupa dukungan F #.

Berapa banyak aplikasi yang tidak akan mendeteksinya dalam pengujian unit

Zero - karena pengujian unit tidak dimaksudkan untuk menguji libs / framework eksternal seperti .NET BCL itu sendiri.

Pandangan saya adalah bahwa harus ada Atribut tingkat Majelis yang dapat mengontrol mode perubahan perilaku ini. Setidaknya, Anda dapat memilih untuk ikut / keluar di tingkat per perakitan. Ini kemudian berarti bahwa masalah .NET Standard juga hilang.

Itu tidak bagus - tidak dapat mengontrol perpustakaan lama yang saya rujuk jika saya ingin meningkatkan.

Saya tidak mengerti mengapa Anda tidak bisa mengendalikannya. Semua perbandingan string menggunakan ICU atau NLS. Anda dapat memilih keluar dari ICU menggunakan saklar compat jika Anda mau, dan semua perpustakaan Anda akan kembali ke perilaku lama.

Anda tidak dapat mengandalkan data globalisasi agar tetap stabil dari waktu ke waktu. Ambil contoh dari tim Windows bahwa mereka tidak takut menghancurkan orang-orang yang bergantung pada data globalisasi yang stabil. Fungsi globalisasi harus menjadi kotak hitam; Saya rasa tidak masuk akal bagi perpustakaan (terutama yang menargetkan .NET Standard) untuk mengatakan bahwa mereka bergantung pada detail implementasi seperti ini.

Saya yakin bahwa sama seperti banyak orang yang mengeluh tentang fungsi globalisasi .NET yang mengembalikan hasil berbeda pada Windows vs. Linux (dan bahkan mungkin lebih banyak orang belum menyadarinya). Lebih baik menyatukan perilaku antara Windows dan platform lain, dan kode yang benar tidak boleh mengandalkan data globalisasi yang tidak dapat diubah, apa pun.

Apakah Anda akan mempertimbangkan untuk membuat perubahan besar agar StringComparison.Ordinal menjadi strategi perbandingan default? Melihat globalisasi begitu tidak stabil, masuk akal bahwa setidaknya implementasi default menggunakan algoritme yang stabil. Saya berani bertaruh bahwa 99,9% orang yang menggunakan string.Equals(...) atau string.Contains(...) dll. Tanpa melewati StringComparison tidak melakukannya dengan maksud eksplisit menangani kebiasaan aneh yang terkait dengan lokal.

Edit: Saya kira pertanyaan saya sudah dijawab:

Sebenarnya kami telah mencoba sebelumnya untuk menjadikan perilaku Ordinal sebagai default sebelumnya selama rilis Silverlight dan itu menyebabkan lebih banyak masalah daripada yang dilaporkan di sini. Kami mencari lebih banyak cara untuk membantu para pengembang agar sadar saat memanggil sesuatu seperti IndexOf dan dengan sengaja memberikan tanda Perbandingan String untuk menyatakan maksudnya. Kami menyambut baik ide apa pun yang mungkin Anda keluarkan juga.

Anda dapat memilih keluar dari ICU menggunakan saklar compat jika Anda mau, dan semua perpustakaan Anda akan kembali ke perilaku lama.

Saya membuat perpustakaan untuk mencari nafkah, bukan aplikasi. Saya lebih suka memiliki cara waktu kompilasi untuk menangani ini.

Sebagian besar pekerjaan yang kami lakukan adalah InvariantCulture , yang menurut pemahaman saya sebelumnya seharusnya tidak dapat diubah oleh desain. Sepertinya perilaku IndexOf berbeda antara .NET 5.0 dan .NET Core 3.1 dalam keadaan itu juga.

Bagaimana penganalisis dapat membantu proyek yang ada?

@petarrp itu juga C # -hanya hal.

@isaacabraham dan VB juga;)

Saya lebih suka memiliki cara waktu kompilasi untuk menangani ini.

@Aaronontheweb Anda memiliki cara waktu kompilasi untuk menangani ini (saat menyusun aplikasi). Anda dapat menambahkan ini ke proyek Anda:

<ItemGroup>
  <RuntimeHostConfigurationOption Include="System.Globalization.UseNls" Value="true" />
</ItemGroup>

EDIT: ini hanya untuk aplikasi yang menggunakan perpustakaan, sayangnya Anda tidak dapat mengontrol ini saat menulis perpustakaan.

Dalam jangka panjang, tim Windows mempromosikan untuk pindah ke ICU, jadi pada titik tertentu ICU akan menjadi cerita globalisasi, dan kami hanyalah pembungkus tipis di sekitar pustaka OS.

apa yang akan terjadi ketika .NET 5 memanggil objek yang didefinisikan di dalam pustaka .NET Standard 2.0 yang memanipulasi string yang diteruskan ke dalamnya dari situs panggilan .NET? Apakah perilaku lama digunakan atau perilaku baru?

Perilaku baru akan digunakan, karena bergantung pada runtime dan .NET Standard hanyalah standar untuk implementasi runtime. Namun, perhatikan bahwa ini membawa konsistensi platform di antara Unix dan Windows, jika Anda menjalankan pustaka yang sama yang dikhawatirkan orang di Unix, Anda akan mendapatkan hasil ICU karena ICU adalah dukungan perpustakaan di Unix.

@reflectronic benar di semua poinnya https://github.com/dotnet/runtime/issues/43736#issuecomment -716681586.

untuk mengomentari hasil @jbogard yang disebutkan di sini https://github.com/dotnet/runtime/issues/43736#issuecomment -716527590, Anda dapat meringkas hasil dengan membandingkan antara perilaku Linguistik antara Windows dan ICU. Ngomong-ngomong, ICU sekarang digunakan oleh banyak aplikasi di Windows dan diharapkan penggunaannya meningkat. Selain itu, hasil ini tidak termasuk Linux dengan .NET Core 3.1 dan di bawahnya. yang akan menunjukkan konsistensi antara .NET 5.0 dan versi sebelumnya di Linux.

Poin tentang perpustakaan yang dulu berfungsi akan rusak, ini tidak sepenuhnya benar karena perpustakaan semacam itu sudah rusak di Linux.

Apakah Anda akan mempertimbangkan untuk membuat perubahan besar agar juga menjadikan StringComparison.Ordinal sebagai strategi perbandingan default?

Saya sebutkan sebelumnya bahwa kami sudah mencobanya sebelumnya tetapi ukuran keluhan sangat besar sehingga kami tidak dapat menerapkannya. Kami mencari cara untuk membantu pengembang agar sadar dalam menentukan tanda perbandingan string saat memanggil API pemeriksaan.

Saya membuat perpustakaan untuk mencari nafkah, bukan aplikasi. Saya lebih suka memiliki cara waktu kompilasi untuk menangani ini.

Ya, beberapa penganalisis dapat membantu dalam kasus seperti itu. biasanya melihat panggilan API pemeriksaan dan melihat mana yang tidak menunjukkan maksud menggunakan operasi ordinal atau linguistik.

Bagaimana penganalisis dapat membantu proyek yang ada?

Penganalisis memindai kode dan mendeteksi panggilan API collations yang tidak meneruskan flag akan membantu untuk melihat panggilan tersebut dan memperbaikinya jika terdeteksi ada masalah.

itu juga C # -hanya hal.

Perubahannya ada di dalam runtime .NET yang harus global dan tidak terbatas pada C #.

@ Tarekgh bagaimana C # analyzer memanifestasikan dirinya dalam basis kode VB atau F #?

Sebagian besar pekerjaan yang kami lakukan adalah InvariantCulture , yang menurut pemahaman saya sebelumnya seharusnya tidak dapat diubah oleh desain.

Secara kritis, sebelum perubahan ini, tidak mungkin untuk benar-benar bergantung pada ini untuk kode lintas platform; seperti apa perilaku NLS dan ICU, bahkan ketika menggunakan budaya invarian, tidak selalu sama (seperti yang dibuktikan dalam masalah ini). Seperti yang dikatakan @tarekgh , kode ini telah bertindak berbeda di Linux selama ini. Sekarang perubahan ini telah dilakukan, untuk setiap penginstalan Windows terbaru, apa arti "budaya invarian" yang _actually_ harus konsisten di semua platform.

Ini mungkin mengejutkan, tetapi kami akhirnya menemukan dan memperbaiki lusinan bug yang terkait dengan perbedaan platform selama bertahun-tahun sebagai hasil dari pelaporan pengguna, seperti yang saya yakin banyak penulis perpustakaan lain telah lakukan selama bertahun-tahun.

Saya hanya tidak senang dengan prospek .NET 5 memperkenalkan tanaman baru dari hal-hal yang tidak diketahui yang tidak diketahui dan meninjau kembali perbaikan tersebut tidak hanya untuk perpustakaan saya, tetapi juga ketergantungan hilir kami. Itu adalah biaya ekonomi yang signifikan bagi kami yang tidak menciptakan peningkatan produktivitas baru bagi pengguna kami. Seseorang di MSFT harus memberikan pertimbangan tersebut dalam diskusi biaya / manfaat mereka saat membuat perubahan ini.

Edit: seperti, saya sudah mendapatkan manfaat teknisnya - ya, terima kasih. Tolong bantu menjual manfaat ekonomi yang tidak jelas dari membuat perubahan ini dan bukan biaya. Mengapa pengguna harus mengambil lompatan dan meningkatkan ke .NET 5 bagaimanapun juga mengingat seperti apa sarang tikus masalah ini?

@ Tarekgh bagaimana C # analyzer memanifestasikan dirinya dalam basis kode VB atau F #?

Kami dapat mencakup C # dan VB dengan satu penganalisis (kami berusaha keras untuk membuat penganalisis kami tidak mengenal bahasa kapan pun memungkinkan), tetapi kami tidak dapat memperoleh cakupan penganalisis untuk F # saat ini.

@Aaronontheweb siapa pun yang menggunakan fungsionalitas budaya dan menganggapnya tidak akan berubah sudah rusak bahkan jika kami tidak melakukan perubahan ICU ini. Lihat blog https://docs.microsoft.com/en-us/archive/blogs/shawnste/locale-culture-data-churn dari tim Windows yang mengatakan bahwa bahkan perilaku NLS pun berubah demi peningkatan juga. Jadi, masalahnya di sini bukan tentang pindah ke ICU lebih dari sekadar menangkap asumsi yang salah dari perspektif aplikasi / perpustakaan. mengupgrade ke 5.0 sama dengan mengupgrade ke versi sebelumnya. aplikasi akan mendapatkan banyak fitur keren baru dan aplikasi perlu diuji karena mungkin ada beberapa perubahan yang dapat merusak antar rilis. Saya tidak menganggap perubahan perilaku globalisasi benar-benar merusak karena kami selalu memberi tahu globalisasi dapat berubah kapan saja antara versi OS dan OS. Seperti yang ditunjukkan sebelumnya, kami memiliki tombol konfigurasi untuk memilih untuk meningkatkan ke 5.0 dengan tetap menggunakan NLS. yang akan membuat ICU tidak benar-benar menjadi faktor dalam keputusan peningkatan. sekarang dengan ICU, aplikasi akan memiliki kesempatan untuk mendapatkan lebih banyak konsistensi di seluruh OS dan bahkan dapat memiliki kontrol lebih besar pada perilaku globalisasi jika memutuskan untuk menggunakan ICU aplikasi-lokal. Kami memberikan lebih banyak kontrol ke aplikasi daripada sebelumnya.

Terkait: https://github.com/dotnet/runtime/issues/43802

(Masalah itu tidak melacak IndexOf _per se_. Sebaliknya, ini membahas konsekuensi yang tidak diinginkan dari rutinitas Compare default ke pembanding yang sadar budaya.)

Bagaimana penganalisis dapat membantu proyek yang ada?

Penganalisis memindai kode dan mendeteksi panggilan API collations yang tidak meneruskan flag akan membantu untuk melihat panggilan tersebut dan memperbaikinya jika terdeteksi ada masalah.

Saya kira penganalisis harus ditambahkan ke csproj.
Ini tidak akan terjadi secara otomatis. Jadi, banyak proyek yang ada akan dipindahkan ke .NET 5 tanpa penganalisis tersebut.
Ditambah, seperti yang telah disebutkan, ini tidak akan membantu proyek F #.

@ jeffhandley terima kasih, itu menegaskan apa yang sudah saya pahami. Jadi, penting untuk mengetahui bahwa "solusi" yang mungkin tidak akan membantu pengguna F # (pasar kecil tapi tetap didukung penuh oleh MS sebagai warga kelas satu .NET). Saya tidak tahu apa artinya:

Perubahannya ada di dalam runtime .NET yang harus global dan tidak terbatas pada C #.

Saya tidak tahu apa artinya:
Perubahannya ada di dalam runtime .NET yang harus global dan tidak terbatas pada C #.

Maksud saya bahasa apa pun yang menggunakan runtime NET akan terpengaruh dan tidak hanya C #.

Saya akan menyuarakan pendapat saya dengan tegas bahwa di luar kotak harus ada penganalisis untuk mengungkap hal-hal aneh ini di dunia baru, terutama jika rencananya adalah untuk mengubah perilaku saat ini.

Saya sepenuhnya memahami manfaat teknis dari melakukannya dan saya tidak menyarankan Anda untuk tidak membuat perubahan (dalam jangka panjang sepertinya ini adalah langkah yang benar). Saya juga tidak mengatakan bahwa itu belum didokumentasikan sebagai praktik terbaik. Apa yang saya katakan adalah bahwa kita benar-benar membutuhkan ini menjadi kesalahan besar, merah, berkedip bagi pengembang yang mencoba mengangkat ke .NET 5. Di luar kotak Pengembang akan menganggap ini "berfungsi" jika tidak.

Sekarang hari ini Anda dapat menggunakan Perpustakaan Penganalisis Roslyn ini dari @meziantou untuk menemukan area yang terpengaruh: https://github.com/meziantou/Meziantou.Analyzer/tree/master/docs.

Dalam kasus khusus ini, ini akan melempar MA0074 - Hindari metode sensitif budaya implisit

image

Karena itu, ini benar-benar harus di luar kotak, saya telah membuka masalah Roslyn ini di sini: https://github.com/dotnet/roslyn-analyzers/issues/4367

@tarekgh Terima kasih telah mengklarifikasi. Poin asli saya adalah bahwa penganalisis bukanlah jawaban di sini jika Anda mencari solusi yang berfungsi untuk semua pengguna NET.

Kami mencari lebih banyak cara untuk membantu para pengembang agar sadar saat memanggil sesuatu seperti IndexOf dan dengan sengaja memberikan tanda Perbandingan String untuk menyatakan maksudnya. Kami menyambut baik ide apa pun yang mungkin Anda keluarkan juga.

Bagaimana kalau menghentikan metode lama (menggunakan atribut [Obsolete] )?

Apa yang terjadi pada kompatibilitas .NET Standard ketika permukaan API sama tetapi perilakunya berubah?

Perubahan untuk menghormati kelompok grafem tidak mengganggu saya, selama dampaknya didokumentasikan dengan baik. Perubahan yang menyebabkan anggota keluarga metode string berperilaku tidak konsisten satu sama lain tidak.

Seseorang yang melakukan pemungutan string informal, acuh tak acuh terhadap ketidakjelasan karakter, kelompok grafem, atau lokal, akan menganggapnya asalkan jika str. Berisi (apa pun) berhasil, tidak perlu memeriksa hasil dari str.IndexOf (apa pun ) karena kami baru saja diberi tahu bahwa itu ada di sana dan oleh karena itu dapat ditemukan. Tidak masalah parameter kedua mana yang tidak mereka ketahui adalah default karena default pasti akan berperilaku sama di seluruh metode , membebaskan mereka dari keharusan mempelajari semua seluk-beluk untuk menggunakannya sama sekali.

Inkonsistensi seperti ini menghasilkan bahasa yang hanya dapat digunakan dengan sukses oleh para ahli dan mengasingkan orang-orang yang keluar dari kamp kode. Jangan menaikkan standar untuk masuk dengan cara ini.

Saya setuju dengan @lupestro. Ketidakkonsistenan perilaku metode sangat memprihatinkan. Jika Anda ingin memiliki metode lama yang bertindak secara berbeda dan tidak konsisten, akan ada banyak kesedihan. Orang-orang akan mengalami ini, mereka akan merasa dikhianati oleh API dan kemudian mereka akan bertanya-tanya bom waktu apa lagi yang menunggu untuk meledak. Banyak yang akan menjadi. Pengadopsi NET akan menghapus C # karena masalah semacam ini. Tampaknya Anda harus menghapus kelebihan beban yang tidak menerima lokal, atau menormalkan lokal default untuk metode. Sudah ada Ordinal Bandingkan dan Bandingkan, mungkin diperlukan Ordinal Index (Terakhir) IndexOf (Any) dan (Last) IndexOf (Any). Saya tidak suka solusi itu tetapi setidaknya itu akan konsisten dengan apa yang ada saat ini. Mungkin gagasan penggunaan ordinal dalam string harus disusutkan. Jika saya harus memilih antara cepat atau benar, saya akan memilih 'benar' setiap saat. Perilaku yang tidak konsisten dan tidak intuitif sangat membuat frustrasi.

Saya melihat masalah ini sudah ditutup jadi saya kira sudah diputuskan bahwa ini akan bergerak maju di .NET 5.0. Saya tahu hal ini sulit dan info Budaya (seperti Waktu) dapat berubah karena berbagai alasan non-teknis. Pengembang perlu menyadari hal ini, tetapi mereka juga perlu bergantung pada API mereka agar konsisten. Setidaknya harus ada peringatan (di 5.0) seperti yang ditunjukkan oleh @aolszowka yang menunjukkan masalah ... dan yang lebih penting mengapa itu masalah. Bergerak maju itu penting dan terkadang itu berarti Anda harus "mematahkan" perilaku / asumsi lama. Itu tidak berarti bahwa inkonsistensi baru perlu diperkenalkan. Perubahan ini merusak ekspektasi serta kode. Jika tidak memungkinkan untuk membuat metode konsisten maka saya lebih suka CultureInfo dipaksa untuk menjadi eksplisit (yang kemudian dapat saya atasi melalui metode ekstensi) daripada hanya memiliki kemungkinan kesalahan non-intuitif yang meledakkan kode saya selama siklus pengembangan yang penuh tekanan atau yang terburuk di instalasi pelanggan.

TLDR: Ubah hal-hal yang perlu diubah tetapi jangan membuat API tidak konsisten untuk melakukannya. Jika Anda ingin merusaknya, gantilah dengan sesuatu yang lebih baik.

Saya telah menggunakan .NET selama bertahun-tahun dan selalu menggunakan InvariantCulture secara default saat menggunakan fungsi ini. Berkenaan dengan bahasa selain bahasa Inggris, saya selalu mengetahui pasangan karakter yang berfungsi sebagai alias untuk huruf khusus bahasa lainnya, dan pekerjaan ekstra yang dilakukan untuk memeriksa pasangan ini saat melakukan perbandingan dengan CurrentCulture sebagai default. Ini telah menggigit saya, misalnya, saat menulis kode ASP.NET yang menyetel CurrentCulture utas berdasarkan bahasa pilihan pengguna yang dikirim oleh browser, dan perbandingan untuk pengguna yang tidak menggunakan bahasa Inggris membuat kode terputus dengan cara yang halus, terutama ketika string berisi campuran teks yang dimasukkan pengguna (linguistik) dan teks ordinal.

Perilaku klaster grafem Unicode ini adalah yang baru bagi saya, karena saya akan mengharapkan perilaku ordinal untuk umpan garis dan pengembalian kereta, bahkan jika saya telah menggunakan kelebihan muatan Invarian seperti yang biasanya saya lakukan. Tampak bagi saya bahwa perilaku yang bekerja lebih banyak dan membutuhkan pengetahuan ahli haruslah perilaku memilih, terlepas dari kebenaran teknis. Mungkin kapal itu sudah lama berlayar, tetapi _perubahan yang merusak ini_ harus dibuat sejelas, misalnya, perubahan bahasa, tanpa harus membaca blog yang tidak jelas. Rekan-rekan saya hampir tidak mengetahui fitur C # 9.0 baru, apalagi beberapa aturan ICU misterius yang dapat memengaruhi kode yang mereka tulis hari ini yang mungkin suatu saat akan di-porting dan dikompilasi dalam .NET 5 (atau, lebih mungkin, .NET 6 atau 7).

Menghapus metode lama adalah salah satu hal yang kami pertimbangkan. Saya menyelesaikan draf proposal tadi malam dan sedang berbelanja untuk tinjauan internal, dan saya akan mempostingnya sebagai masalah baru di sini dalam beberapa jam.

Draf diposting di https://github.com/dotnet/runtime/issues/43956. Ini mencantumkan beberapa alternatif untuk kemungkinan jalan ke depan (termasuk tidak melakukan apa-apa) dan mempertimbangkan pro dan kontra dari setiap pendekatan. Silakan tinggalkan umpan balik tentang tindakan yang diusulkan di sana.

Jika Anda melaporkan bug, ajukan masalah baru dan gunakan masalah baru itu untuk mendeskripsikan bug.

Jika Anda memiliki komentar tentang terbitan khusus ini ( "\r\n" vs. "\n" ), harap tetap menanggapi di utas ini. Terima kasih!

Pembukaan kembali sementara kami mempertimbangkan pendekatan yang dijelaskan dalam dokumen @GrabYourPitchforks .

Kami benar-benar mendengarkan Anda - ada banyak umpan balik yang jelas di sini - kami sedang berupaya mencari cara yang tepat ke depan, dan kami akan terus memperbarui masalah ini.

Perubahan untuk menghormati kelompok grafem tidak mengganggu saya, selama dampaknya didokumentasikan dengan baik. Perubahan yang menyebabkan anggota keluarga metode string berperilaku tidak konsisten satu sama lain tidak.

Seseorang yang melakukan pemungutan string informal, acuh tak acuh terhadap ketidakjelasan karakter, kelompok grafem, atau lokal, akan menganggapnya asalkan jika str. Berisi (apa pun) berhasil, tidak perlu memeriksa hasil dari str.IndexOf (apa pun ) karena kami baru saja diberi tahu bahwa itu ada di sana dan oleh karena itu dapat ditemukan. Tidak masalah parameter kedua mana yang tidak mereka ketahui adalah default karena default pasti akan berperilaku _sama di semua metode_, membebaskan mereka dari keharusan mempelajari semua seluk-beluk untuk menggunakannya sama sekali.

Inkonsistensi seperti ini menghasilkan bahasa yang hanya dapat digunakan dengan sukses oleh para ahli dan mengasingkan orang-orang yang keluar dari kamp kode. Jangan menaikkan standar untuk masuk dengan cara ini.

Ya, ini benar-benar mengungkapkan keprihatinan saya. Sebagai pengembang Cina pada umumnya, kami jarang memasukkan StringComparison atau CultureInfo secara eksplisit saat memanggil metode terkait string dalam kode aplikasi kami, dan ini berfungsi. Kami pasti tidak mengharapkan perilaku yang berbeda antara IndexOf dan Contains !
.net 5.0
image
.net core 3.1
image
Kerangka .net
image

Saya setuju dengan @lupestro. Ketidakkonsistenan perilaku metode sangat memprihatinkan. Jika Anda ingin memiliki metode lama yang bertindak secara berbeda dan tidak konsisten, akan ada banyak kesedihan.

Mungkin poin kunci di sini adalah bahwa kedua metode tersebut selalu tidak konsisten. Mereka tidak tiba-tiba menjadi tidak konsisten di .NET 5.0. Jika saya mengikuti hal-hal dengan benar, IndexOf selalu menggunakan perbandingan budaya saat ini, Contains selalu menggunakan perbandingan ordinal. Diberikan .NET 5.0 menambahkan lebih banyak inkonsistensi. Tetapi kesalahan di sini adalah pada desain API asli yang memungkinkan ketidakkonsistenan ini.

Jika saya mengikuti hal-hal dengan benar, IndexOf selalu menggunakan perbandingan ordinal, Contains selalu menggunakan perbandingan budaya saat ini. Diberikan .NET 5.0 menambahkan lebih banyak inkonsistensi. Tetapi kesalahan di sini adalah pada desain API asli yang memungkinkan ketidakkonsistenan ini.

Itu benar tetapi sebaliknya, IndexOf(string) menggunakan budaya saat ini, IndexOf(char) menggunakan Ordinal dan Contains menggunakan ordinal.

Saya akan menguraikan secara singkat tentang perbedaan IndexOf vs. Contains yang baru-baru ini disinggung orang lain.

IndexOf(string) selalu mengasumsikan perbandingan _CurrentCulture_, dan Contains(string) selalu mengasumsikan perbandingan _Ordinal_. Perbedaan ini ada jauh di .NET Framework. Ini bukan perbedaan baru yang diperkenalkan di .NET 5. Misalnya, pada .NET Framework (yang menggunakan fasilitas NLS Windows), ligatur "æ" dan dua karakter string "ae" dibandingkan sama di bawah pembanding linguistik. Ini menghasilkan perbedaan berikut:

// Sample on .NET Framework, showing Contains & IndexOf returning inconsistent results
Console.WriteLine("encyclopædia".Contains("ae")); // prints 'False'
Console.WriteLine("encyclopædie".IndexOf("ae")); // prints '8' (my machine is set to en-US)

Perbedaan ini telah ada selama lebih dari satu dekade. Itu didokumentasikan dan ada panduan tentang itu. Apakah ini salah desain? Mungkin. Kami membahas di https://github.com/dotnet/runtime/issues/43956 cara untuk membuat ekosistem lebih sehat di masa mendatang.

Untuk masalah khusus ini, yang sebenarnya kami tanyakan pada diri sendiri adalah: "Mengingat perbedaan tersebut telah ada selamanya, seberapa jauh jarak kedua metode ini dibiarkan menyimpang _ dalam praktiknya_ sebelum merusak ekosistem yang lebih besar?" Saya pikir kami masih mencoba untuk menentukan di mana ambang batas itu seharusnya. Laporan seperti ini _sangat membantu karena memberi kami wawasan tentang orang-orang yang menggunakan API ini dalam praktiknya dan ekspektasi apa yang dimiliki pelanggan terkait perilaku mereka. Sebagai pengurus kerangka kerja, kita perlu mempertimbangkan tidak hanya dokumentasi teknis, tetapi juga cara aplikasi dunia nyata menggunakan API ini.

Komentar ini sebenarnya tidak dimaksudkan untuk mempertahankan sudut pandang tertentu. Maksud saya adalah untuk mengklarifikasi beberapa kesalahpahaman yang telah saya lihat dan untuk membantu menjelaskan bagaimana kami membingkai masalah tersebut.

Bahkan jika InvariantCulture ditentukan, apakah benar bahwa \n tidak cocok dalam versi ICU?

image
image

Mungkin, kode berikut menampilkan 5 di Linux dan -1 di Windows jika kita menggunakan git dan pengaturan default-nya (autocrlf = true)?

using System;

var s = @"hello
world";
Console.WriteLine(s.IndexOf("\n", StringComparison.InvariantCulture));

@ufcpp Ya, per ICU itu adalah perilaku yang diharapkan, seperti yang dibahas sebelumnya di utas ini. Dua karakter <CR><LF> ketika keduanya muncul berdekatan satu sama lain dianggap sebagai unit yang tidak dapat dipecahkan untuk tujuan linguistik. Mencari <LF> menggunakan pembanding linguistik (seperti _InvariantCulture_) tidak akan menghasilkan kecocokan karena akan membagi unit yang tidak dapat dipecahkan ini.

Saya ingin berbagi pembaruan dengan semua orang: Kami telah memutuskan untuk mempertahankan ICU sebagai default untuk 5.0 GA. Kami akan melihat cara memperbaiki jebakan penggunaan perbandingan linguistik secara tidak sengaja saat ordinal dimaksudkan, yang dilacak di https://github.com/dotnet/runtime/issues/43956. Kami juga akan menghubungi beberapa perpustakaan yang telah kami identifikasi terkena dampak masalah ini. Di masa mendatang, kami akan membagikan lebih banyak dokumen untuk menyertai rilis 5.0 mendatang yang akan membantu orang mengidentifikasi kode bermasalah dengan lebih baik dan memperbaikinya untuk menghindari masalah ini.

Ini adalah keputusan yang sangat sulit untuk dibuat dan kami harus mempertimbangkan dampak kompatibilitas pada ekosistem terhadap hard disk standardisasi di seluruh platform.

Kami akan membiarkan masalah ini terbuka untuk mempertimbangkan mitigasi lebih lanjut untuk masalah \r\n dalam pelayanan jika ditentukan bahwa mitigasi saat ini tidak mencukupi.

Saya juga ingin mendorong orang-orang untuk terus melaporkan masalah yang ditemui sebagai akibat dari sakelar ICU, meskipun perilakunya mungkin disebabkan oleh penyebab yang diketahui, bukan berarti itu "sesuai rancangan". Kami akan terus menyelidiki perbedaan dan memahami akar penyebabnya dan menentukan apakah kami perlu mendorong perubahan ke ICU atau .NET untuk mengatasinya.

Ada aturan penganalisis untuk selalu menentukan Perbandingan String.

https://docs.microsoft.com/en-us/dotnet/fundamentals/code-analysis/quality-rules/ca1307

Saya ingin berbagi pembaruan dengan semua orang: Kami telah memutuskan untuk mempertahankan ICU sebagai default untuk 5.0 GA. Kita akan melihat cara memperbaiki jebakan penggunaan perbandingan linguistik secara tidak sengaja saat ordinal dimaksudkan, yang dilacak di # 43956. Kami juga akan menghubungi beberapa perpustakaan yang telah kami identifikasi terkena dampak masalah ini. Di masa mendatang, kami akan membagikan lebih banyak dokumen untuk menyertai rilis 5.0 mendatang yang akan membantu orang mengidentifikasi kode bermasalah dengan lebih baik dan memperbaikinya untuk menghindari masalah ini.

Ini adalah keputusan yang sangat sulit untuk dibuat dan kami harus mempertimbangkan dampak kompatibilitas pada ekosistem terhadap hard disk standardisasi di seluruh platform.

Kami akan membiarkan masalah ini terbuka untuk mempertimbangkan mitigasi lebih lanjut untuk masalah \r\n dalam pelayanan jika ditentukan bahwa mitigasi saat ini tidak mencukupi.

Saya juga ingin mendorong orang-orang untuk terus melaporkan masalah yang ditemui sebagai akibat dari sakelar ICU, meskipun perilakunya mungkin disebabkan oleh penyebab yang diketahui, bukan berarti itu "sesuai rancangan". Kami akan terus menyelidiki perbedaan dan memahami akar penyebabnya dan menentukan apakah kami perlu mendorong perubahan ke ICU atau .NET untuk mengatasinya.

Saya ingin tahu apakah saya masih dapat menggunakan dependensi .NET Standard yang tidak dapat saya kendalikan.

Saya kira saya tidak akan bisa. Bagaimana cara memastikan orang beralih ke, saya tidak tahu, .NET Standard 2.2? Ubah API?

Sehingga saya dapat mengetahui dengan pasti bahwa saya mendapatkan perilaku yang diharapkan.

Saya tidak yakin bagaimana lagi kita dapat menghindari kerusakan ekosistem saat ini, yang sudah memiliki banyak masalah.

Saya senang terbukti salah, lakukan dengan prasangka - itu akan menenangkan pikiran saya :)

@collina_collina

Saya ingin tahu apakah saya masih dapat menggunakan dependensi .NET Standard yang tidak dapat saya kendalikan.

Pustaka Standar Bersih umumnya seharusnya lintas platform. Dan jika beberapa pustaka bekerja dengan benar pada .Net Core 3 di Unix hari ini (yang menggunakan ICU), maka hampir pasti juga akan bekerja pada .Net 5 di Windows (yang juga menggunakan ICU).

.NET Standard 2.2

.Net Standard vNext secara efektif ada, meskipun disebut ".Net 5.0". (Yaitu jika Anda menulis perpustakaan dan tidak peduli tentang mendukung kerangka kerja lama, hari ini, Anda akan menargetkan .Net Standard 2.1. Dalam sebulan, Anda akan menargetkan .Net 5.0 sebagai gantinya.)

@Vikus Saya mengerti. Saya yakin saya sudah memahami cara kerja .NET Standard bekerja. Saya mengerti. NET 5 adalah .NET Standard baru, seolah-olah.

Saya minta maaf tapi saya masih tidak yakin tentang apa yang terjadi ketika saya mereferensikan pustaka .NET Standard 2.1 yang mengandalkan inkonsistensi perilaku yang sudah ada sebelumnya antara IndexOf dan Contains.

Apa yang berubah di sini adalah sesuatu yang out-of-band, ICU versus NLS. Perubahan ini memperlebar perbedaan yang sudah kita miliki, dan merusak ekspektasi.
Tidak ada yang menyandikan info ini ke libs.

Saya tidak berasumsi untuk memahami semua implikasinya, tetapi saya tidak dapat menghilangkan perasaan bahwa kita "secara teknis benar" tanpa jalur orientasi yang mulus ke normal baru. Yang sangat dibutuhkan.

Seperti yang disebutkan orang lain, kebanyakan orang bahkan tidak mengetahui fitur bahasa baru, apalagi perubahan seismik seperti ini ditemukan secara acak oleh anggota komunitas terbaik kami. Seberapa besar kemungkinan kita bisa menahan ini?

Saya ingin tahu apakah saya masih dapat menggunakan dependensi .NET Standard yang tidak dapat saya kendalikan.

Apa yang berubah di sini adalah sesuatu yang out-of-band, ICU versus NLS. Perubahan ini memperlebar perbedaan yang sudah kita miliki, dan merusak ekspektasi.

Tidak, tidak. Tidak dapat cukup ditekankan di sini bahwa ICU _selalu_ digunakan di Unix. Pustaka .NET Standar seharusnya portabel dengan desain dan apa pun yang sebelumnya bekerja di Linux .NET Core 3.x akan bekerja di .NET 5.

Sebagian besar pekerjaan yang kami lakukan adalah InvariantCulture, yang menurut pemahaman saya sebelumnya seharusnya tidak dapat diubah oleh desain.

Tidak benar. InvariantCulture seharusnya hanya mengabaikan pengaturan bahasa pengguna. Itu masih bisa berubah dengan pembaruan ke spesifikasi unicode atau ke perpustakaan globalisasi, dll.

Apakah tim .NET mempertimbangkan rasa sakit dan masalah serta biaya yang dapat ditimbulkan?

Komentar seperti ini membuatku kesal tanpa akhir. Kode apa pun yang tiba-tiba rusak dengan perubahan ini awalnya salah. Bagaimana platform seharusnya bergerak maju jika tim .NET harus mempertahankan perilaku kode pengguna yang salah atau bergantung pada detail implementasi? Ini tidak seperti mereka tidak menyediakan sakelar kompatibilitas. Sebagian besar alasan .NET Core dipisahkan dari .NET Framework adalah untuk menyelesaikan masalah ini melalui fitur seperti penginstalan berdampingan dan penerapan runtime lokal aplikasi. Jika Anda tidak dapat pindah ke .NET 5 karena hal ini, jangan pindah ke .NET 5.

Saya hanya tidak senang dengan prospek .NET 5 memperkenalkan tanaman baru dari hal-hal yang tidak diketahui yang tidak diketahui dan meninjau kembali perbaikan tersebut tidak hanya untuk perpustakaan saya, tetapi juga ketergantungan hilir kami.

Jika Anda telah membasmi semua bug perbedaan platform seperti yang Anda klaim, maka Anda tidak perlu khawatir.

Apakah tim .NET mempertimbangkan rasa sakit dan masalah serta biaya yang dapat ditimbulkan?

Komentar seperti ini membuatku kesal tanpa akhir.

Jutaan proyek berjalan di .NET dan manipulasi string adalah operasi yang sangat sering dilakukan.
Upaya yang diperlukan tim .NET untuk memperbaiki / mengubah ini sangat kecil dibandingkan dengan upaya yang diperlukan untuk memverifikasi semua kode yang ada yang akan dipindahkan ke .NET 5/6.

Jadi, cukup adil untuk bertanya tentang "rencana" untuk mengatasi hal ini.
Apakah ada rencana?
Apakah efek dari perubahan ini diperkirakan?
Apakah 0,001% dari semua proyek? Apakah 75%?
Apa perubahan serupa lainnya yang tidak kita ketahui?

Mungkin ini hanya memengaruhi sejumlah kecil proyek.
Tapi, apakah sudah diperkirakan?

BTW, saya semua untuk melanggar perubahan karena alasan yang cukup baik. Tapi, kita juga membutuhkan jalur migrasi yang tidak terlalu beresiko.

@petarrepac Jangan salah paham, saya mengerti itu. Tetapi seperti yang telah ditunjukkan beberapa kali di utas ini:

  1. Ada rencana, dan itu adalah untuk menyediakan saklar konfigurasi runtime.
  2. Perilaku yang diklaim melanggar adalah perilaku .NET yang ada di semua platform non-windows.
  3. Ini seharusnya hanya mempengaruhi kode yang melakukan operasi peka budaya di mana ordinal dimaksudkan.

Mengingat dua poin terakhir, mungkin masuk akal untuk mengasumsikan bahwa ini memengaruhi sebagian kecil proyek.

100% wajar untuk menanyakan hal ini, tetapi orang-orang yang menulis komentar seperti yang saya kutip seringkali hanya berasumsi bahwa tidak ada pertimbangan yang dimasukkan dan ditulis sebelum mencoba memahami gambaran yang lebih besar di balik perubahan tersebut.

Halo semua. Kami ingin memberikan ringkasan singkat dari tindakan yang kami ambil ketika masalah ini terbuka dan pada akhirnya mengapa kami memutuskan untuk tetap default pada Pembaruan Windows 10 Mei 2019 atau yang lebih baru menjadi ICU untuk .NET 5.0.

Ketika masalah dibuka, kami memulai beberapa diskusi internal tentang potensi dampak dan rasa sakit yang mungkin ditimbulkan hal ini dengan pelanggan kami mengingat ketidakkonsistenan antara Contains(string) yaitu Ordinal dan IndexOf(string) menjadi sadar budaya, ditambah memiliki API lain yang sadar budaya secara default saat beroperasi melalui string, tetapi menjadi Ordinal saat mengoperasikan lebih dari Span<char> atau ReadOnlySpan<char> . Jadi setelah membahas masalah ini, kami mulai melakukan analisis pada paket NuGet yang mungkin terpengaruh dan mengumpulkan data untuk mendapatkan gambaran yang jelas. Inilah temuan kami:

  • "\ n" adalah # 30 pada "literal string yang paling sering digunakan" yang diteruskan ke IndexOf, LastIndexOf, EndsWith, StartsWith, Bandingkan, dan CompareTo.
  • 1% dari situs panggilan ke String.EndsWith adalah dengan string pencarian yang dimulai dengan \ n. Salah satu tempat panggilan ini di mana string yang diuji berisi "akhiran baris bergaya jendela" akan rusak.
  • Ada 2040 id paket yang dihosting di NuGet.org di mana sebuah versinya berisi rakitan dengan callsite berisiko.
  • Sebagian besar situs panggilan ini ditujukan ke EndsWith dan IndexOf, yang konsisten dengan hipotesis bahwa pola ini sering digunakan untuk algoritme pemecah baris yang naif.

Dari paket 2040 ini yang memiliki situs panggilan berisiko, hanya 539 yang mendukung beberapa versi .NET Standard atau .NET Core, jadi itu berarti hanya 0,54% paket yang terdaftar di NuGet.org yang mungkin terkena break.

Kami melihat paket dalam daftar 539 id paket yang berpotensi terpengaruh untuk mendapatkan gambaran tentang dampak sebenarnya terhadapnya. Kami melihat 70 teratas (berdasarkan jumlah unduhan), 20 tidak mengekspos pola di versi terbaru, dari yang mengekspos pola kami hanya dapat melihat 32 yang memiliki lisensi permisive:

  • 14 tidak terkena bug
  • 13 berpotensi rusak
  • 5 tidak pasti (tidak ada indikasi yang jelas dari jeda karena pengkodean defensif untuk pola pemutusan baris yang beragam atau mitigasi lainnya).

Artinya, dari 70 paket teratas dengan mengunduh hanya 18% yang berpotensi terkena dampak.

Persentase ini bertumpuk dan bukan terhadap jumlah total paket di NuGet.org yaitu 229.536. Jadi jika kita menggunakan jumlah total paket dan jumlah total download di NuGet.org, kita akan melihat 539 paket yang berpotensi terkena dampak dari 229.536 yaitu 0,24%.

Dan sementara itu bagus bagi kami untuk menganalisis perpustakaan, nuget hanya mewakili sebagian kecil dari kode C # di luar sana. Dan meskipun seseorang memiliki kode tersebut, a) bug mungkin tidak mudah dilacak, dan b) mereka mungkin tidak memiliki sumbernya lagi.

Namun ini adalah sumber data yang baik untuk menyimpulkan bahwa, meskipun ini bisa menjadi perubahan perilaku yang sangat penting, ini adalah jeda yang sudah terjadi di Unix saat membaca input yang mungkin berisi Windows Line Endings (yang mungkin tidak terlalu umum).

Di .NET Core dan .NET 5+, kami berusaha keras menuju konsistensi di seluruh OS dan mengingat dampak dari perubahan ini, rasanya seperti hal yang benar untuk dilakukan. Kami benar-benar peduli dengan kompatibilitas dan karenanya menyediakan sakelar runtime compat bagi orang-orang untuk dapat kembali ke perilaku lama.

Juga, kesimpulan dari paket yang dapat kami periksa, mengingat bahwa perilakunya berbeda di Unix, kami memang melihat banyak pemrograman defensif terhadap masalah ini, untuk mengurangi potensi jeda di seluruh OS.

Selain itu, globalisasi dapat berubah kapan saja karena kami adalah pembungkus tipis di seluruh OS, jadi rasanya saat ini adalah hal yang tepat untuk menjadi pembungkus yang sama di semua OS yang kami dukung.

Sebagai bagian dari ini, kami meningkatkan dokumentasi kami dengan contoh praktis, aturan penganalisis roslyn dan bagaimana kode yang terpengaruh dapat mengurangi hal ini.

Terima kasih atas semua umpan balik Anda yang berharga karena selalu membawa kami ke tempat yang lebih baik dan kami akan mencoba untuk terus meningkatkan pengalaman ini untuk .NET 6, seperti yang dibahas di: https://github.com/dotnet/runtime/issues/43956

Karena kami memahami rasa sakit yang mungkin ditimbulkan karena perbedaan antara ujung baris di Unix dan Windows, kami membiarkan masalah ini tetap terbuka dan kami akan menyelidiki cara yang mungkin untuk mengurangi kasus \r\n untuk .NET 5.0 .x yang seharusnya menjadi bagian dari rilis layanan.

Ada juga perbedaan dengan char dan string:

Console.WriteLine("com/test/test/test/a/b/ʹ$ʹ".IndexOf("$"));
Console.WriteLine("com/test/test/test/a/b/ʹ$ʹ".IndexOf('$'));
-1
24

@mattleibow saat menggunakan pencarian karakter, ia melakukan pencarian ordinal. Doc https://docs.microsoft.com/en-us/dotnet/api/system.string.indexof?view=net-5.0#System_String_IndexOf_System_Char_ yang menyatakan This method performs an ordinal (culture-insensitive) search . Jika Anda melakukan pencarian string dengan opsi ordinal, Anda akan mendapatkan hasil yang sama seperti karakter.

C# Console.WriteLine("com/test/test/test/a/b/ʹ$ʹ".IndexOf("$", StringComparison.Ordinal));

~ Tampaknya CA1307 hanya terpicu pada indexof(char) tetapi tidak pada indexof(string) . Apakah ada aturan untuk versi string ? Ini tampaknya lebih penting karena default char secara otomatis menggunakan ordinal dan perubahan yang melanggar tidak terlalu memengaruhi ini, sedangkan perilaku string telah berubah dan Anda perlu menentukan ordinal untuk memulihkan perilaku di beberapa kasus. ~

~ Bagaimana Anda mendeteksi indexof(string) ? ~

Ketemu, itu aturan CA1310. Dokumen kami salah untuk https://docs.microsoft.com/en-us/dotnet/standard/globalization-localization/globalization-icu#use -nls-bukan-icu dan tidak menyebutkan variasi khusus ini. Saya akan memperbarui dokumen itu.

Apakah halaman ini membantu?
0 / 5 - 0 peringkat