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.
Not alın
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
Özellik belirtimlerini C# dil standardına benimseme işlemi hakkında daha fazla bilgi edinmek için
Şampiyon sorunu: https://github.com/dotnet/csharplang/issues/49
Özet
Motivasyon
Gerçekleştirilen geçersiz kılmaların, geçersiz kılınan metodla aynı türü geri döndürme zorunluluğuna bir geçici çözüm olarak, farklı metod adlarının oluşturulması sıkça rastlanan bir kodlama desenidir.
Bu, fabrika düzeninde yararlı olabilir. Örneğin, Roslyn kod tabanında şuna sahip olurduk.
class Compilation ...
{
public virtual Compilation WithOptions(Options options)...
}
class CSharpCompilation : Compilation
{
public override CSharpCompilation WithOptions(Options options)...
}
Ayrıntılı tasarım
Bu, C# dilinde
Sınıf Yöntemini Geçersiz Kılma
Sınıf geçersiz kılma (§15.6.5) yöntemlerinde mevcut kısıtlama
- Geçersiz kılma yöntemi ve geçersiz kılınan temel yöntem aynı dönüş türüne sahiptir.
olarak değiştirildi
- Geçersiz kılma yönteminin, kimlik dönüşümü ile dönüştürülebilir bir dönüş türü olmalıdır veya eğer yöntem bir değer döndürüyorsa - başvuru döndürmesi değil - örtük başvuru dönüşümünün geçersiz kılınan temel yöntemin dönüş türüne uygulanması gerekir. §13.1.0.5'e bakın.
Bu listeye aşağıdaki ek gereksinimler eklenir:
- Geçersiz kılma yönteminin dönüş türü, bir kimlik dönüşümü ile dönüştürülebilir olmalı veya (yöntem bir değer döndürüyor ve referans döndürmüyor ise, §13.1.0.5) geçersiz kılma yönteminin doğrudan veya dolaylı temel türlerinde bildirilen, geçersiz kılınan temel yöntemin her bir geçersiz kılmasının dönüş türüne örtük bir referans dönüşümü sağlamalıdır.
- Geçersiz kılma yönteminin dönüş türü en az geçersiz kılma yöntemi kadar erişilebilir olmalıdır (Erişilebilirlik etki alanları - §7.5.3).
Bu kısıtlama, private
sınıfındaki bir geçersiz kılma yönteminin private
dönüş türüne sahip olmasına izin verir. Ancak, public
dönüş türüne sahip olmak için public
türünde bir public
geçersiz kılma yöntemi gerektirir.
Sınıf Özelliği ve Dizin Oluşturucu Geçersiz Kılma
Sınıf geçersiz kılma (§15.7.6) özelliklerinde var olan kısıtlama
Geçersiz kılma özelliği bildirimi devralınan özellik ile tam olarak aynı erişilebilirlik değiştiricilerini ve adını belirtecektir ve geçersiz kılma türü ile devralınan özellikarasında bir kimlik dönüştürme
olacaktır. Devralınan özelliğin yalnızca tek bir erişimcisi varsa (devralınan özellik salt okunur veya salt yazılırsa), üstüne yazılan özellik yalnızca bu erişimciyi içermelidir. Devralınan özellik her iki erişimciyi de içeriyorsa (devralınan özellik okuma-yazma ise), geçersiz kılma özelliği tek bir erişimci veya her iki erişimciyi de içerebilir.
olarak değiştirildi
Geçersiz kılma mülkü bildirimi, devralınan mülkle tam olarak aynı erişilebilirlik değiştiricilerini ve adını belirtecektir ve kimlik dönüştürmesi veya (devralınan mülk salt okunursa ve değer döndürmüşse - başvuru dönüşü§13.1.0.5) geçersiz kılma mülkünün türünden devralınan mülkün türüne örtük başvuru dönüştürmesi. Devralınan özelliğin yalnızca tek bir erişimcisi varsa (devralınan özellik salt okunur veya salt yazılırsa), üstüne yazılan özellik yalnızca bu erişimciyi içermelidir. Devralınan özellik her iki erişimciyi de içeriyorsa (devralınan özellik okuma-yazma ise), geçersiz kılma özelliği tek bir erişimci veya her iki erişimciyi de içerebilir. Geçersiz kılınan özelliğin türü, geçersiz kılan özellik kadar erişilebilir olmalıdır (Erişilebilirlik etki alanları - §7.5.3).
Aşağıdaki taslak belirtiminin geri kalanı, daha sonra dikkate alınması gereken arabirim yöntemlerinin kovaryant dönüşlerine ek bir uzantı önerir.
Arayüz Yöntemi, Özelliği ve Dizinleyici Geçersiz Kılma
C# 8.0'da DIM özelliği ile bir arabirimde izin verilen üye türlerine ek olarak, override
üyelerine ve kovaryant dönüşlere destek ekleniyor. Bunlar, sınıflar için belirtilen override
üyelerin kurallarına uyar ve aşağıdaki farkları içerir:
Sınıflarda aşağıdaki metin:
Geçersiz kılma bildirimiyle geçersiz kılınan temel yöntem, olarak bilinir.
M
sınıfında bildirilen bir geçersiz kılma yöntemiC
için, geçirilen temel yöntem,C
doğrudan temel sınıfıyla başlayarakC
'nin her bir temel sınıfı incelenerek belirlenir ve her ardışık doğrudan temel sınıf bu incelemeye dahil edilir. Belirli bir temel sınıf türünde, tür bağımsız değişkenlerinin yerine konması sonrasındaM
ile aynı imzaya sahip en az bir erişilebilir yöntem bulunduğunda bu süreç tamamlanır.
arabirimler için ilgili belirtim verilmiştir:
Geçersiz kılma bildirimiyle geçersiz kılınan temel yöntem, olarak bilinir.
M
arabiriminde bildirilen geçersiz kılma metoduI
için, yerine geçen üst metot,I
'nin doğrudan veya dolaylı üst arabirimlerinin her biri incelenerek belirlenir. Aynı imzaya sahip erişilebilir bir metot bildiren arabirimler kümesi, tür parametreleri değiştirildiğindeM
ile aynı imzaya sahip olacak şekilde toplanır. Bu arabirim kümesinde, bu kümedeki her tür için bir kimlik veya örtük başvuru dönüşümü olanen çok türetilmiş birtürü varsa ve o tür benzersiz bir yöntem bildirimi içeriyorsa, bu,geçersiz kılınan temel yöntemdir.
Benzer şekilde, override
sınıflar için belirtilen arabirimlerde özelliklerine ve dizin oluşturucularına izin veririz.
İsim Arama
Günümüzde, sınıf override
bildirimlerinin varlığında ad araması, tanımlayıcının niteleyicisinin türünden başlayarak sınıf hiyerarşisindeki en türetilmiş override
bildiriminden (veya niteleyici olmadığında this
) elde edilen üye detaylarını uygulayarak ad aramasının sonucunu değiştirir. Örneğin, §12.6.2.2 İlgili parametreler belgesinde şunlar vardır
Sınıflarda tanımlanan sanal yöntemler ve dizin oluşturucular için parametre listesi, alıcının statik türüyle başlarken ve temel sınıflarında arama yaparken bulunan işlev üyesinin ilk bildiriminden veya geçersiz kılmasından seçilir.
buna ekliyoruz
Arabirimlerde tanımlanan sanal yöntemler ve dizin oluşturucular için parametre listesi, işlev üyesinin geçersiz kılma bildirimini içeren türler arasında en türetilmiş türde bulunan işlev üyesinin bildiriminden veya geçersiz kılmasından seçilir. Tür benzersiz değilse, bu derleme zamanı hatasıdır.
Bir özelliğin veya dizin oluşturucu erişiminin sonuç türü için, mevcut metin
I
bir örnek özelliği tanımlarsa sonuç,E
ilişkili örnek ifadesi ve özelliğin türü olan ilişkili bir tür ile özellik erişimidir.T
bir sınıf türüyse,T
ile başlayıp temel sınıflarında arama yaparken bulunan özelliğin ilk bildiriminden veya geçersiz kılmasından ilişkili tür seçilir.
ile zenginleştirildi
T
bir arabirim türüyse, ilişkili tür,T
'in en türevlenmiş hali veya doğrudan ya da dolaylı temel arabirimlerinden birinde bulunan özelliğin bildiriminden veya geçersiz kılmasından seçilir. Tür benzersiz değilse, bu derleme zamanı hatasıdır.
§12.8.12.3 Dizin Oluşturucu erişiminde de benzer bir değişiklik yapılması gerekiyor
§12.8.10 Çağırma ifadelerinde var olan metni genişletiyoruz
- Aksi takdirde sonuç, yöntem veya temsilcinin dönüş türüne bağlı olan bir değerdir. Çağırma bir örnek yöntemine aitse ve alıcı
T
bir sınıf türündeyse, ilişkili tür,T
ile başlayıp temel sınıflarında arama yaparken bulunan yöntemin ilk bildiriminden veya geçersiz kılınmasından seçilir.
ile
Eğer çağırma bir nesne yöntemi ise ve alıcı arabirim tipi
T
ise, ilişkili tür,T
ve onun doğrudan ve dolaylı temel arabirimleri arasından en çok türetilen arabirimde bulunan yöntemin bildiriminden veya geçersiz kılınmasından seçilir. Tür benzersiz değilse, bu derleme zamanı hatasıdır.
Örtük Arabirim Uygulamaları
Belirtimin bu bölümü
Arabirim eşleme amacıyla, bir sınıf üyesi
A
aşağıdaki durumlarda arabirim üyesiB
eşleşir:
A
veB
yöntemlerdir veA
veB
ad, tür ve resmi parametre listeleri aynıdır.A
veB
özelliklerdir,A
veB
adı ve türü aynıdır veA
B
ile aynı erişimcilere sahiptir (A
açık arabirim üyesi uygulaması değilse ek erişimcilere izin verilir).A
veB
olaylardır veA
veB
adı ve türü aynıdır.A
veB
dizin oluşturuculardır,A
veB
türü ve resmi parametre listeleri aynıdır veA
B
ile aynı erişimcilere sahiptir (A
açık bir arabirim üyesi uygulaması değilse ek erişimcilere izin verilir).
aşağıdaki gibi değiştirilir:
Arabirim eşleme amacıyla, bir sınıf üyesi
A
aşağıdaki durumlarda arabirim üyesiB
eşleşir:
A
veB
yöntemlerdir.A
veB
'ün adları ve resmi parametre listeleri aynıdır.A
dönüş türü,B
'nın dönüş türüne olan örtük referans dönüşümü ile kimlik aracılığıylaB
dönüş türüne dönüştürülebilir.A
veB
, özelliklerdir;A
veB
'ün adları aynıdır;A
,B
ile aynı erişimcilere sahiptir (A
, açık bir arabirim üyesi uygulaması değilse ek erişimcilere izin verilir); veA
türü, kimlik dönüştürmesi yoluyla veya eğerB
salt okunur bir özellikse,A
dönüş türüne örtülü bir başvuru dönüştürmesiyle uyarlanabilir.A
veB
olaylardır veA
veB
adı ve türü aynıdır.A
veB
dizin oluşturuculardır,A
veB
resmi parametre listeleri aynıdır,A
B
ile aynı erişimcilere sahiptir (A
açık bir arabirim üyesi uygulaması değilse ek erişimcilere izin verilir) veA
türü kimlik dönüştürme yoluylaB
dönüş türüne dönüştürülebilir veyaA
salt okunur bir dizin oluşturucuysa örtük başvuru dönüştürmesi.
Bu, teknik olarak, aşağıdaki program bugün "C1.M" yazdırırken, önerilen revizyonda "C2.M" yazdıracağı için önemli bir değişikliktir.
using System;
interface I1 { object M(); }
class C1 : I1 { public object M() { return "C1.M"; } }
class C2 : C1, I1 { public new string M() { return "C2.M"; } }
class Program
{
static void Main()
{
I1 i = new C2();
Console.WriteLine(i.M());
}
}
Önemli bu değişiklik nedeniyle, örtük uygulamalarda kovaryant dönüş türlerini desteklemeyebiliriz.
Arabirim Uygulama Kısıtlamaları
Açık bir arabirim uygulamasının, temel arabirimlerindeki herhangi bir geçersiz kılmada belirtilen dönüş türünden daha az türetilmiş olmayan bir dönüş türünü belirtmesi gerektiğine dair bir kurala ihtiyacımız olacaktır.
API Uyumluluğu etkileri
TBD
Açık Sorunlar
Belirtim, çağıranın daha ayrıntılı dönüş türünü nasıl elde ettiğini belirtmez. Muhtemelen bu, arayanların en fazla türetilmiş geçersiz kılmanın parametre tanımlarını alma yöntemine benzer bir şekilde yapılacaktır.
Aşağıdaki arabirimlere sahipsek:
interface I1 { I1 M(); }
interface I2 { I2 M(); }
interface I3: I1, I2 { override I3 M(); }
I3
'de I1.M()
ve I2.M()
yöntemlerinin "birleştirildiğini" unutmayın.
I3
uygularken her ikisini de birlikte uygulamak gerekir.
Genellikle özgün yönteme başvurmak için açık bir uygulama gerekir. Soru şu ki, bir sınıfta
class C : I1, I2, I3
{
C IN.M();
}
Bu ne anlama geliyor? N ne olmalıdır?
I1.M
veya I2.M
(her ikisini birden değil) uygulamaya izin vermemizi ve bunu her ikisinin de bir uygulaması olarak değerlendirmemizi öneriyorum.
Dezavantaj -ları
- [ ] Her dil değişikliği kendi maliyetini karşılamalıdır.
- [ ] Derin devralma hiyerarşileri söz konusu olduğunda bile performansın makul olduğundan emin olmamız gerekir
- [ ] Çeviri stratejisi yapıtlarının, eski derleyicilerden yeni IL kullanırken bile dil semantiğini etkilemediğinden emin olmamız gerekir.
Alternatif
Dil kurallarını biraz gevşeterek kaynakta izin verebiliriz.
// Possible alternative. This was not implemented.
abstract class Cloneable
{
public abstract Cloneable Clone();
}
class Digit : Cloneable
{
public override Cloneable Clone()
{
return this.Clone();
}
public new Digit Clone() // Error: 'Digit' already defines a member called 'Clone' with the same parameter types
{
return this;
}
}
Çözülmemiş sorular
- [ ] Bu özelliği kullanmak için derlenmiş API'ler dilin eski sürümlerinde nasıl çalışacak?
Tasarım toplantıları
- https://github.com/dotnet/roslyn/issues/357bazı tartışmalar.
- https://github.com/dotnet/csharplang/blob/master/meetings/2020/LDM-2020-01-08.md
- Yalnızca C# 9.0'da sınıf yöntemlerini geçersiz kılmayı destekleme kararına yönelik çevrimdışı tartışma.
C# feature specifications