Temel Öğeler: .NET için uzantı kitaplığı

Bu makalede Microsoft.Extensions.Primitives kitaplığı hakkında bilgi edineceksiniz. Bu makaledeki temel öğeler, BCL'deki .NET temel türleriyle veya C# dilinin temel türleriyle karıştırılmamalıdır . Bunun yerine, temel öğe kitaplığındaki türler aşağıdakiler gibi bazı çevre .NET NuGet paketleri için yapı taşları olarak görev görür:

Bildirimleri değiştirme

Bir değişiklik olduğunda bildirimleri yaymak programlamada temel bir kavramdır. Bir nesnenin gözlemlenen durumu değişemeyebilir. Değişiklik gerçekleştiğinde, ilgili taraflara bu değişikliği bildirmek için arabirimin uygulamaları Microsoft.Extensions.Primitives.IChangeToken kullanılabilir. Kullanılabilir uygulamalar şunlardır:

Geliştirici olarak kendi türünüzü de uygulayabilirsiniz. IChangeToken Arabirim birkaç özelliği tanımlar:

  • IChangeToken.HasChanged: Bir değişiklik olup olmadığını gösteren bir değer alır.
  • IChangeToken.ActiveChangeCallbacks: Belirtecin proaktif olarak geri çağırmalar oluşturacağını gösterir. ise false, belirteç tüketicisinin değişiklikleri algılamak için yoklaması HasChanged gerekir.

Örnek tabanlı işlevsellik

aşağıdaki örnek kullanımını CancellationChangeTokengöz önünde bulundurun:

CancellationTokenSource cancellationTokenSource = new();
CancellationChangeToken cancellationChangeToken = new(cancellationTokenSource.Token);

Console.WriteLine($"HasChanged: {cancellationChangeToken.HasChanged}");

static void callback(object? _) =>
    Console.WriteLine("The callback was invoked.");

using (IDisposable subscription =
    cancellationChangeToken.RegisterChangeCallback(callback, null))
{
    cancellationTokenSource.Cancel();
}

Console.WriteLine($"HasChanged: {cancellationChangeToken.HasChanged}\n");

// Outputs:
//     HasChanged: False
//     The callback was invoked.
//     HasChanged: True

Yukarıdaki örnekte, bir CancellationTokenSource örneği oluşturulur ve Token oluşturucuya CancellationChangeToken geçirilir. öğesinin HasChanged ilk durumu konsola yazılır. Geri çağırma konsola çağrıldığında yazan bir Action<object?> callback oluşturulur. belirtecin RegisterChangeCallback(Action<Object>, Object) yöntemi, değeri verildiğinde çağrılır callback. deyiminde using iptal cancellationTokenSource edilir. Bu, geri çağırmayı tetikler ve durumu HasChanged konsola yeniden yazılır.

Birden çok değişiklik kaynağından eylem gerçekleştirmeniz gerektiğinde kullanın CompositeChangeToken. Bu uygulama bir veya daha fazla değişiklik belirtecini toplar ve bir değişikliğin tetiklenme sayısından bağımsız olarak her kayıtlı geri çağırmayı tam olarak bir kez tetikler. Aşağıdaki örneği inceleyin:

CancellationTokenSource firstCancellationTokenSource = new();
CancellationChangeToken firstCancellationChangeToken = new(firstCancellationTokenSource.Token);

CancellationTokenSource secondCancellationTokenSource = new();
CancellationChangeToken secondCancellationChangeToken = new(secondCancellationTokenSource.Token);

CancellationTokenSource thirdCancellationTokenSource = new();
CancellationChangeToken thirdCancellationChangeToken = new(thirdCancellationTokenSource.Token);

var compositeChangeToken =
    new CompositeChangeToken(
        new IChangeToken[]
        {
            firstCancellationChangeToken,
            secondCancellationChangeToken,
            thirdCancellationChangeToken
        });

static void callback(object? state) =>
    Console.WriteLine($"The {state} callback was invoked.");

// 1st, 2nd, 3rd, and 4th.
compositeChangeToken.RegisterChangeCallback(callback, "1st");
compositeChangeToken.RegisterChangeCallback(callback, "2nd");
compositeChangeToken.RegisterChangeCallback(callback, "3rd");
compositeChangeToken.RegisterChangeCallback(callback, "4th");

// It doesn't matter which cancellation source triggers the change.
// If more than one trigger the change, each callback is only fired once.
Random random = new();
int index = random.Next(3);
CancellationTokenSource[] sources = new[]
{
    firstCancellationTokenSource,
    secondCancellationTokenSource,
    thirdCancellationTokenSource
};
sources[index].Cancel();

Console.WriteLine();

