Aracılığıyla paylaş


Sabit bir dizede desen eşleştirme Span<char>

Not

Bu makale bir özellik belirtimidir. Belirtim, özelliğin tasarım belgesi olarak görev alır. Önerilen belirtim değişikliklerini ve özelliğin tasarımı ve geliştirilmesi sırasında gereken bilgileri içerir. Bu makaleler, önerilen belirtim değişiklikleri son haline getirilene ve geçerli ECMA belirtimine dahil edilene kadar yayımlanır.

Özellik belirtimi ile tamamlanan uygulama arasında bazı tutarsızlıklar olabilir. Bu farklılıklar,ilgili dil tasarım toplantısı (LDM) notlarında yakalanır.

Özellik belirtimlerini C# dil standardına benimseme işlemi hakkında daha fazla bilgi edinmek içinbelirtimleri makalesinde bulabilirsiniz.

Şampiyon sorunu: https://github.com/dotnet/csharplang/issues/8640

Özet

Bir sabit dizede Span<char> ve ReadOnlySpan<char> ile desen eşleştirmesine izin ver.

Motivasyon

Performans için, Span<char> ve ReadOnlySpan<char> kullanımı birçok senaryoda dize yerine tercih edilir. Çerçeve, ReadOnlySpan<char>yerine string kullanmanıza olanak sağlayan birçok yeni API ekledi.

Dizelerde yaygın bir işlem, belirli bir değer olup olmadığını test etmek için bir anahtar kullanmaktır ve derleyici böyle bir anahtarı iyileştirir. Ancak şu anda anahtarın ve optimizasyonun manuel olarak uygulanması dışında ReadOnlySpan<char> üzerinde aynı işlemi verimli bir şekilde gerçekleştirecek bir yol yoktur.

ReadOnlySpan<char> benimsenmesini teşvik etmek için, bir sabit ReadOnlySpan<char>üzerinde bir stringile desen eşleşmesine izin veririz, böylece switch ifadesinde kullanılmasına da olanak tanırız.

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

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

Ayrıntılı tasarım

Sabit desenler için belirtim aşağıdaki gibi değiştiririz (önerilen ekleme kalın olarak gösterilir):

e desen giriş değeri ve Pdönüştürülmüş değere sahip sabit desen v verildiğinde,

  • e tam sayı türüne veya numaralandırma türüne veya bunlardan birinin null atanabilir bir biçimine ve v integral türüne sahipse, ifadesinin sonucu ise desen e değeriyle eşleşir; yoksa
  • eSystem.Span<char> veya System.ReadOnlySpan<char>türündeyse ve c sabit bir dizeyse ve c sabit nulldeğerine sahip değilse, System.MemoryExtensions.SequenceEqual<char>(e, System.MemoryExtensions.AsSpan(c))truedöndürürse desen eşleşen olarak kabul edilir.
  • P desenideğerine e eşleşir, eğer object.Equals(e, v)truedöndürürse.

İyi bilinen üyeler

System.Span<T> ve System.ReadOnlySpan<T> adıyla eşleştirilir, ref structolmalıdır ve corlib dışında tanımlanabilir.

System.MemoryExtensions isimle eşleştirilir ve corlib dışında tanımlanabilir.

System.MemoryExtensions.SequenceEqual aşırı yüklemelerinin imzası eşleşmelidir:

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

System.MemoryExtensions.AsSpan imzası belirtilen kriterle uyumlu olmalıdır.

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

İsteğe bağlı parametreleri olan yöntemler dikkate alınmaz.

Dezavantaj -ları

Hiç kimse

Alternatif

Hiç kimse

Çözülmemiş sorular

  1. Eşleştirmenin MemoryExtensions.SequenceEqual() vb. bağımsız olarak tanımlanması gerekir mi?

    ... e.Length == c.Lengthiçindeki tüm karakterler için e[i] == c[i] ve e varsa desenin eşleştiği kabul edilir.

    Öneri: Performans için MemoryExtensions.SequenceEqual() temelinde tanımlayın. MemoryExtensions eksikse, derleme hatası bildirin.

  2. (string)null ile eşleştirmeye izin verilsin mi?

    Öyleyse, (string)nullnedeniyle ""MemoryExtensions.AsSpan(null) == MemoryExtensions.AsSpan("")'i altına almalı mı?

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

    Önerisi: Sabit desen (string)null hata olarak bildirilmelidir.

  3. Sabit desen eşleşmesi, Span<char> veya ReadOnlySpan<char>için ifade değerinin çalışma zamanı türü testini içermeli mi?

    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?
    }
    

    Tavsiye: Sabit desenler için örtük çalışma zamanı tipi testi yapılmamalıdır. ( tür testi açık olduğundanIsABC<T>() örneğine izin verilir.)

    Bu öneri uygulanmadı. Yukarıdaki örneklerin tümü derleyici hatası oluşturur.

  4. Kapsama sabit dize desenlerini, liste desenlerini ve Length özellik desenlerini dikkate almalı mı?

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

    Öneri: İfade değeri stringolduğunda kullanılan aynı alt verme davranışı. (Bu, sabit dizeler, liste desenleri ve Lengtharasında, [..]'in her şeyle eşleştirilmesi dışında, herhangi bir kapsama girmeme durumu olduğu anlamına mı gelir?)

Tasarım toplantıları

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