Not
Bu sayfaya erişim yetkilendirme gerektiriyor. Oturum açmayı veya dizinleri değiştirmeyi deneyebilirsiniz.
Bu sayfaya erişim yetkilendirme gerektiriyor. Dizinleri değiştirmeyi deneyebilirsiniz.
Arabirim statik sanal üyeleri, aşırı yüklenmiş işleçleri veya diğer statik üyeleri içeren arabirimleri tanımlamanızı sağlar. Statik üyeleri olan arabirimleri tanımladıktan sonra, işleçleri veya diğer statik yöntemleri kullanan genel türler oluşturmak için bu arabirimleri kısıtlamalar olarak kullanabilirsiniz. Aşırı yüklenmiş işleçlere sahip arabirimler oluşturmasanız bile, büyük olasılıkla bu özellikten ve dil güncelleştirmesi tarafından etkinleştirilen genel matematik sınıflarından yararlanabilirsiniz.
Bu eğitimde şunları öğreniyorsunuz:
- Statik üyeleri olan arabirimleri tanımlayın.
- Tanımlanan işleçlerle arabirimler uygulayan sınıfları tanımlamak için arabirimleri kullanın.
- Statik arabirim yöntemlerini kullanan genel algoritmalar oluşturun.
Önkoşullar
- En yeni .NET SDK
- Visual Studio Code düzenleyici
- C# Geliştirme Kiti
Statik soyut arabirim yöntemleri
Bir örnekle başlayalım. Aşağıdaki yöntem iki double sayının orta noktasını döndürür:
public static double MidPoint(double left, double right) =>
(left + right) / (2.0);
Aynı mantık herhangi bir sayısal türde çalışır: int, short, long, ,floatdecimal veya bir sayıyı temsil eden herhangi bir tür.
+ ve / işleçlerini kullanmak ve 2 için bir değer tanımlamak amacıyla bir yol bulmanız gerekmektedir. Yukarıdaki yöntemi aşağıdaki genel yöntem olarak yazmak için arabirimini kullanabilirsiniz System.Numerics.INumber<TSelf> :
public static T MidPoint<T>(T left, T right)
where T : INumber<T> => (left + right) / T.CreateChecked(2); // note: the addition of left and right may overflow here; it's just for demonstration purposes
Arabirimi uygulayan her tür, operator + ve operator / için bir tanım içermelidir. Payda, herhangi bir sayısal tür için değeri 2 oluşturmak amacıyla, paydayı iki parametreyle aynı türe zorlayan T.CreateChecked(2) tarafından tanımlanır.
INumberBase<TSelf>.CreateChecked<TOther>(TOther) belirtilen değerden türün bir örneğini oluşturur ve değer temsil edilebilir aralığın dışında kalırsa bir OverflowException oluşturur. Bu uygulama, left ve right yeterince büyük değerler olduğunda, taşma potansiyeli taşır. Bu olası taşma sorununu önleyebilecek alternatif algoritmalar vardır.
Tanıdık söz dizimini kullanarak bir arayüzde statik soyut üyeler tanımlarsınız: Bir uygulama sağlamayan herhangi bir statik üyeye static ve abstract değiştiricilerini eklersiniz. Aşağıdaki örnek, IGetNext<T> arabiriminin geçersiz kılınabilecek operator ++'i uygulayarak her türde kullanılabileceğini tanımlar:
public interface IGetNext<T> where T : IGetNext<T>
{
static abstract T operator ++(T other);
}
tür bağımsız değişkeninin uyguladığı T kısıtlama, IGetNext<T>işlecin imzasının içeren türü veya tür bağımsız değişkenini içermesini sağlar. Birçok operatör, parametrelerinin tür ile uyumlu olması veya içeren türü uygulayacak şekilde kısıtlanmış tür parametresi olması gerektiğini zorlar. Bu kısıtlama olmadan, ++ işleci IGetNext<T> arabiriminde tanımlanamaz.
Aşağıdaki kodu kullanarak her artışın dizeye başka bir karakter eklediği bir 'A' karakter dizesi oluşturan bir yapı oluşturabilirsiniz:
public struct RepeatSequence : IGetNext<RepeatSequence>
{
private const char Ch = 'A';
public string Text = new string(Ch, 1);
public RepeatSequence() {}
public static RepeatSequence operator ++(RepeatSequence other)
=> other with { Text = other.Text + Ch };
public override string ToString() => Text;
}
Daha genel olarak, "bu türün sonraki değerini üret" anlamına gelecek şekilde tanımlamak ++ isteyebileceğiniz herhangi bir algoritma oluşturabilirsiniz. Bu arabirimin kullanılması net kod ve sonuçlar üretir:
var str = new RepeatSequence();
for (int i = 0; i < 10; i++)
Console.WriteLine(str++);
Yukarıdaki örnek aşağıdaki çıkışı oluşturur:
A
AA
AAA
AAAA
AAAAA
AAAAAA
AAAAAAA
AAAAAAAA
AAAAAAAAA
AAAAAAAAAA
Bu küçük örnek, bu özelliğin motivasyonunu gösterir. İşleçler, sabit değerler ve diğer statik işlemler için doğal söz dizimi kullanabilirsiniz. Statik üyeleri kullanan ve aşırı yüklenmiş işleçleri içeren birden çok tür oluşturduğunuzda bu teknikleri keşfedebilirsiniz. Türlerinizin özellikleriyle eşleşen arabirimleri tanımlayın ve ardından bu türlerin yeni arabirim desteğini bildirin.
Genel matematik
Arabirimlerde işleçler de dahil olmak üzere statik yöntemlere izin vermek için motivasyon sağlayan senaryo , genel matematik algoritmalarını desteklemektir. .NET 7 temel sınıf kitaplığı, birçok aritmetik işleç için arabirim tanımları ve bir arabirimde birçok aritmetik işleci birleştiren INumber<T> türetilmiş arabirimler içerir. Bu türleri kullanarak T için herhangi bir sayısal türün kullanılabileceği bir Point<T> kayıt oluşturalım.
+ işleci kullanılarak noktayı biraz XOffset ve YOffset hareket ettirebilirsiniz.
Yeni bir Konsol uygulaması oluşturarak başlayın, ya dotnet new ya da Visual Studio kullanarak.
Translation<T> ve Point<T> için genel arabirim aşağıdaki kod gibi görünmelidir.
// Note: Not complete. This won't compile yet.
public record Translation<T>(T XOffset, T YOffset);
public record Point<T>(T X, T Y)
{
public static Point<T> operator +(Point<T> left, Translation<T> right);
}
Hem record hem de Translation<T> türleri için türü kullanırsınız: Her ikisi de Point<T> iki değeri depolar ve bunlar karmaşık davranışlar yerine veri depolamayı temsil eder. uygulaması operator + aşağıdaki koda benzer olacaktır:
public static Point<T> operator +(Point<T> left, Translation<T> right) =>
left with { X = left.X + right.XOffset, Y = left.Y + right.YOffset };
Önceki kodun derlenmesi için T öğesinin IAdditionOperators<TSelf, TOther, TResult> arabirimini desteklediğini bildirmeniz gerekir. Bu arabirim statik yöntemi içerir operator + . Üç tür parametresi bildirir: Sol işlenen için biri, sağ işlenen için diğeri ve sonuç için de bir tane. Bazı türler, farklı işlenen ve sonuç türleri için + uygular. Tür bağımsız değişkeninin, T olarak IAdditionOperators<T, T, T>'i uyguladığını belirten bir bildirim ekleyin.
public record Point<T>(T X, T Y) where T : IAdditionOperators<T, T, T>
Bu kısıtlamayı ekledikten sonra, sınıfınızın ekleme işleci için + kullanabilirsiniz. Aynı kısıtlamayı Translation<T> deklarasyonuna ekleyin.
public record Translation<T>(T XOffset, T YOffset) where T : IAdditionOperators<T, T, T>;
IAdditionOperators<T, T, T> sınıfınız için getirilen kısıtlama, geliştiricinin, bir noktaya ekleme kısıtlamasını karşılamayan bir tür kullanarak Translation yaratmasını engeller.
Translation<T> ve Point<T> için gerekli kısıtlamaları tür parametresine eklediniz, bu nedenle bu kod çalışır.
Translation dosyanızda ve Point bildirimlerinin üstüne aşağıdaki gibi bir kod ekleyerek test edebilirsiniz:
var pt = new Point<int>(3, 4);
var translate = new Translation<int>(5, 10);
var final = pt + translate;
Console.WriteLine(pt);
Console.WriteLine(translate);
Console.WriteLine(final);
Bu türlerin uygun aritmetik arabirimleri uyguladığını bildirerek bu kodu daha yeniden kullanılabilir hale getirebilirsiniz. İlk yapılacak değişiklik, Point<T, T>'un IAdditionOperators<Point<T>, Translation<T>, Point<T>> arayüzünü uyguladığını beyan etmektir.
Point türü, işlenenler ve sonuç için farklı türler kullanır. Türü Point zaten bu imzaya sahip bir operator + uygular, bu nedenle tek ihtiyacınız olan bildirime arabirim eklemektir:
public record Point<T>(T X, T Y) : IAdditionOperators<Point<T>, Translation<T>, Point<T>>
where T : IAdditionOperators<T, T, T>
Son olarak, ekleme gerçekleştirirken, bu tür için ek kimlik değerini tanımlayan bir özelliğe sahip olmak yararlı olur. Bu özellik için yeni bir arabirim vardır: IAdditiveIdentity<TSelf,TResult>. öğesinin çevirisi {0, 0} , eklemeli kimliktir: Sonuçta elde edilen nokta, sol işlenenle aynıdır.
IAdditiveIdentity<TSelf, TResult> Arabirim, AdditiveIdentitykimlik değerini döndüren tek bir salt okunur özelliği tanımlar. bu Translation<T> arabirimi uygulamak için birkaç değişikliğe ihtiyaç duyar:
using System.Numerics;
public record Translation<T>(T XOffset, T YOffset) : IAdditiveIdentity<Translation<T>, Translation<T>>
where T : IAdditionOperators<T, T, T>, IAdditiveIdentity<T, T>
{
public static Translation<T> AdditiveIdentity =>
new Translation<T>(XOffset: T.AdditiveIdentity, YOffset: T.AdditiveIdentity);
}
Burada birkaç değişiklik var, bu nedenle bunları tek tek inceleyelim. İlk olarak, Translation türünün IAdditiveIdentity arabirimini uyguladığını belirtirsiniz.
public record Translation<T>(T XOffset, T YOffset) : IAdditiveIdentity<Translation<T>, Translation<T>>
Daha sonra aşağıdaki kodda gösterildiği gibi arabirim üyesini uygulamayı deneyebilirsiniz:
public static Translation<T> AdditiveIdentity =>
new Translation<T>(XOffset: 0, YOffset: 0);
Türüne bağlı olduğundan 0 yukarıdaki kod derlenemiyor. Yanıt: 0 için IAdditiveIdentity<T>.AdditiveIdentity kullanın. Bu değişiklik, kısıtlamalarınızın artık T uygulayan IAdditiveIdentity<T> içermesi gerektiği anlamına gelir. Bunun sonucunda aşağıdaki uygulama elde edebilirsiniz:
public static Translation<T> AdditiveIdentity =>
new Translation<T>(XOffset: T.AdditiveIdentity, YOffset: T.AdditiveIdentity);
Artık bu kısıtlamayı öğesine Translation<T>eklediğinize göre, öğesine de aynı kısıtlamayı Point<T>eklemeniz gerekir:
using System.Numerics;
public record Point<T>(T X, T Y) : IAdditionOperators<Point<T>, Translation<T>, Point<T>>
where T : IAdditionOperators<T, T, T>, IAdditiveIdentity<T, T>
{
public static Point<T> operator +(Point<T> left, Translation<T> right) =>
left with { X = left.X + right.XOffset, Y = left.Y + right.YOffset };
}
Bu örnek, genel matematik arabirimlerinin nasıl oluşturulduğuna bir göz atmanızı sağladı. Nasıl yapılacağını öğrendinsiniz:
- Yöntemin herhangi bir sayısal türle kullanılabilmesi için arabirime dayalı
INumber<T>bir yöntem yazın. - Yalnızca bir matematiksel işlemi destekleyen bir tür uygulamak için ekleme arabirimlerine dayalı bir tür oluşturun. Bu tür, başka şekillerde oluşturulabilmesi için aynı arabirimler için desteğini bildirir. Algoritmalar, matematik işleçlerinin en doğal söz dizimi kullanılarak yazılır.
Bu özelliklerle denemeler yapın ve geri bildirimleri kaydedin. Visual Studio'da Geri Bildirim Gönder menü öğesini kullanabilir veya GitHub'daki roslyn deposunda yeni bir sorun oluşturabilirsiniz. Herhangi bir sayısal türle çalışan genel algoritmalar oluşturun. Tür bağımsız değişkeninin yalnızca sayı benzeri özelliklerin bir alt kümesini uyguladığı bu arabirimleri kullanarak algoritmalar oluşturun. Bu özellikleri kullanan yeni arabirimler oluşturmasanız bile bunları algoritmalarınızda kullanmayı deneyebilirsiniz.