// Outputs:
//     The 4th callback was invoked.
//     The 3rd callback was invoked.
//     The 2nd callback was invoked.
//     The 1st callback was invoked.

Yukarıdaki C# kodunda üç CancellationTokenSource nesne örneği oluşturulur ve karşılık gelen CancellationChangeToken örneklerle eşleştirilir. Bileşik belirteç, belirteçlerin bir dizisini oluşturucuya CompositeChangeToken geçirerek örneği oluşturulur. Action<object?> callback oluşturulur, ancak bu kez state nesnesi kullanılır ve konsola biçimlendirilmiş bir ileti olarak yazılır. Geri çağırma dört kez kaydedilir ve her biri biraz farklı bir durum nesnesi bağımsız değişkenine sahip. Kod, değişiklik belirteci kaynaklarından birini seçmek (hangisi fark etmez) ve yöntemini çağırmak Cancel() için sahte rastgele bir sayı oluşturucu kullanır. Bu, her kayıtlı geri çağırmayı tam olarak bir kez çağırarak değişikliği tetikler.

Alternatif static yaklaşım

çağrısına RegisterChangeCallbackalternatif olarak statik sınıfını kullanabilirsiniz Microsoft.Extensions.Primitives.ChangeToken . Aşağıdaki tüketim desenini göz önünde bulundurun:

CancellationTokenSource cancellationTokenSource = new();
CancellationChangeToken cancellationChangeToken = new(cancellationTokenSource.Token);

IChangeToken producer()
{
    // The producer factory should always return a new change token.
    // If the token's already fired, get a new token.
    if (cancellationTokenSource.IsCancellationRequested)
    {
        cancellationTokenSource = new();
        cancellationChangeToken = new(cancellationTokenSource.Token);
    }

    return cancellationChangeToken;
}

void consumer() => Console.WriteLine("The callback was invoked.");

using (ChangeToken.OnChange(producer, consumer))
{
    cancellationTokenSource.Cancel();
}

// Outputs:
//     The callback was invoked.

Önceki örneklerde olduğu gibi, tarafından oluşturulan bir uygulamasına IChangeTokenchangeTokenProducerihtiyacınız olacaktır. Üretici olarak Func<IChangeToken> tanımlanır ve bunun her çağrıda yeni bir belirteç döndürmesi beklenir. consumer, kullanmadığında stateveya genel türün TState değişiklik bildirimi aracılığıyla aktığı bir Action<TState> durumdurAction.

Dize belirteci oluşturucuları, kesimleri ve değerleri

Dizelerle etkileşim kurma, uygulama geliştirmede yaygın olarak görülür. Dizelerin çeşitli gösterimleri ayrıştırılır, bölünür veya yinelenir. Temel öğeler kitaplığı, dizelerle etkileşimi daha iyi ve verimli hale getirmeye yardımcı olan birkaç seçenek türü sunar. Aşağıdaki türleri göz önünde bulundurun:

  • StringSegment: Alt dizenin iyileştirilmiş gösterimi.
  • StringTokenizer: Bir öğesini örnekler halinde StringSegment belirteç string haline getirmektedir.
  • StringValues: , sıfır, bir veya birçok dizeyi verimli bir şekilde temsil eder null.

Türü StringSegment

Bu bölümde, türü olarak StringSegmentstruct bilinen bir alt dizenin iyileştirilmiş gösterimi hakkında bilgi edineceksiniz. Bazı StringSegment özellikleri ve yöntemini gösteren aşağıdaki C# kod örneğini AsSpan göz önünde bulundurun:

var segment =
    new StringSegment(
        "This a string, within a single segment representation.",
        14, 25);

Console.WriteLine($"Buffer: \"{segment.Buffer}\"");
Console.WriteLine($"Offset: {segment.Offset}");
Console.WriteLine($"Length: {segment.Length}");
Console.WriteLine($"Value: \"{segment.Value}\"");

Console.Write("Span: \"");
foreach (char @char in segment.AsSpan())
{
    Console.Write(@char);
}
Console.Write("\"\n");

// Outputs:
//     Buffer: "This a string, within a single segment representation."
//     Offset: 14
//     Length: 25
//     Value: " within a single segment "
//     " within a single segment "

Yukarıdaki kod, verilen değerin string örneğini StringSegment oluşturur: bir offsetve length. StringSegment.Buffer özgün dize bağımsız değişkenidir ve StringSegment.Value ve StringSegment.Length değerlerine göre StringSegment.Offset alt dizedir.

StringSegment yapısı, segmentle etkileşim kurmak için birçok yöntem sağlar.

Türü StringTokenizer

