Aracılığıyla paylaş


Arabirimlerdeki statik soyut üyeler

Dikkat

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/4436

Özet

Arabirimlerin, soyut statik üyeleri belirtmesine izin verilir ve bu üyeler için açık veya örtük uygulamalar sağlamak, bu arabirimleri uygulayan sınıflar ve yapılar için zorunludur. Üyelere, arabirim tarafından kısıtlanmış tür parametrelerinden erişilebilir.

Motivasyon

Şu anda statik üyeler üzerinde soyutlama ve bu statik üyeleri tanımlayan türler arasında geçerli olan genelleştirilmiş kod yazmanın bir yolu yoktur. Bu durum özellikle yalnızca statik bir formda üye türleri (özellikle işleçler) için sorunludur.

Bu özellik, belirli işleçlerin varlığını belirten arabirim kısıtlamalarıyla temsil edilen sayısal türler üzerinde genel algoritmalara izin verir. Bu nedenle algoritmalar şu işleçler açısından ifade edilebilir:

// Interface specifies static properties and operators
interface IAddable<T> where T : IAddable<T>
{
    static abstract T Zero { get; }
    static abstract T operator +(T t1, T t2);
}

// Classes and structs (including built-ins) can implement interface
struct Int32 : …, IAddable<Int32>
{
    static Int32 IAddable.operator +(Int32 x, Int32 y) => x + y; // Explicit
    public static int Zero => 0;                          // Implicit
}

// Generic algorithms can use static members on T
public static T AddAll<T>(T[] ts) where T : IAddable<T>
{
    T result = T.Zero;                   // Call static operator
    foreach (T t in ts) { result += t; } // Use `+`
    return result;
}

// Generic method can be applied to built-in and user-defined types
int sixtyThree = AddAll(new [] { 1, 2, 4, 8, 16, 32 });

Sözdizimi

Arabirim üyeleri

Bu özellik statik arabirim üyelerinin sanal olarak bildirilmesine izin verir.

C# 11'in öncesi kurallar

C# 11'in öncesinde, arabirimlerdeki örnek üyeleri örtük olarak soyuttur (veya varsayılan bir uygulama varsa sanaldır), ancak isteğe bağlı olarak bir abstract (veya virtual) değiştiriciye sahip olabilir. Sanal olmayan örnek üyeleri açıkça sealedolarak işaretlenmelidir.

Günümüzde statik arabirim üyeleri örtük olarak sanal değildir ve abstract, virtual veya sealed değiştiricilere izin vermez.

Teklif

Soyut statik üyeler

Alanlar dışındaki statik arabirim üyelerinin de abstract değiştiricisine sahip olması gerekir. Soyut statik üyelerin gövdeye sahip olmasına izin verilmez (veya özellikler söz konusu olduğunda, erişimcilerin gövdeye sahip olmasına izin verilmez).

interface I<T> where T : I<T>
{
    static abstract void M();
    static abstract T P { get; set; }
    static abstract event Action E;
    static abstract T operator +(T l, T r);
    static abstract bool operator ==(T l, T r);
    static abstract bool operator !=(T l, T r);
    static abstract implicit operator T(string s);
    static abstract explicit operator string(T t);
}
Sanal statik üyeler

Alanlar dışındaki statik arabirim üyelerinin de virtual değiştiricisine sahip olması gerekir. Sanal statik üyelerin bir gövdeye sahip olması gerekir.

interface I<T> where T : I<T>
{
    static virtual void M() {}
    static virtual T P { get; set; }
    static virtual event Action E;
    static virtual T operator +(T l, T r) { throw new NotImplementedException(); }
}
Belirgin olarak sanal olmayan statik üyeler

Sanal olmayan örnek üyeleriyle simetri için, statik üyelere (alanlar dışında) varsayılan olarak sanal olmayan olsalar bile isteğe bağlı bir sealed değiştiriciye izin verilmelidir:

interface I0
{
    static sealed void M() => Console.WriteLine("Default behavior");
    
    static sealed int f = 0;
    
    static sealed int P1 { get; set; }
    static sealed int P2 { get => f; set => f = value; }
    
    static sealed event Action E1;
    static sealed event Action E2 { add => E1 += value; remove => E1 -= value; }
    
