Делегатлар тавсифи унинг ёрдамида чақирилиши мумкин бўлган методларнинрг сигнатураларини белгилаб беради:
[ атрибутлар ] [ спецификаторлар ] delegate тип делегат_номи ( [ параметрлар ] ) New, public, protected, internal хамда private спецификаторларига рухсат берилади. Тип делегат ёрдамида чақирилган методлар қайтариши лозим бўлган типларни тавсифлайди. Мажбурий бўлмаган параметралар шу методларнинг параметрлари ҳисобланади. Делегатлар бир нечта методларни сақлаши хамда уларни навбати билан қариши мумкин. Бу холда барча методларнинг сигнатурлари устма-уст тушиши керак.
Делегатларни аниқлашга намуна:
public delegate void D ( int i ); Бу ерда void ни қайтарадиган методларга ҳаволаларни сақловчи делегатларнинг типи келтирилган ва у бутун тсон типидаги битта параметрга эга. Делегатларни бевосита холатлар фазосида ёки класси ичида эълон қилиниши мумкин.
Делегатлардан фойдаланиш.
Делегатлардан фойдаланиш учун уларнинг экземплярларини яратиш хамда улар ҳақола қиладиган методларнинг номлари кўрсатилади. Делегат экземпляри чақирилганда унда аниқланган барча методлар чақирилади. Делегатлар асосан қуйидаги мақсадлар учун фойдаланилиши мумкин:
методларни компиляция вақтида эмас, балки дастур бажарилаётганда аниқлаш имкониятига эга бўлиш;
“манбаа-кузатувчи” типидаги объектлар ўртасидаги алоқани таъминлаш;
Бошқа методларга узатиш мумкин бўлган универсал методларни яратиш;
Дастлаб бу мақсадларнинг бириничисини амалга ошириш учун намуна кўрамиз. 17.1-листингла иккита хар хил методларни (C00l хамда Hack ). чақириш учун фойдаланиш мумкин бўлган делегат эълон қилинади
17.1-листинг. Содда делегатдан фойдаланиш
using System; namespace ConsoleApplication1 { delegate void Del ( ref string s ); // делегатни эълон қилиш class Class1 { public static void C00l ( ref string s ) // 1-метод { string temp = ""; for ( int i = 0; i < s.Length; ++i ) { if ( s[i] == 'o' || s[i] == 'O') temp += '0'; else if ( s[i] == 'l' ) temp += '1'; else temp += s[i]; } s = temp; }
public static void Hack ( ref string s ) // 2-метод { string temp = ""; for ( int i = 0; i < s.Length; ++i ) if ( i / 2 * 2 == i ) temp += char.ToUpper( s[i] ); else temp += s[i]; s = temp; }
static void Main() { string s = "cool hackers"; Del d; // делегат экземпляри
for ( int i = 0; i < 2; ++i ) { d = new Del( C00l ); // 1-метод билан инициализация if ( i == 1 ) d = new Del(Hack); // 2-метод билан инициализация d( ref s ); // методларни чақиришда делегатдан фойдаланиш Console.WriteLine( s ); } } } } Дастур ишининг натижаси :
c001 hackers
C001 hAcKeRs
Делегатлардан фойдалниш синтаксиси методларни чақириш сннтакисиси билан бир ҳил. Агар делегат бир нечта методларга ҳаволаларни сақласа, у холда бу методлар делегатга қўшилиш тартибида кетма-кет чақирилади.
Методларни рўйхатга System.Delegate классидан мерос олинган Combine методи ёрдамида қўшилади. Делегат чақирилганда бошланғич сатр бирданига иккита метод билан алмаштириладиган Main методи қуйидагича ёзилади:
static void Main() { string s = "cool hackers"; Del d = new Del( C00l ); d += new Del( Hack ); // методни делегатга қўшиш d( ref s ); Console.WriteLine( s ); // натижа: C001 hAcKeRs } Делегатлар ёрдамида методлар кетма-кетлигини чақиришда қуйидаги холатларни ҳисобга олиш зарур:
Методлар сигнатураси делегатга аниқ мос келиши керак;
Методлар статик хамда класснинг оддий методлари хам бўлиши мумкин;
Рўйхатдаги ҳар бир методга бир хил параметрлар узатилади;
Агар параметр ҳавола бўйича узатилса, битта методдаги параметрнинг ўзгариши навбатдаги методнинг чақирилишида унинг қийматига таъсир этади;
агар параметр out калит сўзи билан узатилса ёки метод қиймат қайтарадиган бўлса, у холда делегатнинг натижаси рўйхатдаги охирги метод шакллантирган қийматдан иборат бўлади (шу муносабат билан рўйхатларни void типидаги қиймат қайтарадиган делегатлардан тузиш тавсиф қилинади);
агар методнинг ишлаш жараёнида шу метод билан қайта ишланмаган истисноли вазият юзага келса, рўйхатда кўрсатилган навбатдаги методлар бажарилмайди ва делегатларни ўз ичига олувчи блоклардан қайта ишлагичлар изланади;
рўйхатида битта хам метод мавжуд бўлмаган делегатни чақиришга уриниш System.NullReferenceException истисноли вазиятни юзага келтиради.