StringTokenizer nesnesi, örneğini belirteç haline getiren bir stringStringSegment yapı türüdür. Büyük dizelerin belirteçleştirilmesi genellikle dizeyi bölmeyi ve bunun üzerinde yinelemeyi içerir. Bununla birlikte, String.Split muhtemelen akla gelir. Bu API'ler benzerdir, ancak genel olarak StringTokenizer daha iyi performans sağlar. İlk olarak aşağıdaki örneği göz önünde bulundurun:

var tokenizer =
    new StringTokenizer(
        s_nineHundredAutoGeneratedParagraphsOfLoremIpsum,
        new[] { ' ' });

foreach (StringSegment segment in tokenizer)
{
    // Interact with segment
}

Yukarıdaki kodda, otomatik olarak oluşturulan 900 metin paragrafı StringTokenizerLorem Ipsum ve tek bir boşluk karakteri ' 'değerine sahip bir dizi verildiğinde türün bir örneği oluşturulur. Belirteç oluşturucu içindeki her değer olarak StringSegmenttemsil edilir. Kod segmentleri yineleyerek tüketicinin her segmentile etkileşim kurmasına olanak sağlar.

Karşılaştırma karşılaştırması StringTokenizerstring.Split

Dizeleri dilimlemenin ve bağlamanın çeşitli yolları sayesinde, iki yöntemi bir karşılaştırma ile karşılaştırmak uygun olur. BenchmarkDotNet NuGet paketini kullanarak aşağıdaki iki karşılaştırma yöntemini göz önünde bulundurun:

  1. kullanarak StringTokenizer:

    StringBuilder buffer = new();
    
    var tokenizer =
        new StringTokenizer(
            s_nineHundredAutoGeneratedParagraphsOfLoremIpsum,
            new[] { ' ', '.' });
    
    foreach (StringSegment segment in tokenizer)
    {
        buffer.Append(segment.Value);
    }
    
  2. kullanarak String.Split:

    StringBuilder buffer = new();
    
    string[] tokenizer =
        s_nineHundredAutoGeneratedParagraphsOfLoremIpsum.Split(
            new[] { ' ', '.' });
    
    foreach (string segment in tokenizer)
    {
        buffer.Append(segment);
    }
    

Her iki yöntem de API yüzey alanında benzer görünür ve her ikisi de büyük bir dizeyi öbeklere böler. Aşağıdaki karşılaştırma sonuçları yaklaşımın neredeyse üç kat daha hızlı olduğunu ancak sonuçların StringTokenizer farklılık gösterebileceğini göstermektedir. Performansla ilgili dikkat edilmesi gereken tüm noktalarda olduğu gibi, belirli kullanım örneğinizi değerlendirmeniz gerekir.

Metot Ortalama Hata Stdsapma Oran
Belirteç Oluşturucu 3,315 ms 0,0659 ms 0,0705 ms 0.32
Bölünme 10,257 ms 0,2018 ms 0,2552 ms 1.00

Açıklama

  • Ortalama: Tüm ölçümlerin aritmetik ortalaması
  • Hata: %99,9 olasılık aralığının yarısı
  • Standart sapma: Tüm ölçümlerin standart sapması
  • Ortanca: Tüm ölçümlerin yüksek yarısını ayıran değer (50. yüzdebirlik)
  • Oran: Oran dağılımının ortalaması (Geçerli/Temel)
  • Oran standart sapması: Oran dağılımının standart sapması (Geçerli/Temel)
  • 1 ms: 1 Milisaniye (0,001 sn)

.NET ile karşılaştırma hakkında daha fazla bilgi için bkz . BenchmarkDotNet.

Türü StringValues

StringValues nesnesi, sıfır, bir struct veya birçok dizeyi verimli bir şekilde temsil nulleden bir türdür. Türü StringValues aşağıdaki söz dizimlerinden biriyle oluşturulabilir: string? veya string?[]?. Önceki örnekteki metni kullanarak aşağıdaki C# kodunu göz önünde bulundurun:

StringValues values =
    new(s_nineHundredAutoGeneratedParagraphsOfLoremIpsum.Split(
        new[] { '\n' }));

Console.WriteLine($"Count = {values.Count:#,#}");

foreach (string? value in values)
{
    // Interact with the value
}
// Outputs:
//     Count = 1,799

Yukarıdaki kod, dize değerleri dizisi verilen bir StringValues nesnenin örneğini oluşturur. StringValues.Count konsola yazılır.

türü StringValues , aşağıdaki koleksiyon türlerinin bir uygulamasıdır:

  • IList<string>
  • ICollection<string>
  • IEnumerable<string>
  • IEnumerable
  • IReadOnlyList<string>
  • IReadOnlyCollection<string>

Bu nedenle, yinelenebilir ve her value biri gerektiği gibi etkileşime geçirilebilir.

Ayrıca bkz.