    static sealed I0 operator +(I0 l, I0 r) => l;
}

Arabirim üyelerinin uygulanması

Bugünün kuralları

Sınıflar ve yapılar, arabirimlerin soyut örnek üyelerini örtük veya açıkça uygulayabilir. Bir arabirim üyesinin örtük olarak uygulanması, bir sınıfın veya yapının tipik (sanal veya sanal olmayan) üye bildirimidir ve bu bildirim aynı zamanda arabirim üyesini de "rastlantısal olarak" uygular. Üye bir temel sınıftan bile devralınabilir ve bu nedenle sınıf bildiriminde bile mevcut olmaz.

Açıkça uygulanan arabirim üyesi, söz konusu arabirim üyesini tanımlamak için nitelenmiş bir ad kullanır. Uygulamaya, sınıfta veya yapıda bir üye olarak doğrudan erişilemez, yalnızca arabirim üzerinden erişilebilir.

Teklif

Statik soyut arabirim üyelerinin örtük uygulanmasını kolaylaştırmak için sınıflarda ve yapılarda yeni söz dizimi gerekmez. Mevcut statik üye bildirimleri bu amaca hizmet eder.

Statik soyut arabirim üyelerinin açık uygulamaları, static değiştiricisi ile birlikte nitelenmiş bir ad kullanır.

class C : I<C>
{
    string _s;
    public C(string s) => _s = s;
    static void I<C>.M() => Console.WriteLine("Implementation");
    static C I<C>.P { get; set; }
    static event Action I<C>.E // event declaration must use field accessor syntax
    {
        add { ... }
        remove { ... }
    }
    static C I<C>.operator +(C l, C r) => new C($"{l._s} {r._s}");
    static bool I<C>.operator ==(C l, C r) => l._s == r._s;
    static bool I<C>.operator !=(C l, C r) => l._s != r._s;
    static implicit I<C>.operator C(string s) => new C(s);
    static explicit I<C>.operator string(C c) => c._s;
}

Anlambilim

İşletimci kısıtlamaları

Bugün tüm birli ve ikili işleç bildirimlerinin, işlenenlerinden en az birinin T veya T?türünde olması gerekir; burada T kapsayan türün örnek türüdür.

Kısıtlanmış bir işlenenin, "kapsayan türün örnek türü" olarak kabul edilen bir tür parametresi olmasına izin verilmesi için bu gereksinimlerin gevşetilmesi gerekmektedir.

Tür parametresinin T "kapsayan türün örnek türü" olarak sayılabilmesi için aşağıdaki gereksinimleri karşılaması gerekir:

  • T, işleç bildiriminin gerçekleştiği arabirimdeki bir doğrudan tür parametresidir ve
  • T doğrudan belirtimlerin "örnek türü" olarak adlandırdığı şeyle kısıtlanır; yani tür bağımsız değişkenleri olarak kullanılan kendi tür parametrelerine sahip çevresindeki arabirim.

Eşitlik işleçleri ve dönüşümleri

== ve != işleçlerinin soyut/sanal bildirimlerinin yanı sıra örtük ve açık dönüştürme işleçlerinin soyut/sanal bildirimlerine arabirimlerde izin verilir. Türetilmiş arabirimlerin de bunları uygulamasına izin verilir.

Önceki bölümde tanımlandığı gibi, == ve != işleçleri için en az bir parametre türü, "kapsayan türün örnek türü" olarak değerlendirilen bir tür parametresi olmalıdır.

Statik soyut üyelerin uygulanması

Bir sınıf veya yapıdaki statik üye bildiriminin statik soyut arabirim üyesini uygulamak için ne zaman dikkate alınacağı ve uygulandığında hangi gereksinimlerin geçerli olduğuyla ilgili kurallar örnek üyeleriyle aynıdır.

TBD: Burada henüz düşünmediğimiz ek veya farklı kurallar gerekebilir.

Arabirimler, tür bağımsız değişkenleri olarak

https://github.com/dotnet/csharplang/issues/5955 tarafından ortaya atılan sorunu ele aldık ve bir arabirimin tür bağımsız değişkeni (https://github.com/dotnet/csharplang/blob/main/meetings/2022/LDM-2022-03-28.md#type-hole-in-static-abstracts) olarak kullanımıyla ilgili bir kısıtlama eklemeye karar verdik. https://github.com/dotnet/csharplang/issues/5955 tarafından önerilen ve LDM tarafından onaylanan kısıtlama aşağıdadır.

