Bagikan melalui


Kecocokan pola Span<char> pada string konstanta

Nota

Artikel ini adalah spesifikasi fitur. Spesifikasi berfungsi sebagai dokumen desain untuk fitur tersebut. Ini termasuk perubahan spesifikasi yang diusulkan, bersama dengan informasi yang diperlukan selama desain dan pengembangan fitur. Artikel ini diterbitkan sampai perubahan spesifikasi yang diusulkan diselesaikan dan dimasukkan dalam spesifikasi ECMA saat ini.

Mungkin ada beberapa perbedaan antara spesifikasi fitur dan implementasi yang selesai. Perbedaan tersebut dicatat dalam catatan terkait rapat desain bahasa (LDM) .

Anda dapat mempelajari lebih lanjut tentang proses untuk mengadopsi speklet fitur ke dalam standar bahasa C# dalam artikel tentang spesifikasi .

Masalah utama: https://github.com/dotnet/csharplang/issues/8640

Ringkasan

Izinkan pencocokan pola Span<char> dan ReadOnlySpan<char> pada string konstan.

Motivasi

Untuk performa, penggunaan Span<char> dan ReadOnlySpan<char> lebih disukai daripada string dalam banyak situasi. Kerangka kerja telah menambahkan banyak API baru untuk memungkinkan Anda menggunakan ReadOnlySpan<char> menggantikan string.

Operasi umum pada string adalah menggunakan sakelar untuk menguji apakah itu adalah nilai tertentu, dan pengkompilasi mengoptimalkan sakelar seperti itu. Namun saat ini tidak ada cara untuk melakukan hal yang sama pada ReadOnlySpan<char> secara efisien, kecuali dengan menerapkan alih dan pengoptimalan secara manual.

Untuk mendorong adopsi ReadOnlySpan<char>, kami mengizinkan pencocokan pola ReadOnlySpan<char>terhadap konstanta string, sehingga pola tersebut juga dapat digunakan dalam sakelar.

static bool Is123(ReadOnlySpan<char> s)
{
    return s is "123";
}

static bool IsABC(Span<char> s)
{
    return s switch { "ABC" => true, _ => false };
}

Desain terperinci

Kami mengubah spesifikasi untuk pola konstan sebagai berikut (penambahan yang diusulkan ditampilkan dalam huruf tebal):

Diberikan nilai input pola e dan pola konstan P dengan nilai yang sudah dikonversi v,

  • jika e memiliki jenis integral atau jenis enum, atau bentuk nullable salah satunya, dan v memiliki jenis integral, pola Pakan cocok dengan nilaie jika hasil ekspresi e == v adalah true; Sebaliknya.
  • Jika e berjenis System.Span<char> atau System.ReadOnlySpan<char>, dan c adalah string konstanta, dan c tidak memiliki nilai konstanta null, maka pola dianggap cocok jika System.MemoryExtensions.SequenceEqual<char>(e, System.MemoryExtensions.AsSpan(c)) mengembalikan true.
  • pola Pcocok nilai e jika object.Equals(e, v) mengembalikan true.

Anggota terkenal

System.Span<T> dan System.ReadOnlySpan<T> dicocokkan berdasarkan nama, harus merupakan ref struct, dan dapat didefinisikan di luar corlib.

System.MemoryExtensions dicocokkan berdasarkan nama dan dapat didefinisikan di luar corlib.

Tanda tangan overload System.MemoryExtensions.SequenceEqual harus sesuai:

  • public static bool SequenceEqual<T>(System.Span<T>, System.ReadOnlySpan<T>)
  • public static bool SequenceEqual<T>(System.ReadOnlySpan<T>, System.ReadOnlySpan<T>)

Tanda tangan System.MemoryExtensions.AsSpan harus sesuai dengan:

  • public static System.ReadOnlySpan<char> AsSpan(string)

Metode dengan parameter opsional dikecualikan dari pertimbangan.

Kekurangan

Tidak

Alternatif

Tidak

Pertanyaan yang belum terselesaikan

  1. Haruskah pencocokan didefinisikan secara terpisah dari MemoryExtensions.SequenceEqual() dll.?

    ... pola dianggap cocok jika e.Length == c.Length dan e[i] == c[i] untuk semua karakter dalam e.

    Rekomendasi: Tetapkan dengan MemoryExtensions.SequenceEqual() untuk kinerja. Jika MemoryExtensions hilang, laporkan kesalahan kompilasi.

  2. Apakah pencocokan dengan (string)null harus diizinkan?

    Apakah (string)null mengambil alih "" karena MemoryExtensions.AsSpan(null) == MemoryExtensions.AsSpan("")?

    static bool IsEmpty(ReadOnlySpan<char> span)
    {
        return span switch
        {
            (string)null => true, // ok?
            "" => true,           // error: unreachable?
            _ => false,
        };
    }
    

    Rekomendasi: Pola konstanta (string)null harus dilaporkan sebagai kesalahan.

  3. Haruskah kecocokan pola konstanta menyertakan pengujian jenis runtime dari nilai ekspresi untuk Span<char> atau ReadOnlySpan<char>?

    static bool Is123<T>(Span<T> s)
    {
        return s is "123"; // test for Span<char>?
    }
    
    static bool IsABC<T>(Span<T> s)
    {
        return s is Span<char> and "ABC"; // ok?
    }
    
    static bool IsEmptyString<T>(T t) where T : ref struct
    {
        return t is ""; // test for ReadOnlySpan<char>, Span<char>, string?
    }
    

    Rekomendasi: Tidak ada pengujian jenis runtime implisit untuk pola konstan. (contohIsABC<T>() diizinkan karena pengujian tipe yang eksplisit.)

    Rekomendasi ini tidak diimplementasikan. Semua sampel sebelumnya menghasilkan kesalahan pengkompilasi.

  4. Haruskah subsumption mempertimbangkan pola string konstan, pola daftar, dan pola properti Length?

    static int ToNum(ReadOnlySpan<char> s)
    {
        return s switch
        {
            { Length: 0 } => 0,
            "" => 1,        // error: unreachable?
            ['A',..] => 2,
            "ABC" => 3,     // error: unreachable?
            _ => 4,
        };
    }
    

    Rekomendasi: Perilaku subsumpsi yang sama seperti yang digunakan saat nilai ekspresi string. Apakah itu berarti tidak ada subsumpsi antara string konstan, pola daftar, dan Length, kecuali memperlakukan [..] sebagai cocok dengan apa saja?

Rapat desain

https://github.com/dotnet/csharplang/blob/master/meetings/2020/LDM-2020-10-07.md#readonlyspanchar-patterns