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:
Microsoft.Extensions.Configuration
Microsoft.Extensions.Configuration.FileExtensions
Microsoft.Extensions.FileProviders.Composite
Microsoft.Extensions.FileProviders.Physical
Microsoft.Extensions.Logging.EventSource
Microsoft.Extensions.Options
System.Text.Json
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ı CancellationChangeToken
gö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 RegisterChangeCallback
alternatif 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 IChangeToken
changeTokenProducer
ihtiyacı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 state
veya 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 StringSegment struct
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 offset
ve 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 string
StringSegment
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ı StringTokenizer
Lorem 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 StringSegment
temsil edilir. Kod segmentleri yineleyerek tüketicinin her segment
ile etkileşim kurmasına olanak sağlar.
Karşılaştırma karşılaştırması StringTokenizer
string.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:
kullanarak StringTokenizer:
StringBuilder buffer = new(); var tokenizer = new StringTokenizer( s_nineHundredAutoGeneratedParagraphsOfLoremIpsum, new[] { ' ', '.' }); foreach (StringSegment segment in tokenizer) { buffer.Append(segment.Value); }
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 | StdDev | 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 null
eden 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.