Bir arabirimde en belirgin uygulamaya sahip olmayan statik soyut/sanal üye içeren veya devralan bir arabirim, tür bağımsız değişkeni olarak kullanılamaz. Eğer tüm statik soyut/sanal üyelerin en özgül uygulaması varsa, arabirim bir tür argümanı olarak kullanılabilir.

Statik soyut arabirim üyelerine erişme

M bir arabirim T tarafından kısıtlandığında ve T.MT'nin erişilebilir statik soyut üyesi olduğunda I ifadesi kullanılarak M bir tür parametresinde statik soyut arabirim üyesine I erişilebilir.

T M<T>() where T : I<T>
{
    T.M();
    T t = T.P;
    T.E += () => { };
    return t + T.P;
}

Çalışma zamanında, kullanılan gerçek üye uygulaması, tür bağımsız değişkeni olarak sağlanan gerçek tür üzerinde bulunan uygulamadır.

C c = M<C>(); // The static members of C get called

Sorgu ifadeleri söz dizimi yeniden yazma olarak belirtimli olduğundan, kullandığınız sorgu işleçleri için statik üyelere sahip olduğu sürece C# aslında sorgu kaynağı olarak tür kullanmanızı sağlar! Başka bir deyişle, söz dizimi uyuyorsa, izin veririz! Bu davranışın özgün LINQ'te kasıtlı veya önemli olmadığını düşünüyoruz ve bunu tür parametrelerinde desteklemek için çalışmayı yapmak istemiyoruz. Dışarıda senaryolar varsa bunları duyarız ve bunu daha sonra benimsemeyi seçebiliriz.

Varyans güvenliği §18.2.3.2

Varyans güvenlik kuralları statik soyut üyelerin imzalarına uygulanmalıdır. https://github.com/dotnet/csharplang/blob/main/proposals/variance-safety-for-static-interface-members.md#variance-safety'de önerilen eklemenin, ayarlamak üzere düzenlenmesi gerekiyor

Bu kısıtlamalar, statik üyelerin bildirimleri içindeki türlerin oluşumları için geçerli değildir.

için

Bu kısıtlamalar, sanal olmayan, soyut olmayan statik üyeler bildirimleri içindeki türlerin oluşumları için geçerli değildir.

§10.5.4 Kullanıcı tanımlı örtük dönüştürmeler

Aşağıdaki madde işareti noktaları

  • S, S₀ ve T₀türlerini belirleyin.
    • Eğer E'ın bir türü varsa, S o tür olsun.
    • S veya T null atanabilir değer türleriyse, Sᵢ ve Tᵢ temel türleri olarak kabul edin; aksi takdirde Sᵢ ve Tᵢ sırasıyla S ve Tolarak kabul edin.
    • Sᵢ veya Tᵢ tür parametreleriyse, S₀ ve T₀ etkili temel sınıfları olmasına izin verin; aksi takdirde S₀ ve T₀ sırasıyla Sₓ ve Tᵢolmasına izin verin.
  • Kullanıcı tanımlı dönüştürme işleçlerinin dikkate alınacağı Dtür kümesini bulun. Bu küme S0 (S0 bir sınıf veya yapıysa), S0 temel sınıflarından (S0 bir sınıfsa) ve T0 (T0 bir sınıf veya yapıysa) oluşur.
  • geçerli kullanıcı tanımlı ve yükseltilmiş dönüştürme işleçleri kümesini bulun, U. Bu küme, D kapsayan bir türden Starafından kapsanan bir türe dönüştüren T sınıfları ve yapıları tarafından bildirilen kullanıcı tanımlı ve aşırı yüklenmiş örtük dönüştürme işleçlerinden oluşur. U boşsa, dönüştürme tanımsız olur ve derleme zamanı hatası oluşur.

