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.
21.1 Genel
Temsilci bildirimi, sınıfından türetilen bir sınıfı System.Delegatetanımlar. Temsilci örneği, her biri çağrılabilen varlık olarak adlandırılan bir veya daha fazla yöntemin listesi olan çağrı listesini kapsüller. Örneğin yöntemler, çağrılabilen bir varlık bir örnekten ve bu örnekteki bir yöntemden oluşur. Statik yöntemler için çağrılabilen varlık yalnızca bir yöntemden oluşur. Uygun bir bağımsız değişken kümesiyle bir temsilci örneği çağırmak, temsilcinin çağrılabilir varlıklarının her birinin belirtilen bağımsız değişkenler kümesiyle çağrılmalarına neden olur.
Not: Temsilci örneğinin ilginç ve kullanışlı bir özelliği, kapsüllediği yöntemlerin sınıflarını bilmemesi veya önemsememesidir; önemli olan tek şey, bu yöntemlerin temsilcinin türüyle uyumlu (§21.4) olmasıdır. Bu, temsilcileri "anonim" çağırma için mükemmel bir şekilde uygun hale getirir. son not
21.2 Temsilci bildirimleri
delegate_declaration, yeni bir temsilci türü bildiren bir type_declaration (§14.7) olur.
delegate_declaration
: attributes? delegate_modifier* 'delegate' return_type delegate_header
| attributes? delegate_modifier* 'delegate' ref_kind ref_return_type
delegate_header
;
delegate_header
: identifier '(' parameter_list? ')' ';'
| identifier variant_type_parameter_list '(' parameter_list? ')'
type_parameter_constraints_clause* ';'
;
delegate_modifier
: 'new'
| 'public'
| 'protected'
| 'internal'
| 'private'
| unsafe_modifier // unsafe code support
;
unsafe_modifier, §24.2'de tanımlanır.
Aynı değiştiricinin temsilci bildiriminde birden çok kez görünmesi derleme zamanı hatasıdır.
variant_type_parameter_list sağlayan temsilci bildirimi genel bir temsilci bildirimidir. Ayrıca, genel bir sınıf bildiriminin veya genel yapı bildiriminin içinde iç içe yerleştirilmiş tüm temsilciler kendi genel bir temsilci bildirimidir, çünkü içeren tür için tür bağımsız değişkenleri oluşturulmuş bir tür (§8.4) oluşturmak için sağlanmalıdır.
new Değiştiriciye yalnızca başka bir tür içinde bildirilen temsilcilerde izin verilir; bu durumda, bu tür bir temsilcinin devralınan bir üyeyi §15.3.5'te açıklandığı gibi aynı ada göre gizlediğini belirtir.
public, protected, internalve private değiştiricileri temsilci türünün erişilebilirliğini denetler. Temsilci bildiriminin gerçekleştiği bağlama bağlı olarak, bu değiştiricilerden bazılarına izin verilmeyebilir (§7.5.2).
Temsilcinin tür adı tanımlayıcıdır.
Yöntemlerde (§15.6.1) olduğu gibi, varsaref, temsilci başv döndürür; aksi takdirde, return_typetemsilci değer döndürmez; aksi takdirde temsilci değere göre döndürür.
İsteğe bağlı parameter_list temsilcinin parametrelerini belirtir.
Değere göre döndürür veya değer döndürmez temsilci bildiriminin return_type , varsa, temsilci tarafından döndürülen sonucun türünü belirtir.
Başv temsilci bildiriminin ref_return_type, temsilci tarafından döndürülen variable_reference (§9.5) tarafından başvuruda bulunan değişkenin türünü belirtir.
İsteğe bağlı variant_type_parameter_list (§19.2.3), temsilcinin kendisi için tür parametrelerini belirtir.
Temsilci türünün dönüş türü veya voidçıkış açısından güvenli (§19.2.3.2) olmalıdır.
Temsilci türünün tüm parametre türleri giriş açısından güvenli olmalıdır (§19.2.3.2). Ayrıca, 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
Ayrıca, temsilcinin 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 olacaktır.
C# içindeki temsilci türleri ad eşdeğeridir, yapısal olarak eşdeğer değildir.
Örnek:
delegate int D1(int i, double d); delegate int D2(int c, double d);Temsilci türü
D1veD2iki farklı tür olduğundan, özdeş imzalarına rağmen birbirinin yerine kullanılamaz.son örnek
Diğer genel tür bildirimleri gibi, tür bağımsız değişkenleri de oluşturulacak bir temsilci türü oluşturmak için verilmelidir. Oluşturulan temsilci türünün parametre türleri ve dönüş türü, temsilci bildirimindeki her tür parametresi için oluşturulan temsilci türünün karşılık gelen tür bağımsız değişkeni olan değiştirilerek oluşturulur.
Temsilci türünü bildirmenin tek yolu bir delegate_declaration yoluyla yapılır. Her temsilci türü, türünden System.Delegatetüretilen bir başvuru türüdür. Her temsilci türü için gereken üyeler §21.3'te ayrıntılı olarak yer alır. Temsilci türleri örtük olarak sealedolur, bu nedenle bir temsilci türünden herhangi bir tür türetme izni verilmiyor. Ayrıca, öğesinden System.Delegatetüretilen temsilci olmayan bir sınıf türü bildirmek de mümkün değildir.
System.Delegate kendisi bir temsilci türü değildir; tüm temsilci türlerinin türetildiği bir sınıf türüdür.
21.3 Üye temsilcisi
Her temsilci türü , §15.3.4'te Delegateaçıklandığı gibi sınıftan üyeleri devralır. Ayrıca, her temsilci türü, parametre listesi temsilci bildirimindeki parameter_list eşleşenInvoke veya ref_return_type ile eşleşen ve ref_kind temsilci bildirimindekiyle eşleşen başv temsilcileriiçin genel olmayan bir yöntem sağlayacaktır. Yöntem, Invoke en az içeren temsilci türü kadar erişilebilir olmalıdır.
Invoke Yöntemini temsilci türünde çağırma, temsilci çağırma söz dizimini (§21.6) kullanmaya benzer.
Uygulamalar, temsilci türünde ek üyeler tanımlayabilir.
Örnekleme dışında, bir sınıfa veya sınıf örneğine uygulanabilen tüm işlemler sırasıyla bir temsilci sınıfına veya örneğine de uygulanabilir. Özellikle, türün System.Delegate üyelerine normal üye erişim söz dizimi aracılığıyla erişmek mümkündür.
21.4 Temsilci uyumluluğu
Aşağıdakilerin tümü doğruysa bir yöntem veya temsilci türü M temsilci türüyle uyumludur
-
DveMaynı sayıda parametreye sahiptir ve içindekiDher parametre, içindekiMilgili parametreyle aynı başvuruya göre parametre değiştiricisine sahiptir. - Her değer parametresi için, içindeki parametre türünden içindeki ilgili parametre türüne bir kimlik dönüştürmesi (
D10.2.2) veya örtük başvuru dönüştürmesi (M) vardır. - Her başvuruya göre parametre için içindeki parametre türü
D, içindekiMparametre türüyle aynıdır. - Aşağıdakilerden biri doğrudur:
- hem
Dhem deMdeğer döndürmez. -
DveMdeğere göre döndürür (§15.6.1, §21.2) ve dönüş türünden dönüş türüneMbir kimlik veya örtük başvuru dönüştürmesiDvardır. -
DveMher ikisi de başv döndürür, dönüş türü ile dönüş türüMDarasında bir kimlik dönüştürmesi vardır ve her ikisi de aynı ref_kind sahiptir.
- hem
Bu uyumluluk tanımı, dönüş türünde kovaryans ve parametre türlerinde değişken karşıtılık sağlar.
Örnek:
delegate int D1(int i, double d); delegate int D2(int c, double d); delegate object D3(string s); class A { public static int M1(int a, double b) {...} } class B { public static int M1(int f, double g) {...} public static void M2(int k, double l) {...} public static int M3(int g) {...} public static void M4(int g) {...} public static object M5(string s) {...} public static int[] M6(object o) {...} }ve
A.M1yöntemleriB.M1, aynı dönüş türüne veD1parametre listesine sahip olduğundan hem temsilci türleriyleD2hem de ile uyumludur. , ve yöntemleriB.M2, farklı dönüş türlerineB.M3veya parametre listelerine sahip olduğundan veB.M4temsilcileriyleD1uyumsuz.D2ve yöntemleriB.M5,B.M6temsilci türüyleD3uyumludur.son örnek
Örnek:
delegate bool Predicate<T>(T value); class X { static bool F(int i) {...} static bool G(string s) {...} }yöntemi
X.Ftemsilci türüylePredicate<int>ve yöntemiX.Gde temsilci türüylePredicate<string>uyumludur.son örnek
Not: Temsilci uyumluluğunun sezgisel anlamı, temsilcinin her çağrısının tür güvenliğini ihlal etmeden, isteğe bağlı parametreleri ve parametre dizilerini açık parametreler olarak ele almadan yöntemin çağrılmasıyla değiştirilebiliyorsa yöntemin temsilci türüyle uyumlu olmasıdır. Örneğin, aşağıdaki kodda:
delegate void Action<T>(T arg); class Test { static void Print(object value) => Console.WriteLine(value); static void Main() { Action<string> log = Print; log("text"); } }Bir
Action<string>da yönteminAction<string>geçerli bir çağrısıYukarıdaki
Print(object value, bool prependTimestamp = false)olarak değiştirildiyse,Action<string>uyumlu olmayacaktır.son not
21.5 Temsilci örneği oluşturma
Temsilci örneği, bir temsilci türüne dönüştürme, temsilci birleşimi veya temsilci kaldırma işlemi olan bir delegate_creation_expression (§12.8.17.5) tarafından oluşturulur. Yeni oluşturulan temsilci örneği aşağıdakilerden birine veya daha fazlasına başvurur:
- delegate_creation_expression başvuruda bulunan statik yöntem veya
- hedef nesne (olamaz
null) ve delegate_creation_expression başvurulan örnek yöntemi veya - Başka bir temsilci (§12.8.17.5).
Örnek:
delegate void D(int x); class C { public static void M1(int i) {...} public void M2(int i) {...} } class Test { static void Main() { D cd1 = new D(C.M1); // Static method C t = new C(); D cd2 = new D(t.M2); // Instance method D cd3 = new D(cd2); // Another delegate } }son örnek
Temsilci örneği tarafından kapsüllenen yöntem kümesi çağırma listesi olarak adlandırılır. Tek bir yöntemden bir temsilci örneği oluşturulduğunda, bu yöntemi kapsüller ve çağırma listesinde yalnızca bir giriş bulunur. Ancak, temsilci olmayannull iki örnek birleştirildiğinde, iki veya daha fazla girdi içeren yeni bir çağırma listesi oluşturmak için çağrı listeleri (sol işlenen ve sağ işlenen sırasıyla) birleştirilir.
Tek bir temsilciden yeni bir temsilci oluşturulduğunda, sonuç çağırma listesinde yalnızca bir girdi vardır ve bu da kaynak temsilcidir (§12.8.17.5).
Temsilciler ikili + (§12.12.5) ve += işleçler (§12.23.4) kullanılarak birleştirilir. Temsilci, ikili - (§12.12.6) ve -= işleçler (§12.23.4) kullanılarak temsilci birleşiminden kaldırılabilir. Temsilciler eşitlik için karşılaştırılabilir (§12.14.9).
Örnek: Aşağıdaki örnek, bir dizi temsilcinin ve buna karşılık gelen çağrı listelerinin örneğini gösterir:
delegate void D(int x); class C { public static void M1(int i) {...} public static void M2(int i) {...} } class Test { static void Main() { D cd1 = new D(C.M1); // M1 - one entry in invocation list D cd2 = new D(C.M2); // M2 - one entry D cd3 = cd1 + cd2; // M1 + M2 - two entries D cd4 = cd3 + cd1; // M1 + M2 + M1 - three entries D cd5 = cd4 + cd3; // M1 + M2 + M1 + M1 + M2 - five entries D td3 = new D(cd3); // [M1 + M2] - ONE entry in invocation // list, which is itself a list of two methods. D td4 = td3 + cd1; // [M1 + M2] + M1 - two entries D cd6 = cd4 - cd2; // M1 + M1 - two entries in invocation list D td6 = td4 - cd2; // [M1 + M2] + M1 - two entries in invocation list, // but still three methods called, M2 not removed. } }ve
cd1örneği oluşturulurkencd2, her biri bir yöntemi kapsüller. Örneklendiğindecd3, bu sırada ve olmak üzere iki yönteminM1M2çağrı listesi bulunur.cd4'nin çağırma listesindeM1,M2veM1, sırasıyla bulunur. içincd5, çağrı listesiM1bu sırada ,M2M1, ,M1veM2içerir.delegate_creation_expression başka bir temsilciden temsilci oluştururken, sonuç özgünden farklı bir yapıya sahip bir çağrı listesine sahiptir, ancak bu da aynı yöntemlerin aynı sırayla çağrılmasına neden olur. Çağrı
td3listesindencd3oluşturulduğunda yalnızca bir üye vardır, ancak bu üye yöntemlerinM1listesidir veM2bu yöntemler tarafındantd3cd3tarafından çağrıldıkları sırayla çağrılır. Benzer şekilde, çağrı listesinin örneği oluşturulurkentd4yalnızca iki giriş vardır, ancak aynı şekilde üç yöntemiM1(M2veM1) bu sıraylacd4çağırır.Çağırma listesinin yapısı temsilci çıkarma işlemini etkiler. '
cd6den çıkarılarakcd2oluşturulan (çağıranM2) temsilci , ve çağrılarınıcd4M1M2(,M1veM1) çağırır.M1td6Ancak , öğesindencd2çıkarılarakM2oluşturulan (çağırantd4) ( ,M1veM2) öğesini çağıranM1temsilci, listedeki tek bir girdi değil, iç içe bir listenin üyesi olduğu gibiM1, veM2'yi bu sırayla çağırmaya devam ederM1M2. Temsilcileri birleştirme (kaldırmanın yanı sıra) hakkında daha fazla örnek için bkz. §21.6.son örnek
Örnek oluşturulduktan sonra, temsilci örneği her zaman aynı çağrı listesine başvurur.
Not: İki temsilci birleştirildiğinde veya biri başka bir temsilciden kaldırıldığında, yeni bir temsilci kendi çağırma listesiyle sonuçlanır; birleştirilen veya kaldırılan temsilcilerin çağrı listeleri değişmeden kalır. son not
21.6 Temsilci çağırma
C# temsilci çağırmak için özel söz dizimi sağlar. Çağrı listesinde tek bir giriş bulunannull olmayan bir temsilci örneği çağrıldığında, kendisine verilen aynı bağımsız değişkenlerle tek bir yöntemi çağırır ve başvurulan yöntemle aynı değeri döndürür. (Temsilci çağırma hakkında ayrıntılı bilgi için bkz. §12.8.10.4.) Böyle bir temsilci çağrılırken bir özel durum oluşursa ve bu özel durum çağrılan yöntem içinde yakalanmazsa, temsilciyi çağıran yöntemde, bir özel durum yakalama yan tümcesi aranmasına devam edilir, sanki bu yöntem, temsilcinin başvurduğu yöntemi doğrudan çağırmış gibi.
Çağırma listesi birden çok girdi içeren bir temsilci örneğinin çağrılması, çağırma listesindeki yöntemlerin her birini sırayla zaman uyumlu olarak çağırarak devam eder. Çağrılan her yöntem, temsilci örneğine verilen bağımsız değişkenler kümesiyle aynı şekilde geçirilir. Böyle bir temsilci çağırması başvuru parametreleri (§15.6.2.3.3) içeriyorsa, her yöntem çağrısı aynı değişkene başvuruyla gerçekleşir; çağırma listesindeki bir yöntem tarafından bu değişkende yapılan değişiklikler, çağrı listesinin daha ilerisindeki yöntemlere görünür. Temsilci çağırması çıkış parametreleri veya dönüş değeri içeriyorsa, son değeri listedeki son temsilcinin çağrısından gelir. Böyle bir temsilcinin çağrılma işlemi sırasında bir özel durum oluşursa ve bu özel durum çağrılan yöntemde yakalanmazsa, özel durum yakalama yan tümcesi araması temsilciyi çağıran yöntemde devam eder ve çağrı listesinin daha aşağısındaki yöntemler çağrılmaz.
Değeri türünde nullbir özel durumla sonuçlanan bir temsilci örneği çağrılmaya çalışılıyorSystem.NullReferenceException.
Örnek: Aşağıdaki örnek, temsilcilerin örneğini oluşturma, birleştirme, kaldırma ve çağırma adımlarını gösterir:
delegate void D(int x); class C { public static void M1(int i) => Console.WriteLine("C.M1: " + i); public static void M2(int i) => Console.WriteLine("C.M2: " + i); public void M3(int i) => Console.WriteLine("C.M3: " + i); } class Test { static void Main() { D cd1 = new D(C.M1); cd1(-1); // call M1 D cd2 = new D(C.M2); cd2(-2); // call M2 D cd3 = cd1 + cd2; cd3(10); // call M1 then M2 cd3 += cd1; cd3(20); // call M1, M2, then M1 C c = new C(); D cd4 = new D(c.M3); cd3 += cd4; cd3(30); // call M1, M2, M1, then M3 cd3 -= cd1; // remove last M1 cd3(40); // call M1, M2, then M3 cd3 -= cd4; cd3(50); // call M1 then M2 cd3 -= cd2; cd3(60); // call M1 cd3 -= cd2; // impossible removal is benign cd3(60); // call M1 cd3 -= cd1; // invocation list is empty so cd3 is null // cd3(70); // System.NullReferenceException thrown cd3 -= cd1; // impossible removal is benign } }deyiminde
cd3 += cd1;gösterildiği gibi, bir temsilci bir çağrı listesinde birden çok kez bulunabilir. Bu durumda, her oluşumda bir kez çağrılır. Bunun gibi bir çağrı listesinde, bu temsilci kaldırıldığında, çağrı listesindeki son oluşum aslında kaldırılandır.Son deyiminin yürütülmesinden hemen önce,
cd3 -= cd1temsilcicd3boş bir çağırma listesine başvurur. Boş bir listeden temsilci kaldırmaya (veya boş olmayan bir listeden var olmayan bir temsilciyi kaldırmaya) çalışmak hata değildir.Üretilen çıkış:
C.M1: -1 C.M2: -2 C.M1: 10 C.M2: 10 C.M1: 20 C.M2: 20 C.M1: 20 C.M1: 30 C.M2: 30 C.M1: 30 C.M3: 30 C.M1: 40 C.M2: 40 C.M3: 40 C.M1: 50 C.M2: 50 C.M1: 60 C.M1: 60son örnek
ECMA C# draft specification