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.
19.1 Genel
Arabirim bir sözleşme tanımlar. Arabirim uygulayan bir sınıf veya yapı, sözleşmesine uymalıdır. Bir arabirim birden çok temel arabirimden devralabilir ve bir sınıf veya yapı birden çok arabirim uygulayabilir.
Arabirimler , §19.4'te açıklandığı gibi çeşitli üye türleri içerebilir. Arabirimin kendisi, bildirmiş olduğu işlev üyelerinin bazıları veya tümü için bir uygulama sağlayabilir. Arabirimin uygulama sağlamadığı üyeler soyut. Uygulamaları, arabirimi uygulayan sınıflar veya yapılar ya da geçersiz kılma tanımı sağlayan türetilmiş arabirim tarafından sağlanmalıdır.
Not: Geçmişe dönük olarak, arabirime yeni bir işlev üyesi eklemek, bu arabirim türünün mevcut tüm tüketicilerini etkilemektedir; Bu büyük bir değişiklikti. Arabirim işlevi üye uygulamalarının eklenmesi, geliştiricilerin bir arabirimi yükseltmesine olanak tanırken tüm uygulayıcıların bu uygulamayı geçersiz kılmasını sağladı. Arabirimin kullanıcıları uygulamayı hataya neden olmayan bir değişiklik olarak kabul edebilir; ancak gereksinimleri farklıysa, sağlanan uygulamaları geçersiz kılabilir. son not
19.2 Arabirim bildirimleri
19.2.1 Genel
interface_declaration, yeni bir arabirim türü bildiren bir type_declaration (§14.7) olur.
interface_declaration
: attributes? interface_modifier* 'partial'? 'interface'
identifier variant_type_parameter_list? interface_base?
type_parameter_constraints_clause* interface_body ';'?
;
interface_declaration isteğe bağlı bir öznitelik kümesi (§23) ve ardından isteğe bağlı bir interface_modifierkümesi (§19.2.2) ve ardından isteğe bağlı kısmi değiştirici (§15.2.7) ve ardından anahtar sözcüğü interface ve arabirimi adlandıran bir tanımlayıcıdan oluşur. ardından isteğe bağlı bir variant_type_parameter_list belirtimi (§19.2.3) ve ardından isteğe bağlı interface_base belirtimi (§19.2.4)), ardından isteğe bağlı bir type_parameter_constraints_clausebelirtimi (§15.2.5), ardından bir interface_body (§19.3) ve isteğe bağlı olarak noktalı virgül.
variant_type_parameter_listsağlanmadıkça, bir arabirim bildirimi type_parameter_constraints_clausesağlamamalıdır.
variant_type_parameter_list sağlayan bir arabirim bildirimi, genel bir arabirim bildirimidir. Ayrıca, genel bir sınıf bildiriminin veya genel bir yapı bildiriminin içinde yer alan herhangi bir arabirim, kendiliğinden genel bir arabirim bildirimidir, çünkü içeren türün tür bağımsız değişkenleri, oluşturulacak türü oluşturmak için sağlanmalıdır (§8.4).
19.2.2 Arabirim değiştiricileri
bir interface_declaration isteğe bağlı olarak bir dizi arabirim değiştirici içerebilir:
interface_modifier
: 'new'
| 'public'
| 'protected'
| 'internal'
| 'private'
| unsafe_modifier // unsafe code support
;
unsafe_modifier (§24.2) yalnızca güvenli olmayan kodda (§24) kullanılabilir.
Aynı değiştiricinin bir arabirim bildiriminde birden çok kez görünmesi bir derleme zamanı hatasıdır.
new Değiştiriciye yalnızca bir sınıf içinde tanımlanan arabirimlerde izin verilir. Arabirimin, §15.3.5'te açıklandığı gibi, devralınan bir üyeyi aynı isimle gizlediğini belirtir.
public, protected, internalve private değiştiricileri arabirimin erişilebilirliğini denetler. Arabirim bildiriminin gerçekleştiği bağlama bağlı olarak, bu değiştiricilerin yalnızca bazılarına izin verilebileceği (§7.5.2). Kısmi tür bildirimi (§15.2.7) bir erişilebilirlik belirtimi içerdiğinde (, public, protectedve internal değiştiricileri aracılığıylaprivate), §15.2.2'deki kurallar geçerlidir.
19.2.3 Değişken türü parametre listeleri
19.2.3.1 Genel
Değişken türü parametre listeleri yalnızca arabirim ve temsilci türlerinde oluşabilir. Sıradan type_parameter_list'lerin farkı, her tür parametresindeki isteğe bağlı variance_annotation'dır.
variant_type_parameter_list
: '<' variant_type_parameter (',' variant_type_parameter)* '>'
;
variant_type_parameter
: attributes? variance_annotation? type_parameter
;
variance_annotation
: 'in'
| 'out'
;
Varyans ek açıklaması out olduğunda, tür parametresinin birlikte değişken olduğu söylenir. Varyans açıklaması in ise, tür parametresinin kontravaryant olduğu söylenir. Varyans ek açıklaması yoksa tür parametresinin sabit olduğu söylenir.
Örnek: Aşağıdakilerde:
interface C<out X, in Y, Z> { X M(Y y); Z P { get; set; } }
Xkovaryant,Ykontravariant veZsabittir.son örnek
Genel bir arabirim birden çok bölümde (§15.2.3) bildirilirse, her kısmi bildirim her tür parametresi için aynı varyansı belirtecektir.
19.2.3.2 Varyans güvenliği
Türün tür parametre listesinde varyans ek açıklamalarının oluşumu, tür bildiriminde türlerin oluşabileceği yerleri kısıtlar.
Aşağıdakilerden biri barındırılıyorsa, T türü çıkış güvensizdir:
-
Tdeğişken karşıtı bir tür parametresidir -
Tçıktı için güvensiz öğe türüne sahip bir dizi türüdür -
T, aşağıdakilerden en az birininSᵢ,... Aₑtutulduğu genel bir türden oluşturulan bir arabirim veya temsilci türüdür:S<Xᵢ, ... Xₑ>Aᵢ-
Xᵢkovaryant veya invaryanttır veAᵢçıkış açısından güvensizdir. -
Xᵢdeğişken veya sabittir veAᵢgirişe güvenli değildir.
-
Aşağıdakilerden biri barındırılıyorsa , T türü girişi güvenli değildir:
-
Tortak değişken türünde bir parametredir -
Tgiriş-güvensiz öğe türüne sahip bir dizi türüdür -
T, aşağıdakilerden en az birininS<Aᵢ,... Aₑ>tutulduğu genel bir türden oluşturulan bir arabirim veya temsilci türüdür:S<Xᵢ, ... Xₑ>Aᵢ-
Xᵢkovaryant veya sabittir veAᵢgiriş açısından güvensizdir. -
Xᵢkontravaryant veya invaryanttır veAᵢçıkış-güvensizdir.
-
Sezgisel olarak, çıkış konumunda güvenli olmayan bir çıkış türü yasaktır ve giriş konumunda güvenli olmayan giriş türü yasaktır.
Bir tür çıkış-güvenli ise çıkış-güvensiz değildir ve giriş-güvenli ise giriş-güvensiz değildir.
19.2.3.3 Varyans dönüştürme
Varyans anotasyonlarının amacı, arabirim ve temsilci türlerine daha esnek (ancak yine de tür güvenli) dönüşümler sağlamaktır. Bu amaçla örtük (§10.2) ve açık dönüştürme (§10.3) tanımları, aşağıdaki gibi tanımlanan varyans-dönüştürülebilirlik kavramını kullanır:
Bir tür T<Aᵢ, ..., Aᵥ>, değişken tür parametreleri T<Bᵢ, ..., Bᵥ> ile ilan edilmiş T bir arabirim veya temsilci türüyse ve her değişken tür parametresi T<Xᵢ, ..., Xᵥ> için aşağıdakilerden biri geçerliyse, Xᵢ türüne değişkenlikle dönüştürülebilir.
-
Xᵢkovaryanttır veAᵢ'denBᵢ'ye örtük bir referans veya kimlik dönüştürmesi vardır. -
Xᵢkontravaryanttır veBᵢ'denAᵢ'ye örtük bir başvuru veya kimlik dönüştürmesi vardır. -
Xᵢsabittir veAᵢileBᵢarasında bir kimlik dönüştürmesi vardır.
19.2.4 Temel arabirimler
Bir arabirim, arabirimin açık temel arabirims'leri olarak adlandırılan sıfır veya daha fazla arabirim türünden devralabilir. Bir arabirimde bir veya daha fazla açık temel arabirim olduğunda, bu arabirimin bildiriminde arabirim tanımlayıcısını iki nokta üst üste ve virgülle ayrılmış temel arabirim türlerinin listesi izler.
Türetilmiş arabirim, temel arabirimlerde bildirilen devralınan üyeleri (§7.7.2.3) gizleyen veya temel arabirimlerde bildirilen devralınan üyeleri (§19.6.2) açıkça uygulayan yeni üyeler bildirebilir.
interface_base
: ':' interface_type_list
;
Açık temel arabirimler arabirim türleri (§8.4, §19.2) oluşturulabilir. Temel arabirim kendi başına bir tür parametresi olamaz, ancak kapsamdaki tür parametrelerini içerebilir.
Oluşturulmuş bir arabirim türü için, açık temel arabirimler, genel tür tanımındaki açık temel arabirim bildirimlerindekileri alarak ve her bir temel arabirim bildirimindeki type_parameter yerine, oluşturulmuş türün karşılık gelen type_argument ile değiştirerek oluşturulur.
Bir arabirimin açık taban arabirimleri en az arabirimin kendisi kadar erişilebilir olmalıdır (§7.5.5).
Not: Örneğin, bir
privatearabiriminininternalkısmında bir veyapublicarabirimini belirtmek bir derleme zamanı hatasıdır. son not
Bir arabirimin doğrudan veya dolaylı olarak kendisinden devralması derleme zamanı hatasıdır.
Bir arabirimin temel arabirimleriaçık temel arabirimler ve bunların temel arabirimleridir. Başka bir deyişle, temel arabirim kümesi, açık temel arabirimlerin, bunların açık temel arabirimlerinin vb. tam geçişli kapanışıdır. Arabirim, temel arabirimlerinin tüm üyelerini devralır.
Örnek: Aşağıdaki kodda
interface IControl { void Paint(); } interface ITextBox : IControl { void SetText(string text); } interface IListBox : IControl { void SetItems(string[] items); } interface IComboBox: ITextBox, IListBox {}temel arabirimleri
IComboBox,IControlveITextBoxşeklindedirIListBox. Başka bir deyişle, yukarıdakiIComboBoxarabirimiSetText,SetItemsvePaintgibi üyeleri devralır.son örnek
Oluşturulmuş bir genel türden devralınan üyeler, tür değiştirme işleminden sonra devralınır. Diğer bir ifadeyle, üyedeki tüm bileşen türlerinde, temel sınıf bildiriminin tür parametrelerinin yerine class_base belirtiminde kullanılan ilgili tür bağımsız değişkenleri kullanılır.
Örnek: Aşağıdaki kodda
interface IBase<T> { T[] Combine(T a, T b); } interface IDerived : IBase<string[,]> { // Inherited: string[][,] Combine(string[,] a, string[,] b); }Tür parametresi
IDerivedileCombinedeğiştirildikten sonra arabirim,Tarayüzünü devralır vestring[,]yöntemini uygular.son örnek
Arabirim uygulayan bir sınıf veya yapı, arabirimin tüm temel arabirimlerini de örtük olarak uygular.
Kısmi arabirim bildiriminin (§15.2.7) birden çok parçasındaki arabirimlerin işlenmesi ,15.2.4.3'te daha ayrıntılı olarak ele alınıyor.
Bir arabirimin her temel arabirimi çıkış açısından güvenli olmalıdır (§19.2.3.2).
19.3 Arabirim gövdesi
Arabirimin interface_body , arabirimin üyelerini tanımlar.
interface_body
: '{' interface_member_declaration* '}'
;
19.4 Arabirim üyeleri
19.4.1 Genel
Bir arabirimin üyeleri, temel arabirimlerden devralınan üyeler ve arabirimin kendisi tarafından bildirilen üyelerdir.
interface_member_declaration
: constant_declaration
| field_declaration
| method_declaration
| property_declaration
| event_declaration
| indexer_declaration
| static_constructor_declaration
| operator_declaration
| type_declaration
;
Bu yan tümce, sınıflardaki üyelerin açıklamasını (§15.3) arabirimler için kısıtlamalarla genişletmektedir. Arabirim üyeleri, aşağıdaki ek kurallarla member_declarationkullanılarak bildirilir:
- finalizer_declaration izin verilmez.
- constructor_declarationörnek oluşturuculara izin verilmez.
- Tüm arabirim üyeleri örtük olarak genel erişime sahiptir; ancak statik oluşturucular (§15.12) dışında açık erişim değiştiriciye (§7.5.2) izin verilir.
- Değiştirici
abstract, gövdeleri olmayan arabirim işlevi üyeleri için örtülüdür; bu değiştirici açıkça verilebilir. - veya
virtualdeğiştirici kullanılmadığı sürecesealed, bildirimi gövde içeren bir arabirim örneği işlev üyesi örtük birprivateüyedir. Değiştiricivirtualaçıkça verilebilir. - Bir
privatearabirimin veyasealedişlev üyesinin bir gövdesi olmalıdır. - bir
privateişlev üyesi değiştiricisinesealedsahip olmayacaktır. - Türetilmiş arabirim, temel arabirimde bildirilen soyut veya sanal üyeyi geçersiz kılabilir.
- Açıkça uygulanan bir işlev üyesinin değiştiricisi
sealedolmamalıdır.
constant_declaration (§15.4) gibi bazı bildirimlerin arabirimlerde hiçbir kısıtlaması yoktur.
Bir arabirimin devralınan üyeleri, özellikle arabirimin bildirim alanının bir parçası değildir. Bu nedenle, bir arabirimin devralınan üyeyle aynı ada veya imzaya sahip bir üyeyi tanımlamasına izin verilir. Bu durum oluştuğunda, türetilmiş arabirim üyesinin temel arabirim üyesini gizley dediği söylenir. Devralınan üyenin gizlenmesi hata olarak kabul edilmez, ancak bir uyarıya (§7.7.2.3) neden olur.
Devralınan bir new üyeyi gizlemeyen bir bildirime değiştirici eklenirse, bu durumla ilgili bir uyarı verilir.
Not: Sınıftaki
objectüyeler hiçbir arabirimin (§19.4) üyesi değildir. Ancak, sınıftakiobjectüyeler herhangi bir arabirim türünde (§12.5) üye arama yoluyla kullanılabilir. son not
Birden çok bölümde bildirilen bir arabirimin üyeleri kümesi (§15.2.7), her bölümde bildirilen üyelerin birleşimidir. Arabirim bildiriminin tüm bölümlerinin gövdeleri aynı bildirim alanını (§7.3) paylaşır ve her üyenin (§7.7) kapsamı tüm parçaların gövdelerine kadar uzanır.
Örnek: Bir üye
IAve özelliğiMiçin uygulaması olan bir arabirimPdüşünün. Uygulama türüCveyaMiçinPbir uygulama sağlamaz. Derleme zamanı türü örtük olarak veyaIAolarak dönüştürülebilenIBbir arabirim olan bir başvuru aracılığıyla erişilmelidir. Bu üyeler türündekiCbir değişkende üye araması aracılığıyla bulunmaz.interface IA { public int P { get { return 10; } } public void M() { Console.WriteLine("IA.M"); } } interface IB : IA { public new int P { get { return 20; } } void IA.M() { Console.WriteLine("IB.M"); } } class C : IB { } class Test { public static void Main() { C c = new C(); ((IA)c).M(); // cast needed Console.WriteLine($"IA.P = {((IA)c).P}"); // cast needed Console.WriteLine($"IB.P = {((IB)c).P}"); // cast needed } }ve
IAarabirimleriIBiçinde üyeyeMdoğrudan adla erişilebilir. Ancak, yöntemindeMainveyac.M()yazamıyoruzc.P, bu adlar görünür değil. Bunları bulmak için uygun arabirim türüne atamalar gerekir. içindeMbildirimiIB, açık arabirim uygulama söz dizimini kullanır. Bu, bu yöntemin içindekiIAyöntemi geçersiz kılması için gereklidir; değiştiricioverridebir işlev üyesine uygulanamayabilir. son örnek
19.4.2 Arabirim alanları
Bu yan tümcesi, arabirimlerde bildirilen alanlar için §15.5 sınıflarındaki alanların açıklamasını genişletmektedir.
Arabirim alanları aşağıdaki ek kurallarla field_declaration(§15.5.1) kullanılarak bildirilir:
- Field_declaration bir örnek alanı bildirmesi bir derleme zamanı hatasıdır.
Örnek: Aşağıdaki program çeşitli türlerdeki statik üyeleri içerir:
public interface IX { public const int Constant = 100; protected static int field; static IX() { Console.WriteLine("static members initialized"); Console.WriteLine($"constant = {IX.Constant}, field = {IX.field}"); field = 50; Console.WriteLine("static constructor has run"); } } public class Test: IX { public static void Main() { Console.WriteLine($"constant = {IX.Constant}, field = {IX.field}"); } }Üretilen çıkış şu şekildedir:
static members initialized constant = 100, field = 0 static constructor has run constant = 100, field = 50son örnek
Statik alanların ayrılması ve başlatılmasıyla ilgili bilgi için bkz. §19.4.8 .
19.4.3 Arabirim yöntemleri
Bu yan tümcesi, arabirimlerde bildirilen yöntemler için §15.6 sınıflarındaki yöntemlerin açıklamasını genişletmektedir.
Arabirim yöntemleri method_declaration(§15.6)) kullanılarak bildirilir. Arabirim yöntemi bildiriminin öznitelikleri, return_type, ref_return_type, tanımlayıcısı ve parameter_list , bir sınıftaki yöntem bildiriminin anlamlarıyla aynı anlama sahiptir. Arabirim yöntemleri aşağıdaki ek kurallara sahiptir:
method_modifier içermeyecektir
override.Gövdesi noktalı virgül (
;) olan bir yöntem;abstractabstractdeğiştirici gerekli değildir, ancak buna izin verilir.method_body olarak bir blok gövdesine veya ifade gövdesine
virtualsahip bir arabirim yöntemi bildirimidirvirtual; değiştirici gerekli değildir, ancak buna izin verilir.Bir method_declaration, type_parameter_listolmadığı sürece type_parameter_constraints_clause sahip olmayacaktır.
Bir sınıf yöntemi için belirtilen geçerli değiştirici birleşimleri için gereksinimlerin listesi aşağıdaki gibi genişletilmiştir:
- Extern olmayan statik bir bildirimin method_body olarak bir blok gövdesi veya ifade gövdesi olmalıdır.
- Extern olmayan bir sanal bildirimin method_body olarak bir blok gövdesi veya ifade gövdesi olmalıdır.
- Extern olmayan özel bir bildirimin method_body olarak bir blok gövdesi veya ifade gövdesi olmalıdır.
- Extern olmayan korumalı bir bildirimin method_body olarak bir blok gövdesi veya ifade gövdesi olmalıdır.
- Zaman uyumsuz bildirimin method_body olarak bir blok gövdesi veya ifade gövdesi olmalıdır.
Bir arabirim yönteminin tüm parametre türleri giriş-güvenli (§19.2.3.2) ve dönüş türü ya da
voidçıkış-güvenli olmalıdır.Tüm çıkış veya başvuru parametre türleri de çıkış açısından güvenli olmalıdır.
Not: Yaygın uygulama kısıtlamaları nedeniyle çıkış parametrelerinin giriş açısından güvenli olması gerekir. son not
Yöntemin herhangi bir tür parametresindeki her sınıf türü kısıtlaması, arabirim türü kısıtlaması ve tür parametresi kısıtlaması giriş açısından güvenli olmalıdır.
Bu kurallar, arabirimin herhangi bir kovaryant veya kontravaryant kullanımının tür güvenliğini korumasını sağlar.
Örnek:
interface I<out T> { void M<U>() where U : T; // Error }
Tüzerinde tür parametresi kısıtlaması olarakUkullanımının giriş açısından güvenli olmaması nedeniyle yanlış biçimlendirilmiştir.Bu kısıtlamanın yapılmaması durumunda tür güvenliğini aşağıdaki şekilde ihlal etmek mümkün olacaktır:
interface I<out T> { void M<U>() where U : T; } class B {} class D : B {} class E : B {} class C : I<D> { public void M<D>() {...} } ... I<B> b = new C(); b.M<E>();Aslında bu,
C.M<E>için bir çağrıdır. Ancak bu çağrının yapılabilmesi içinE'ninD'den türetilmesi gerektiğinden, tür güvenliği burada ihlal edilir.son örnek
Not: Yalnızca bir uygulama ile statik yöntem göstermekle kalmaz, aynı zamanda bu yöntem çağrıldığı ve doğru dönüş türüne ve imzaya sahip olduğu için aynı zamanda bir giriş noktası olduğunu gösteren bir örnek için
Main. son not
Bir arabirimde bildirilen uygulamalı bir sanal yöntem, türetilmiş bir arabirimde soyut olacak şekilde geçersiz kılınabilir. Bu, yeniden kısıtlama olarak bilinir.
Örnek:
interface IA { void M() { Console.WriteLine("IA.M"); } } interface IB: IA { abstract void IA.M(); // reabstraction of M }Bu, bir yöntemin uygulanmasının uygun olmadığı ve sınıflar uygulanarak daha uygun bir uygulama sağlanması gereken türetilmiş arabirimlerde yararlıdır. son örnek
19.4.4 Arabirim özellikleri
Bu yan tümcesi, arabirimlerde bildirilen özellikler için §15.7 sınıflarındaki özelliklerin açıklamasını genişletmektedir.
Arabirim özellikleri aşağıdaki ek kurallarla property_declaration(§15.7.1) kullanılarak bildirilir:
property_modifier içermeyecektir
override.Açık arabirim üyesi uygulaması bir accessor_modifier (§15.7.3) içermemelidir.
Türetilmiş bir arabirim, temel arabirimde bildirilen bir soyut arabirim özelliğini açıkça uygulayabilir.
Not: Arabirim örnek alanları içeremediğinden, örtük gizli örnek alanlarının bildirilmesi gerekeceğinden arabirim özelliği örnek otomatik özelliği olamaz. son not
Bir arabirim özelliğinin türü, bir get erişimcisi varsa çıkış-güvenli olmalı ve bir set erişimcisi varsa giriş-güvenli olmalıdır.
method_body olarak bir blok gövdesine veya ifade gövdesine
virtualsahip bir arabirim yöntemi bildirimidirvirtual; değiştirici gerekli değildir, ancak buna izin verilir.Uygulaması olmayan bir örnek property_declaration;
abstractabstractdeğiştirici gerekli değildir, ancak buna izin verilir. Hiçbir zaman otomatik olarak uygulanan bir özellik (§15.7.4) olarak kabul edilmez.
19.4.5 Arabirim olayları
Bu yan tümcesi, arabirimlerde bildirilen olaylar için §15.8 sınıflarındaki olayların açıklamasını genişletmektedir.
Arabirim olayları aşağıdaki ek kurallarla event_declaration(§15.8.1) kullanılarak bildirilir:
-
event_modifier içermeyecektir
override. - Türetilmiş arabirim, temel arabirimde (§15.8.5) bildirilen bir soyut arabirim olayı uygulayabilir.
- Bir örnekteki variable_declarators event_declarationherhangi birvariable_initializer içermesi derleme zamanı hatasıdır.
- veya
virtualdeğiştiricilerisealedolan bir örnek olayı erişimcileri bildirmelidir. Hiçbir zaman otomatik olarak uygulanan alan benzeri bir olay (§15.8.2) olarak kabul edilmez. - Değiştiricisi
abstractolan bir örnek olayı erişimcileri bildirmemelidir. - Bir arabirim olayının türü giriş açısından güvenli olmalıdır.
19.4.6 Arabirim dizin oluşturucuları
Bu yan tümce, arabirimlerde bildirilen dizin oluşturucular için §15.9 sınıflarındaki dizin oluşturucuların açıklamasını genişletmektedir.
Arabirim dizin oluşturucuları aşağıdaki ek kurallarla indexer_declaration(§15.9) kullanılarak bildirilir:
indexer_modifier içermeyecektir
override.İfade gövdesine sahip olan veya blok gövdesine veya ifade gövdesine sahip bir erişimci içeren bir indexer_declaration;
virtualvirtualdeğiştirici gerekli değildir, ancak buna izin verilir.Erişimci gövdeleri noktalı virgül ()
;olan birabstract;abstractdeğiştirici gerekli değildir, ancak buna izin verilir.Arabirim dizin oluşturucusunun tüm parametre türleri giriş açısından güvenli olmalıdır (§19.2.3.2).
Tüm çıkış veya başvuru parametre türleri de çıkış açısından güvenli olmalıdır.
Not: Yaygın uygulama kısıtlamaları nedeniyle çıkış parametrelerinin giriş açısından güvenli olması gerekir. son not
Bir arabirim dizinleyicisinin türü, bir get erişimcisi varsa çıkış açısından güvenli olmalı ve bir set erişimcisi varsa giriş açısından güvenli olmalıdır.
19.4.7 Arabirim işleçleri
Bu yan tümcesi, arabirimlerde bildirilen işleçler için §15.10 sınıflarındaki operator_declaration üyelerin açıklamasını genişletmektedir.
Arabirimdeki operator_declaration uygulamadır (§19.1).
Bir arabirimin dönüştürme, eşitlik veya eşitsizlik işleci bildirmesi derleme zamanı hatasıdır.
19.4.8 Arabirim statik oluşturucuları
Bu yan tümcesi, arabirimlerde bildirilen statik oluşturucular için §15.12 sınıflarındaki statik oluşturucuların açıklamasını genişletmektedir.
Kapalı (§8.4.3) arabirimi için statik oluşturucu, belirli bir uygulama etki alanında en fazla bir kez yürütülür. Statik bir oluşturucunun yürütülmesi, aşağıdaki eylemlerin ilki tarafından bir uygulama etki alanında gerçekleşecek şekilde tetikler:
- Arabirimin statik üyelerinden herhangi birine başvurulur.
- Yöntem, yürütmenin
Mainbaşladığı yöntemi (Main) içeren bir arabirim için çağrılmadan önce. - Bu arabirim bir üye için bir uygulama sağlar ve bu uygulamaya söz konusu üye için en özel uygulama (§19.4.10) olarak erişilir.
Not: Önceki eylemlerden hiçbirinin gerçekleşmemesi durumunda, arabirimi uygulayan tür örneklerinin oluşturulduğu ve kullanıldığı bir program için bir arabirim için statik oluşturucu yürütülmeyebilir. son not
Yeni bir kapalı arabirim türü başlatmak için, önce bu kapalı tür için yeni bir statik alan kümesi oluşturulur. Statik alanların her biri varsayılan değerine başlatılır. Ardından, statik alan başlatıcıları bu statik alanlar için yürütülür. Son olarak, statik oluşturucu yürütülür.
Not: Arabirim içinde bildirilen çeşitli statik üye türlerini (Main yöntemi dahil) kullanma örneği için bkz. §19.4.2 . son not
19.4.9 Arabirim iç içe türler
Bu yan tümcesi, arabirimlerde bildirilen iç içe türler için §15.3.9 sınıflarındaki iç içe türlerin açıklamasını genişletmektedir.
Variance_annotation (§19.2.3.1) ile bildirilen tür parametresi kapsamında bir sınıf türü, yapı türü veya numaralandırma türü bildirmek bir hatadır.
Örnek: Aşağıdaki bildirimi
Cbir hatadır.interface IOuter<out T> { class C { } // error: class declaration within scope of variant type parameter 'T' }son örnek
19.4.10 en özel uygulama
Her sınıf ve yapı, türü veya doğrudan ve dolaylı arabirimlerinde görünen uygulamalar arasında bu tür tarafından uygulanan tüm arabirimlerde bildirilen her sanal üye için en özel bir uygulamaya sahip olacaktır. En özel uygulama, diğer tüm uygulamalardan daha özel olan benzersiz bir uygulamadır.
Not: En özel uygulama kuralı, elmas arabirim devralma sonucunda ortaya çıkan bir belirsizliğin çakışmanın oluştuğu noktada programcı tarafından açıkça çözülmesini sağlar. son not
T ve arabirimleri I2I3uygulayan bir yapı veya sınıf türü için, burada I2 ve I3 her ikisi de bir üyeyi Ibildiren arabirimden M doğrudan veya dolaylı olarak türetilir, en özel uygulaması M şunlardır:
- uygulamasını
TbildirirseI.M, bu uygulama en özel uygulamadır. - Aksi takdirde, bir sınıfsa
Tve doğrudan veya dolaylı bir temel sınıf uygulamasını bildirirseI.M, en çok türetilmiş temel sınıfıTen özel uygulamadır. - Aksi takdirde,
I2veI3tarafındanTuygulanan veI3doğrudanI2veya dolaylı olarak türetilen arabirimler ise,I3.MdeğerindenI2.Mdaha özel bir uygulamadır. - Aksi takdirde, ne daha belirgin ne
I2.MdeI3.Mdaha belirgindir ve bir hata oluşur.
Örnek:
interface IA { void M() { Console.WriteLine("IA.M"); } } interface IB : IA { void IA.M() { Console.WriteLine("IB.M"); } } interface IC: IA { void IA.M() { Console.WriteLine("IC.M"); } } abstract class C: IB, IC { } // error: no most specific implementation for 'IA.M' abstract class D: IA, IB, IC // OK { public abstract void M(); }En özel uygulama kuralı, çakışmanın (yani elmas devralmadan kaynaklanan bir belirsizlik) çakışmanın ortaya çıktığı noktada programcı tarafından açıkça çözülmesini sağlar. son örnek
19.4.11 Arabirim üyesi erişimi
Arabirim üyelerine üye erişimi (§12.8.7) ve formun dizin oluşturucu erişimi (I.M) ifadeleri aracılığıyla erişilir. I[A]Burada I bir arabirim türü, sabit, M alan, yöntem, özellik veya bu arabirim türünün olayıdır ve A bir dizin oluşturucu bağımsız değişken listesidir.
Doğrudan veya dolaylı temel sınıfına Dsahip bir sınıfındaB, B doğrudan veya dolaylı olarak arabirimi I uygulayan ve I bir yöntemi M()tanımlayan ifadebase.M(), yalnızca statik olarak (base.M()) bir sınıf türündeki uygulamasına bağlanıyorsa M() geçerlidir.
Kesin olarak tek devralma olan arabirimler için (devralma zincirindeki her arabirim tam olarak sıfır veya bir doğrudan temel arabirime sahiptir), üye aramasının etkileri (§12.5), yöntem çağırma (§12.8.10.2) ve dizin oluşturucu erişimi (§12.8.12.4) kuralları, sınıflar ve yapılar ile tam olarak aynıdır: Daha fazla türetilmiş üye, aynı ada veya imzaya sahip daha az türetilmiş üyeleri gizler. Ancak, birden çok devralma arabirimleri için, iki veya daha fazla ilişkisiz temel arabirim aynı ada veya imzaya sahip üyeleri bildirdiğinde belirsizlikler oluşabilir. Bu alt bölümde, bazıları belirsizliklere yol açan ve bazıları belirsizliğe yol açmayan çeşitli örnekler gösterilir. Her durumda, açık dönüştürmeler belirsizlikleri çözmek için kullanılabilir.
Örnek: Aşağıdaki kodda
interface IList { int Count { get; set; } } interface ICounter { int Count { get; set; } } interface IListCounter : IList, ICounter {} class C { void Test(IListCounter x) { x.Count = 1; // Error ((IList)x).Count = 1; // Ok, invokes IList.Count.set ((ICounter)x).Count = 1; // Ok, invokes ICounter.Count } }Üye araması (§12.5)
CountiçindeIListCounterbelirsiz olduğundan, ilk deyim derleme zamanı hatasına neden olur. Örnekte gösterildiği gibi belirsizlik, uygun temel arabirim türüne geçirilerekxçözümlenir. Bu tür dönüştürmelerin çalışma zamanı maliyeti yoktur; yalnızca örneğin derleme zamanında daha az türetilmiş bir tür olarak görülmesidir.son örnek
Örnek: Aşağıdaki kodda
interface IInteger { void Add(int i); } interface IDouble { void Add(double d); } interface INumber : IInteger, IDouble {} class C { void Test(INumber n) { n.Add(1); // Invokes IInteger.Add n.Add(1.0); // Only IDouble.Add is applicable ((IInteger)n).Add(1); // Only IInteger.Add is a candidate ((IDouble)n).Add(1); // Only IDouble.Add is a candidate } }
n.Add(1)çağrısı, aşırı yük çözümleme kurallarınıIInteger.Adduygulayarak seçer. Benzer şekilde, çağrısın.Add(1.0)'yi seçerIDouble.Add. Açık atamalar eklendiğinde yalnızca bir aday yöntemi vardır ve bu nedenle belirsizlik yoktur.son örnek
Örnek: Aşağıdaki kodda
interface IBase { void F(int i); } interface ILeft : IBase { new void F(int i); } interface IRight : IBase { void G(); } interface IDerived : ILeft, IRight {} class A { void Test(IDerived d) { d.F(1); // Invokes ILeft.F ((IBase)d).F(1); // Invokes IBase.F ((ILeft)d).F(1); // Invokes ILeft.F ((IRight)d).F(1); // Invokes IBase.F } }
IBase.Füyesi,ILeft.Füyesi tarafından gizleniyor. Bu nedenled.F(1)çağrısı,ILeft.Füzerinden geçen erişim yolundaIBase.Fgizli görünmese deIRightöğesini seçer.Birden çok devralma arabirimlerinde gizlemeye yönelik sezgisel kural şudur: Bir üye herhangi bir erişim yolunda gizlenirse, tüm erişim yollarında gizlenir. tr-TR:
IDerivedileILeftüzerindenIBaseerişim yoluIBase.Föğesini gizlediği için,IDerivedileIRightüzerindenIBaseerişim yolunda üye de gizlidir.son örnek
19.5 Nitelenmiş arabirim üye adları
Arabirim üyesine bazen nitelikli arabirim üyesi adıyla başvurulur. Arabirim üyesinin tam adı, üyenin bildirildiği arabirimin adından, ardından bir nokta ve ardından üyenin adından oluşur. Üyenin tam adı, üyenin bildirildiği arabirime başvurur.
Örnek: Bildirimlere göre
interface IControl { void Paint(); } interface ITextBox : IControl { void SetText(string text); }
Paintöğesinin tam adıIControl.Paint'dir ve SetText'in tam adıITextBox.SetText'dir. Yukarıdaki örnektePaint'yeITextBox.Paintolarak başvurmak mümkün değildir.son örnek
Arabirim bir ad alanının parçası olduğunda, nitelikli arabirim üyesi adı ad alanı adını içerebilir.
Örnek:
namespace GraphicsLib { interface IPolygon { void CalculateArea(); } }Ad alanı içinde
GraphicsLib, hemIPolygon.CalculateAreahem deGraphicsLib.IPolygon.CalculateArea,CalculateAreayöntemi için nitelikli arabirim üye adlarıdır.son örnek
19.6 Arabirim uygulamaları
19.6.1 Genel
Arabirimler sınıflar ve yapılar tarafından uygulanabilir. Bir sınıfın veya yapının doğrudan bir arabirim uyguladığını belirtmek için, arabirim sınıfın veya yapının temel sınıf listesine eklenir.
Bir arabirim C uygulayan bir sınıf veya yapıI, içinde erişim sağlayabilen her IC üye için bir uygulama sağlamalı veya devralmalıdır. genel üyeleri, I genel üyelerinde Ctanımlanabilir. içinde I erişilebilir C olarak bildirilen genel olmayan üyeler, açık arabirim uygulaması (C) kullanılarak tanımlanabilir.
Arabirim eşlemesini (§19.6.5) karşılayan ancak eşleşen temel arabirim üyesini uygulamayan türetilmiş türde bir üye yeni bir üye tanıtır. Bu, arabirim üyesini tanımlamak için açık arabirim uygulaması gerektiğinde oluşur.
Örnek:
interface ICloneable { object Clone(); } interface IComparable { int CompareTo(object other); } class ListEntry : ICloneable, IComparable { public object Clone() {...} public int CompareTo(object other) {...} }son örnek
Doğrudan bir arabirim uygulayan bir sınıf veya yapı, arabirimin tüm temel arabirimlerini de örtük olarak uygular. Sınıf veya yapı, temel sınıf listesindeki tüm temel arabirimleri açıkça listelemese bile bu durum geçerlidir.
Örnek:
interface IControl { void Paint(); } interface ITextBox : IControl { void SetText(string text); } class TextBox : ITextBox { public void Paint() {...} public void SetText(string text) {...} }Burada,
TextBoxsınıfı hemIControlhem deITextBoxuygular.son örnek
Bir sınıf C doğrudan bir arabirim uyguladığında, öğesinden C türetilen tüm sınıflar da örtük olarak arabirimi uygular.
Sınıf bildiriminde belirtilen temel arabirimler arabirim türleri (§8.4, §19.2) oluşturulabilir.
Örnek: Aşağıdaki kod, bir sınıfın oluşturulmuş arabirim türlerini nasıl uygulayabileceğini gösterir:
class C<U, V> {} interface I1<V> {} class D : C<string, int>, I1<string> {} class E<T> : C<int, T>, I1<T> {}son örnek
Genel sınıf bildiriminin temel arabirimleri , §19.6.3'te açıklanan benzersizlik kuralını karşılayacaktır.
19.6.2 Açık arabirim üyesi uygulamaları
Arabirimleri uygulama amacıyla, bir sınıf, yapı veya arabirim açık arabirim üyesi uygulamalarıbildirebilir. Açık arabirim üyesi uygulaması, uygun arabirim üye adına başvuran bir yöntem, özellik, olay veya dizin oluşturucu bildirimidir. Temel arabirimde ortak olmayan bir üye uygulayan bir sınıf veya yapı, açık bir arabirim üyesi uygulaması bildirmelidir. Bir temel arabirimde üye uygulayan bir arabirim, açık bir arabirim üyesi uygulaması bildirmelidir.
Arabirim eşlemesini (§19.6.5) karşılayan türetilmiş arabirim üyesi, temel arabirim üyesini (§7.7.2) gizler. Değiştirici mevcut olmadığı sürece new derleyici bir uyarı yayınlar.
Örnek:
interface IList<T> { T[] GetElements(); } interface IDictionary<K, V> { V this[K key] { get; } void Add(K key, V value); } class List<T> : IList<T>, IDictionary<int, T> { public T[] GetElements() {...} T IDictionary<int, T>.this[int index] {...} void IDictionary<int, T>.Add(int index, T value) {...} }Burada
IDictionary<int,T>.thisveIDictionary<int,T>.Addaçık arabirim üyesi uygulamalarıdır.son örnek
Örnek: Bazı durumlarda, bir arabirim üyesinin adı uygulayan sınıf için uygun olmayabilir, bu durumda arabirim üyesi açık arabirim üyesi uygulaması kullanılarak uygulanabilir. Örneğin, dosya soyutlaması uygulayan bir sınıf, büyük olasılıkla dosya kaynağını serbest bırakma etkisine sahip bir
Closeüye işlevi uygular ve açık arabirim üyesi uygulamasını kullanarak arabiriminDisposeyöntemini uygularIDisposable:interface IDisposable { void Dispose(); } class MyFile : IDisposable { void IDisposable.Dispose() => Close(); public void Close() { // Do what's necessary to close the file System.GC.SuppressFinalize(this); } }son örnek
Bir yöntem çağırma, özellik erişimi, olay erişimi veya dizin oluşturucu erişiminde uygun arabirim üye adı aracılığıyla açık arabirim üyesi uygulamasına erişmek mümkün değildir. Açık arabirim örneği üye uygulamasına yalnızca bir arabirim örneği üzerinden erişilebilir ve bu durumda yalnızca üye adıyla başvurulur. Açık arabirim statik üye uygulamasına yalnızca arabirim adı üzerinden erişilebilir.
Açık bir arabirim üyesi uygulaması, §15.6 dışında extern veya async haricinde herhangi bir değiştirici içerdiğinde derleme zamanı hatası oluşur.
Açık arabirim yöntemi uygulaması, arabirimden herhangi bir tür parametresi kısıtlamasını devralır.
Açık arabirim yöntemi uygulamasındaki type_parameter_constraints_clause, yalnızca class'lerin uygulandığı struct'lara karşılık gelecek şekilde, devralınan kısıtlamalara göre sırasıyla referans veya değer türleri olarak bilinenler veya içerebilir. Açık arabirim yöntemi uygulamasının T? imzasında yer alan ve tür parametresi olan herhangi bir form T türü aşağıdaki gibi yorumlanır:
- Tür parametresi
classiçin birTkısıtlama eklenirseT?nullable bir başvuru türüdür; aksi takdirde - Tür parametresi
structiçin ya herhangi bir kısıtlama eklenmemişse ya da birTkısıtlama eklenirse,T?null atanabilir bir değer türü olur.
Örnek: Aşağıda, tür parametreleri söz konusu olduğunda kuralların nasıl çalıştığı gösterilmektedir:
#nullable enable interface I { void Foo<T>(T? value) where T : class; void Foo<T>(T? value) where T : struct; } class C : I { void I.Foo<T>(T? value) where T : class { } void I.Foo<T>(T? value) where T : struct { } }Tür parametresi kısıtlaması
where T : classolmadan, başvuru türü belirlenmiş tür parametresine sahip temel yöntem geçersiz kılınamaz. son örnek
Not: Açık arabirim üyesi uygulamaları diğer üyelerden farklı erişilebilirlik özelliklerine sahiptir. Açık arabirim üyesi uygulamalarına hiçbir zaman bir yöntem çağrısında veya özellik erişiminde uygun arabirim üyesi adı üzerinden erişilemediğinden, bunlar bir anlamda özeldir. Ancak, arabirim üzerinden erişilebildiği için, bir anlamda bildirildikleri arabirim kadar geneldirler. Açık arabirim üyesi uygulamaları iki birincil amaca hizmet eder:
- Açık arabirim üyesi uygulamalarına sınıf veya yapı örnekleri aracılığıyla erişilemediğinden, arabirim uygulamalarının bir sınıfın veya yapının ortak arabiriminden dışlanmasına izin verir. Bu, özellikle bir sınıf veya yapı, bu sınıfın veya yapının tüketicisini ilgilendirmeyen bir iç arabirim uyguladığında kullanışlıdır.
- Açık arabirim üyesi uygulamaları, aynı imzaya sahip arabirim üyelerinin kesinleştirilmesine olanak sağlar. Açık arabirim üyesi uygulamaları olmadan, bir sınıf, yapı veya arabirimin aynı imzaya ve dönüş türüne sahip arabirim üyelerinin farklı uygulamalarına sahip olması mümkün değildir; sınıf, yapı veya arabirimin tüm arabirim üyelerinde aynı imzaya sahip ancak farklı dönüş türlerine sahip herhangi bir uygulamaya sahip olması mümkün değildir.
son not
Açık arabirim üyesi uygulamasının geçerli olması için, sınıf, yapı veya arabirim, kendi temel sınıfındaki veya temel arabirim listesinde, uygun arabirim üye adı, türü, tür parametresi sayısı ve parametre türleri açık arabirim üyesi uygulamasınınkilerle tam olarak eşleşen bir üye içeren bir arabirim adlandırmalıdır. Arabirim işlevi üyesinin bir parametre dizisi varsa, ilgili açık arabirim üyesi uygulamasının karşılık gelen parametresinin params değiştiricisine sahip olmasına izin verilir, ancak zorunlu değildir. Arabirim işlevi üyesinin parametre dizisi yoksa, ilişkili açık arabirim üyesi uygulaması parametre dizisine sahip olmaz.
Örnek: Bu nedenle, aşağıdaki sınıfta
class Shape : ICloneable { object ICloneable.Clone() {...} int IComparable.CompareTo(object other) {...} // invalid }
IComparable.CompareTobildiriminin sonucu derleme zamanı hatasıdır çünküIComparableShapetemel sınıf listesinde yer almamakta veICloneable'nin temel arabirimi olmamaktadır. Benzer şekilde, bildirimlerdeclass Shape : ICloneable { object ICloneable.Clone() {...} } class Ellipse : Shape { object ICloneable.Clone() {...} // invalid }
ICloneable.CloneiçindekiEllipsebildirimi,ICloneable'ün temel sınıf listesindeEllipseaçıkça listelenmediği için derleme zamanı hatasıyla sonuçlanır.son örnek
Açık arabirim üyesi uygulamasının nitelikli arabirim üyesi adı, üyenin bildirildiği arabirime başvuracaktır.
Örnek: Bu nedenle, bildirimlerde
interface IControl { void Paint(); } interface ITextBox : IControl { void SetText(string text); } class TextBox : ITextBox { void IControl.Paint() {...} void ITextBox.SetText(string text) {...} }Paint'in açık arabirim üyesi uygulaması
IControl.Paintolarak yazılmalı,ITextBox.Paintolarak yazılmamalıdır.son örnek
19.6.3 Uygulanan arabirimlerin benzersizliği
Genel tür bildirimi tarafından uygulanan arabirimler, olası tüm yapı türleri için benzersiz kalacaktır. Bu kural olmadan, belirli yapılandırılmış türler için çağrılacak doğru yöntemi belirlemek mümkün olmazdı.
Örnek: Genel bir sınıf bildiriminin aşağıdaki gibi yazılması için izin verilmiş olduğunu varsayalım:
interface I<T> { void F(); } class X<U ,V> : I<U>, I<V> // Error: I<U> and I<V> conflict { void I<U>.F() {...} void I<V>.F() {...} }Buna izin verilseydi, aşağıdaki durumda hangi kodun yürütüleceğini belirlemek mümkün olmazdı:
I<int> x = new X<int, int>(); x.F();son örnek
Genel tür bildiriminin arabirim listesinin geçerli olup olmadığını belirlemek için aşağıdaki adımlar gerçekleştirilir:
- Genel bir sınıf, yapı veya arabirim bildiriminde
Ldoğrudan belirtilen arabirimlerin listesi olsunC. -
Löğesine,Liçinde zaten bulunan arabirimlerin temel arabirimlerini ekleyin. -
Liçindeki herhangi bir yineleneni kaldırın. -
C'den oluşturulan herhangi bir olası tür, tür bağımsız değişkenleriL'e yerine koyulduğundaLiçinde iki arayüzün aynı olmasına neden olursa, o zamanCbildirimi geçersizdir. Tüm olası yapı türleri belirlenirken kısıtlama bildirimleri dikkate alınmaz.
Not: Yukarıdaki sınıf bildiriminde
X, arabirim listesiLvel<U>'yiI<V>içerir.UveVaynı tür olduğunda bu iki arabirimin aynı türler olmasına neden olacağından bildirim geçersizdir. son not
Farklı devralma düzeylerinde belirtilen arabirimlerin birleştirilmesi mümkündür:
interface I<T>
{
void F();
}
class Base<U> : I<U>
{
void I<U>.F() {...}
}
class Derived<U, V> : Base<U>, I<V> // Ok
{
void I<V>.F() {...}
}
Bu kod, Derived<U,V> hem de I<U> ve I<V> uygulasa bile geçerlidir. Kod
I<int> x = new Derived<int, int>();
x.F();
yöntemini Derivediçinde çağırır çünkü Derived<int,int>' etkin bir şekilde yeniden uygular I<int> (§19.6.7).
19.6.4 Genel yöntemlerin uygulanması
Genel bir yöntem örtük olarak bir arabirim yöntemi uyguladığında, her yöntem türü parametresi için verilen kısıtlamalar her iki bildirimde de eşdeğer olacaktır (herhangi bir arabirim türü parametresi uygun tür bağımsız değişkenleriyle değiştirildikten sonra), burada yöntem türü parametreleri soldan sağa sıralı konumlarla tanımlanır.
Örnek: Aşağıdaki kodda:
interface I<X, Y, Z> { void F<T>(T t) where T : X; void G<T>(T t) where T : Y; void H<T>(T t) where T : Z; } class C : I<object, C, string> { public void F<T>(T t) {...} // Ok public void G<T>(T t) where T : C {...} // Ok public void H<T>(T t) where T : string {...} // Error }yöntemi
C.F<T>örtük olarak uygularI<object,C,string>.F<T>. Bu durumda,C.F<T>tüm tür parametrelerinde örtük bir kısıtlama olduğundanT: objectkısıtlamayıobjectbelirtmek için gerekli değildir (veya izin verilmez). Arabirim türü parametreleri karşılık gelen tür bağımsız değişkenleriyle değiştirildikten sonra, kısıtlamalar arabirimdekilerle eşleştiği içinC.G<T>yöntemiI<object,C,string>.G<T>'i örtük olarak uygular. Korumalı türler (C.H<T>bu örnekte) kısıtlama olarak kullanılamadığından yöntemstringkısıtlaması bir hatadır. Örtük arabirim yöntemi uygulamalarının kısıtlamalarının eşleşmesi gerektiğinden kısıtlamanın atlanması da hata olabilir. Bu nedenle, örtük olarak uygulamakI<object,C,string>.H<T>mümkün değildir. Bu arabirim yöntemi yalnızca açık bir arabirim üyesi uygulaması kullanılarak uygulanabilir:class C : I<object, C, string> { ... public void H<U>(U u) where U : class {...} void I<object, C, string>.H<T>(T t) { string s = t; // Ok H<T>(t); } }Bu durumda, açık arabirim üyesi uygulaması kesinlikle daha zayıf kısıtlamalara sahip bir ortak yöntemi çağırır. T'den s'ye atama geçerli çünkü, bu kısıtlama kaynak kodda ifade edilemez olsa bile,
TT: stringkısıtlamasını devralır. son örnek
Not: Genel bir yöntem açıkça bir arabirim yöntemi uyguladığında, uygulayan yöntem üzerinde hiçbir kısıtlamaya izin verilmez (§15.7.1, §19.6.2). son not
19.6.5 Arabirim eşlemesi
Sınıf veya yapı, sınıfın veya yapının temel sınıf listesinde listelenen arabirimlerin tüm soyut üyelerinin uygulamalarını sağlayacaktır. Bir uygulama sınıfı veya yapısında arabirim üyelerinin uygulamalarını bulma işlemi, arabirim eşlemesi olarak bilinir.
Bir sınıf veya yapı C için arabirim eşlemesi, temel sınıf listesinde Cbelirtilen her arabirimin her üyesi için bir uygulama bulur. Üyesinin bildirildiği arabirim olan I.M belirli bir arabirim üyesinin Iuygulaması, her bir sınıf, arabirim veya yapı Mile başlayıp S her bir temel sınıf için yinelenerek ve bir eşleşme bulunana kadar arabirimi uygulanarak Cbelirlenir:C
-
SetiketiIveMile eşleşen açık bir arabirim üyesi uygulamasının bildirimini içeriyorsa, bu üyeI.M'ün uygulamasıdır. - Aksi takdirde,
Sile eşleşen statik olmayan bir public üyenin bildiriminiMiçeriyorsa, bu üyeI.Muygulamasıdır. Birden fazla üye eşleşirse, hangi üyeninI.Muygulaması olduğu belirtilmez. Bu durum yalnızca,Soluşturulmuş bir tür ise ve genel türde bildirilen iki üyenin farklı imzalara sahip olduğu, ancak tür argümanlarının imzalarını özdeş hale getirmesi durumunda ortaya çıkabilir.
uygulamasının temel sınıf listesinde Cbelirtilen tüm arabirimlerin tüm üyeleri için uygulamalar bulunamazsa derleme zamanı hatası oluşur. Bir arabirimin üyeleri, temel arabirimlerden devralınan üyeleri içerir.
Yapılandırılmış arabirim türünün üyeleri, §15.3.3'te belirtilen karşılık gelen tür bağımsız değişkenleriyle değiştirilen herhangi bir tür parametresine sahip olarak kabul edilir.
Örnek: Örneğin, genel arabirim bildirimi göz önünde bulundurulduğunda:
interface I<T> { T F(int x, T[,] y); T this[int y] { get; } }oluşturulan arabirimde
I<string[]>şu üyeler bulunur:string[] F(int x, string[,][] y); string[] this[int y] { get; }son örnek
Arabirim eşleme amacıyla, aşağıdaki durumlarda bir sınıf, arabirim veya yapı üyesi A bir arabirim üyesiyle B eşleşir:
-
AveByöntemleridir ve ve'ninABadı, türü ve parametre listeleri aynıdır. -
AveBözellikleridir, adı ve türüABaynıdır veAile aynı erişimcilereBsahiptir (Aaçık bir arabirim üyesi uygulaması değilse ek erişimcilere izin verilir). -
AveBolayları, adı ve türüAileBaynıdır. -
AveBdizin oluşturucularıdır, türü ve parametre listeleriABaynıdır veA(Baçık bir arabirim üyesi uygulaması değilse ek erişimcilere sahip olması için izin verilir) ile aynı erişimcilereAsahiptir.
Arabirim eşleme algoritmasının önemli etkileri şunlardır:
- Açık arabirim üyesi uygulamaları, bir arabirim üyesi uygulayan sınıf veya yapı üyesini belirlerken aynı sınıf veya yapıdaki diğer üyelere göre önceliklidir.
- Genel olmayan veya statik üyeler arabirim eşlemeye katılmaz.
Örnek: Aşağıdaki kodda
interface ICloneable { object Clone(); } class C : ICloneable { object ICloneable.Clone() {...} public object Clone() {...} }
ICloneable.Cloneüyesi, açık arabirim üyesi uygulamaları diğer üyelere göre öncelikli olduğundan,CiçindeClone'teICloneableuygulaması olur.son örnek
Bir sınıf veya yapı aynı ad, tür ve parametre türlerine sahip bir üye içeren iki veya daha fazla arabirim uygularsa, bu arabirim üyelerinin her birini tek bir sınıf veya yapı üyesine eşlemek mümkündür.
Örnek:
interface IControl { void Paint(); } interface IForm { void Paint(); } class Page : IControl, IForm { public void Paint() {...} }Burada, hem
Painthem deIControlyöntemleri,IFormiçindekiPaintyöntemine eşlenir. Elbette iki yöntem için ayrı açık arabirim üyesi uygulamalarına sahip olmak da mümkündür.son örnek
Bir sınıf veya yapı gizli üyeleri içeren bir arabirim uygularsa, bazı üyelerin açık arabirim üyesi uygulamaları aracılığıyla uygulanması gerekebilir.
Örnek:
interface IBase { int P { get; } } interface IDerived : IBase { new int P(); }Bu arabirimin uygulanması için en az bir açık arabirim üyesi uygulaması gerekir ve aşağıdaki formlardan birini alır
class C1 : IDerived { int IBase.P { get; } int IDerived.P() {...} } class C2 : IDerived { public int P { get; } int IDerived.P() {...} } class C3 : IDerived { int IBase.P { get; } public int P() {...} }son örnek
Bir sınıf aynı temel arabirime sahip birden çok arabirim uyguladığında, temel arabirimin yalnızca bir uygulaması olabilir.
Örnek: Aşağıdaki kodda
interface IControl { void Paint(); } interface ITextBox : IControl { void SetText(string text); } interface IListBox : IControl { void SetItems(string[] items); } class ComboBox : IControl, ITextBox, IListBox { void IControl.Paint() {...} void ITextBox.SetText(string text) {...} void IListBox.SetItems(string[] items) {...} }temel sınıf listesinde adlandırılan
IControl,IControltarafından devralınanITextBox, veIControltarafından devralınanIListBoxiçin ayrı uygulamalara sahip olmak mümkün değildir. Aslında, bu arabirimler için ayrı bir kimlik diye bir şey yoktur. Bunun yerine,ITextBoxveIListBoxuygulamalarıIControl'nin aynı uygulamasını paylaşır veComboBoxiseIControl,ITextBoxveIListBoxolmak üzere üç arabirimi uyguladığı kabul edilir.son örnek
Bir temel sınıfın üyeleri arabirim eşlemesine katılır.
Örnek: Aşağıdaki kodda
interface Interface1 { void F(); } class Class1 { public void F() {} public void G() {} } class Class2 : Class1, Interface1 { public new void G() {} }
FiçindekiClass1yöntemi,Class2'suygulamasınınInterface1içinde kullanılır.son örnek
19.6.6 Arabirim uygulaması devralma
Bir sınıf, temel sınıfları tarafından sağlanan tüm arabirim uygulamalarını devralır.
Bir arabirimi açıkça yeniden uygulamadan türetilmiş bir sınıf, temel sınıflarından devraldığı arabirim eşlemelerini hiçbir şekilde değiştiremez.
Örnek: Bildirimlerde
interface IControl { void Paint(); } class Control : IControl { public void Paint() {...} } class TextBox : Control { public new void Paint() {...} }
Paintyöntemi,TextBoxiçindekiPaintyöntemini gizlerControl, ancakControl.Paint'ünIControl.Paint'e olan eşlemesini değiştirmez ve sınıf örnekleri ile arabirim örnekleri aracılığıyla yapılanPaintçağrıları aşağıdaki etkilere sahip olacaktır.Control c = new Control(); TextBox t = new TextBox(); IControl ic = c; IControl it = t; c.Paint(); // invokes Control.Paint(); t.Paint(); // invokes TextBox.Paint(); ic.Paint(); // invokes Control.Paint(); it.Paint(); // invokes Control.Paint();son örnek
Ancak, bir arabirim yöntemi bir sınıftaki bir sanal yönteme eşlendiğinde, türetilmiş sınıfların sanal yöntemi geçersiz kılıp arabirimin uygulamasını değiştirmesi mümkündür.
Örnek: Yukarıdaki bildirimleri yeniden yazma
interface IControl { void Paint(); } class Control : IControl { public virtual void Paint() {...} } class TextBox : Control { public override void Paint() {...} }şimdi aşağıdaki etkiler gözlemlenecektir
Control c = new Control(); TextBox t = new TextBox(); IControl ic = c; IControl it = t; c.Paint(); // invokes Control.Paint(); t.Paint(); // invokes TextBox.Paint(); ic.Paint(); // invokes Control.Paint(); it.Paint(); // invokes TextBox.Paint();son örnek
Açık arabirim üyesi uygulamaları sanal olarak bildirilemediğinden, açık arabirim üyesi uygulamasını geçersiz kılmak mümkün değildir. Ancak, açık bir arabirim üyesinin başka bir yöntemi çağırması tamamen geçerlidir ve bu diğer yöntem, türetilmiş sınıfların onu geçersiz kılabilmesi için sanal olarak bildirilebilir.
Örnek:
interface IControl { void Paint(); } class Control : IControl { void IControl.Paint() { PaintControl(); } protected virtual void PaintControl() {...} } class TextBox : Control { protected override void PaintControl() {...} }Burada,
Controlsınıfından türetilen sınıflar,IControl.Paintyöntemini geçersiz kılarakPaintControluygulamasını özelleştirebilir.son örnek
19.6.7 Arabirimi yeniden uygulama
Arabirim uygulamasını devralan bir sınıfın, temel sınıf listesine ekleyerek arabirimi yeniden uygulamasına izin verilir.
Bir arabirimin yeniden uygulanması, bir arabirimin ilk uygulamasıyla tam olarak aynı arabirim eşleme kurallarını izler. Bu nedenle, devralınan arabirim eşlemesinin arabirimin yeniden uygulanması için oluşturulan arabirim eşlemesi üzerinde hiçbir etkisi yoktur.
Örnek: Bildirimlerde
interface IControl { void Paint(); } class Control : IControl { void IControl.Paint() {...} } class MyControl : Control, IControl { public void Paint() {} }
ControlIControl.Paint'inControl.IControl.Paintüzerindeki eşlemesi,MyControliçindekiIControl.PaintMyControl.Paintüzerindeki yeniden uygulamayı etkilemez.son örnek
Devralınan genel üye bildirimleri ve devralınan açık arabirim üyesi bildirimleri, yeniden uygulanan arabirimler için arabirim eşleme işlemine katılır.
Örnek:
interface IMethods { void F(); void G(); void H(); void I(); } class Base : IMethods { void IMethods.F() {} void IMethods.G() {} public void H() {} public void I() {} } class Derived : Base, IMethods { public void F() {} void IMethods.H() {} }Burada,
IMethods'ünDerived'deki uygulaması, arabirim yöntemleriniDerived.F,Base.IMethods.G,Derived.IMethods.HveBase.Iile eşleştirir.son örnek
Bir sınıf bir arabirim uyguladığında, örtük olarak bu arabirimin tüm temel arabirimlerini de uygular. Benzer şekilde, bir arabirimin yeniden uygulanması da örtük olarak arabirimin tüm temel arabirimlerinin yeniden uygulanmasıdır.
Örnek:
interface IBase { void F(); } interface IDerived : IBase { void G(); } class C : IDerived { void IBase.F() {...} void IDerived.G() {...} } class D : C, IDerived { public void F() {...} public void G() {...} }Burada,
IDerivedöğesinin yeniden uygulanması,IBaseöğesini de yeniden uygular veIBase.F'yiD.Füzerine eşler.son örnek
19.6.8 Soyut sınıflar ve arabirimler
Soyut olmayan bir sınıf gibi, soyut sınıf da sınıfın temel sınıf listesinde listelenen arabirimlerin tüm soyut üyelerinin uygulamalarını sağlayacaktır. Ancak, soyut bir sınıfın arabirim yöntemlerini soyut yöntemlerle eşlemesine izin verilir.
Örnek:
interface IMethods { void F(); void G(); } abstract class C : IMethods { public abstract void F(); public abstract void G(); }Burada,
IMethodsveF,G'den türeyen soyut olmayan sınıflarda geçersiz kılınması gereken soyut yöntemlerle eşleştirilir.son örnek
Açık arabirim üyesi uygulamaları soyut olamaz, ancak açık arabirim üyesi uygulamalarının soyut yöntemleri çağırmasına elbette izin verilir.
Örnek:
interface IMethods { void F(); void G(); } abstract class C: IMethods { void IMethods.F() { FF(); } void IMethods.G() { GG(); } protected abstract void FF(); protected abstract void GG(); }Burada,
Csınıfından türeyen soyut olmayan sınıflarınFFveGG'yi geçersiz kılmaları, dolayısıylaIMethods'ün gerçek uygulamasını sağlamaları gerekecektir.son örnek
ECMA C# draft specification