aşağıdaki gibi ayarlanır:

  • S, S₀ ve T₀türlerini belirleyin.
    • Eğer E'ın bir türü varsa, S o tür olsun.
    • S veya T null atanabilir değer türleriyse, Sᵢ ve Tᵢ temel türleri olarak kabul edin; aksi takdirde Sᵢ ve Tᵢ sırasıyla S ve Tolarak kabul edin.
    • Sᵢ veya Tᵢ tür parametreleriyse, S₀ ve T₀ etkili temel sınıfları olmasına izin verin; aksi takdirde S₀ ve T₀ sırasıyla Sₓ ve Tᵢolmasına izin verin.
  • geçerli kullanıcı tanımlı ve yükseltilmiş dönüştürme işleçleri kümesini bulun, U.
    • Kullanıcı tanımlı dönüştürme işleçlerinin dikkate alınacağı D1tür kümesini bulun. Bu küme S0 (S0 bir sınıf veya yapıysa), S0 temel sınıflarından (S0 bir sınıfsa) ve T0 (T0 bir sınıf veya yapıysa) oluşur.
    • geçerli kullanıcı tanımlı ve yükseltilmiş dönüştürme işleçleri kümesini bulun, U1. Bu küme, D1 kapsayan bir türden Starafından kapsanan bir türe dönüştüren T sınıfları ve yapıları tarafından bildirilen kullanıcı tanımlı ve aşırı yüklenmiş örtük dönüştürme işleçlerinden oluşur.
    • U1 boş değilse, UU1'dur. Yoksa
      • Kullanıcı tanımlı dönüştürme işleçlerinin dikkate alınacağı D2tür kümesini bulun. Bu küme, Sᵢetkili arabirim kümesi ve temel arabirimlerinden (Sᵢ bir tür parametresiyse) ve Tᵢetkili arabirim kümesi (Tᵢ bir tür parametresiyse) oluşur.
      • geçerli kullanıcı tanımlı ve yükseltilmiş dönüştürme işleçleri kümesini bulun, U2. Bu küme, D2 kapsayan bir türden Starafından kapsadığı bir türe dönüştüren T arabirimleri tarafından bildirilen kullanıcı tanımlı ve kaldırılmış örtük dönüştürme işleçlerinden oluşur.
      • U2 boş değilse, o zaman UU2 olur
  • U boşsa, dönüştürme tanımsız olur ve derleme zamanı hatası oluşur.

§10.3.9 Kullanıcı tanımlı açık dönüştürmeler

Aşağıdaki madde işareti noktaları

  • S, S₀ ve T₀türlerini belirleyin.
    • Eğer E'ın bir türü varsa, S o tür olsun.
    • S veya T null atanabilir değer türleriyse, Sᵢ ve Tᵢ temel türleri olarak kabul edin; aksi takdirde Sᵢ ve Tᵢ sırasıyla S ve Tolarak kabul edin.
    • Sᵢ veya Tᵢ tür parametreleriyse, S₀ ve T₀ etkili temel sınıfları olmasına izin verin; aksi takdirde S₀ ve T₀ sırasıyla Sᵢ ve Tᵢolmasına izin verin.
  • Kullanıcı tanımlı dönüştürme işleçlerinin dikkate alınacağı Dtür kümesini bulun. Bu küme S0 (S0 bir sınıf veya yapıysa), S0 temel sınıflarından (S0 bir sınıfsa), T0 (T0 bir sınıf veya yapıysa) ve T0 temel sınıflarından (T0 bir sınıfsa) oluşur.
  • geçerli kullanıcı tanımlı ve yükseltilmiş dönüştürme işleçleri kümesini bulun, U. Bu küme, D sınıfları veya yapıları tarafından bildirilen ve S tarafından kapsanan veya kapsadığı bir türden Ttarafından kapsanan veya kapsadığı bir türe dönüşüm yapan kullanıcı tanımlı ve yükseltilmiş örtük veya açık dönüştürme operatörlerinden oluşmaktadır. U boşsa, dönüştürme tanımsız olur ve derleme zamanı hatası oluşur.

aşağıdaki gibi ayarlanır:

  • S, S₀ ve T₀türlerini belirleyin.
    • Eğer E'ın bir türü varsa, S o tür olsun.
    • S veya T null atanabilir değer türleriyse, Sᵢ ve Tᵢ temel türleri olarak kabul edin; aksi takdirde Sᵢ ve Tᵢ sırasıyla S ve Tolarak kabul edin.
    • Sᵢ veya Tᵢ tür parametreleriyse, S₀ ve T₀ etkili temel sınıfları olmasına izin verin; aksi takdirde S₀ ve T₀ sırasıyla Sᵢ ve Tᵢolmasına izin verin.
  • geçerli kullanıcı tanımlı ve yükseltilmiş dönüştürme işleçleri kümesini bulun, U.
    • Kullanıcı tanımlı dönüştürme işleçlerinin dikkate alınacağı D1tür kümesini bulun. Bu küme S0 (S0 bir sınıf veya yapıysa), S0 temel sınıflarından (S0 bir sınıfsa), T0 (T0 bir sınıf veya yapıysa) ve T0 temel sınıflarından (T0 bir sınıfsa) oluşur.
    • geçerli kullanıcı tanımlı ve yükseltilmiş dönüştürme işleçleri kümesini bulun, U1. Bu küme, D1 sınıfları veya yapıları tarafından bildirilen ve S tarafından kapsanan veya kapsadığı bir türden Ttarafından kapsanan veya kapsadığı bir türe dönüşüm yapan kullanıcı tanımlı ve yükseltilmiş örtük veya açık dönüştürme operatörlerinden oluşmaktadır.
    • U1 boş değilse, UU1'dur. Yoksa
      • Kullanıcı tanımlı dönüştürme işleçlerinin dikkate alınacağı D2tür kümesini bulun. Bu küme, Sᵢetkili arabirim kümesi ve temel arabirimlerinden (Sᵢ bir tür parametresiyse) ve Tᵢetkili arabirim kümesi ve temel arabirimlerinden (Tᵢ bir tür parametresiyse) oluşur.
      • geçerli kullanıcı tanımlı ve yükseltilmiş dönüştürme işleçleri kümesini bulun, U2. Bu küme, D2 arabirimleri tarafından bildirilen, S tarafından kapsanan veya Ttarafından kapsanan bir türe dönüştüren kullanıcı tanımlı ve kullanıcı tarafından kaldırılmış veya açıkça belirtilmiş dönüştürme işleçlerinden oluşur.
      • U2 boş değilse, o zaman UU2 olur
  • U boşsa, dönüştürme tanımsız olur ve derleme zamanı hatası oluşur.

Varsayılan uygulamalar

Bu teklifin ek özelliği, arabirimlerdeki statik sanal üyelerin de sanal/soyut üyeler gibi varsayılan uygulamalara sahip olmasını sağlamaktır.

Buradaki bir komplikasyon, varsayılan uygulamaların diğer statik sanal üyeleri "sanal olarak" çağırmak istemesidir. Statik sanal üyelerin arabirimi üzerinden doğrudan çağrılabilmesi için, geçerli statik yöntemin gerçekten çağrıldığı "self" türünü temsil eden gizli bir tür parametresinin geçmesi gerekir. Bu karmaşık, pahalı ve potansiyel olarak kafa karıştırıcı görünüyor.

Statik sanal üyelerin tür parametrelerinde yalnızca çağrılabilmesini geçerli teklifin sınırlamalarını koruyan daha basit bir sürümü ele aldık. Statik sanal üyeleri olan arabirimler genellikle "self" türünü temsil eden açık bir tür parametresine sahip olacağından, bu büyük bir kayıp sayılmaz: diğer statik sanal üyeler yalnızca bu öz türde çağrılabilir. Bu sürüm çok daha basit ve oldukça uygulanabilir görünüyor.

https://github.com/dotnet/csharplang/blob/main/meetings/2022/LDM-2022-01-24.md#default-implementations-of-abstract-statics olarak, https://github.com/dotnet/csharplang/blob/main/proposals/csharp-8.0/default-interface-methods.md'da belirlenen kuralları izleyerek/genişleterek statik üyelerin Varsayılan Uygulamalarını desteklemeye karar verdik.

Desen eşleştirme

Aşağıdaki kod göz önünde bulundurulduğunda, kullanıcı "True" yazdırmasını makul bir şekilde bekleyebilir (sabit desen satır içinde yazılmışsa olduğu gibi):

M(1.0);

static void M<T>(T t) where T : INumberBase<T>
{
    Console.WriteLine(t is 1); // Error. Cannot use a numeric constant
    Console.WriteLine((t is int i) && (i is 1)); 
}

Ancak, desenin giriş türü doubleolmadığından, sabit 1 deseni önce gelen T'yi int'e karşı tür kontrolü yapar. Bu sezgisel olmadığından, gelecekteki bir C# sürümü INumberBase<T>'dan türetilen türlerle sayısal eşleştirme için daha iyi bir işlem ekleyene kadar engellenmiştir. Bunu yapmak için, INumberBase<T>'ı tüm "sayıların" türeyeceği temel tür olarak açıkça tanımlayacağız ve sayısal bir sabit desenini temsil edemediğimiz bir sayı türüyle eşleştirmeye çalışıyorsak (örneğin, INumberBase<T>ile kısıtlanmış bir tür parametresi veya INumberBase<T>'den türeyen kullanıcı tanımlı bir sayı türü) deseni engelleyeceğiz.

Resmi olarak, sabit desenler için desen-uyumlu 'in tanımına özel bir durum ekliyoruz:

Sabit desen, bir ifadenin değerini sabit bir değerle test ediyor. Sabit, bir literal, bildirilen bir const değişkeninin adı veya numaralandırma sabiti gibi herhangi bir sabit ifade olabilir. Giriş değeri açık bir tür olmadığında, sabit ifade örtük olarak eşleşen ifadenin türüne dönüştürülür; Giriş değerinin türü, sabit ifadenin türüyle desen uyumlu değilse, desen eşleştirme işlemi bir hatadır. Eşleştirilen sabit ifade sayısal bir değerse, giriş değeri System.Numerics.INumberBase<T>'den devralan bir türdür ve sabit ifadeden giriş değerinin türüne sabit dönüştürme yoktur; desen eşleştirme işlemi bir hatadır.

İlişkisel desenler için de benzer bir özel durum ekliyoruz:

Giriş, girişin sol işleneni ve verilen sabiti sağ işlenen olarak geçerli olan uygun bir yerleşik ikili ilişkisel işlecin tanımlandığı bir tür olduğunda, bu işlecin değerlendirmesi ilişkisel desenin anlamı olarak alınır. Aksi takdirde, açık bir null atanabilir veya kutulama kaldırılabilir dönüştürme kullanarak girişi ifadenin türüne dönüştürüriz. Böyle bir dönüştürme yoksa bu bir derleme zamanı hatasıdır. Derleme zamanı hatası oluşur, eğer giriş türü System.Numerics.INumberBase<T> türünden türetilen veya System.Numerics.INumberBase<T> ile kısıtlandırılan bir tür parametresiyse ve giriş türü için tanımlanmış uygun bir yerleşik ikili ilişkisel operatör yoksa. Dönüştürme başarısız olursa desenin eşleşmediği kabul edilir. Dönüştürme başarılı olursa desen eşleştirme işleminin sonucu e OP v ifadesinin değerlendirilmesinin sonucudur; burada e dönüştürülen giriştir, OP ilişkisel işleç ve v sabit ifadedir.

Dezavantaj -ları

  • "statik soyut" yeni bir kavramdır ve C# kavramının kavramsal yüküne anlamlı bir şekilde eklenir.
  • Bunu oluşturmak ucuz bir özellik değildir. Buna değdiğinden emin olmamız gerekir.

Alternatif

Yapısal kısıtlamalar

Alternatif bir yaklaşım, doğrudan ve açıkça bir tür parametresinde belirli işleçlerin bulunmasını gerektiren "yapısal kısıtlamalara" sahip olmaktır. Bunun dezavantajları şunlardır: - Bunun her seferinde yazılması gerekir. Adlandırılmış kısıtlamaya sahip olmak daha iyi görünüyor. - Bu tamamen yeni bir kısıtlama türüdür, ancak önerilen özellik mevcut arabirim kısıtlamaları kavramını kullanır. - Yalnızca operatörler için çalışabilir, diğer türdeki statik üyeler içinse (kolayca) çalışmaz.

Çözülmemiş sorular

Statik soyut arabirimler ve statik sınıflar

Daha fazla bilgi için bkz. https://github.com/dotnet/csharplang/issues/5783 ve https://github.com/dotnet/csharplang/blob/main/meetings/2022/LDM-2022-02-16.md#static-abstract-interfaces-and-static-classes.

Tasarım toplantıları