You are on page 1of 786

HERKES N C#

2
KISIM I C# DL

KISIM I C# DL
BLM 1: C#'IN DOUU
C# Aile Aac ...
C: Modern Programlama ann Balangc .
Nesne Ynelimli Programlamann ve C++'n Douu ...
nternet ve Java'nn Gelii ..
C#' n Douu ..
C# ile .NET Framework Arasndaki Balant ..
.NET Framework Nedir? .
Common Language Runtime Nasl alr? ...
Kontrol Altna Alnan ve Alnmayan Kodlar .
Common Language Specification .

BLM 2: C#'A GENEL BR BAKI ...
Nesne Ynelimli Programlama .
likili Verilerin Paketlenmesi .
ok Biimlilik
Kaltm ...
lk Basit Program .
C# Komut Satr Derleyicisini (csc.exe) Kullanmak
Visual Studio IDE'yi Kullanmak .
Satr Satr lk rnek Program
Sz Dizimi Hatalarn Kontrol Altna Almak .
Kk Bir Deiiklik
kinci Basit Program
Baka Bir Veri Tipi ..
ki Kontrol fadesi .
if fadesi .
for Dngs ..
Kod Bloklarn Kullanmak ...
Noktal Virgller ve Konumlandrma .
Girintileme Altrmalar ..
C# Anahtar Kelimeleri .
Tanmlayclar ..
C# Snf Ktphaneleri ...

BLM 3: VER TPLER, LTERALLER VE DEKENLER
Veri Tipleri Neden nemlidir? ...
C#'n Deer Tipleri ..
Tamsaylar
decimal Tipi ..
Karakterler
bool Tipi
Baz kt Seenekleri
Literaller
Onaltlk Literaller .
Karakter Ka Sekanslar ............
Karakter Katar Literalleri



13
14
14
15
16
17
18
19
19
20
20

21
22
23
23
24
25
25
26
30
33
34
35
37
39
39
40
42
43
44
45
45
46

47

48
48
49
53
54
55
56
59
60
61
62
NDEKLER
HERKES N C#
3
Deikenlere Yakndan Bir Bak .
Bir Deikene lk Deer Atamak ...
Dinamik lk Deer Atamas
Deikenlerin Kapsam ve Yaam Sreleri .
Tip Dnmleri ve Tip Atamalar
Otomatik Dnmler .
Uyumsuz Tiplerin Atamalar ..
Deyimlerde Tip Dnmleri .
Deyimlerde Tip Atamas Kullanmak .

BLM 4: OPERATRLER ..
Aritmetik Operatrler ..
Artrma ve Eksiltme .
likisel ve Mantksal Operatrler ..
Ksa Devre Mantksal Operatrler
Atama Operatr .
Bileik Atamalar ...
Bit Tabanl Operatrler ...
Bit Tabanl VE, VEYA, XOR ve DEL Operatrleri ...
Kaydrma Operatrleri ..
Bit Tabanl Bileik Atamalar
? Operatr ..
Boluklar ve Parantezler
Operatrlerin ncelik Sras ..

BLM 5: PROGRAM KONTROL FADELER ..
if ifadesi .
Kmelenmi if'ler .
if-else-if Merdiveni ...
switch fadesi
Kmelenmi switch fadeleri ..
for Dngs ..
for Dngs zerinde Baz Varyasyonlar ...
while Dngs .
do-while Dngs
foreach Dngs .
Dngden kmak in break Kullanmak
continue fadesini Kullanmak .
return .
goto

BLM 6: SINIFLARA, NESNELERE VE METOTLARA GR .
Snflarn Temel zellikleri .
Snfn Genel Biimi .
Snf Tanmlamak ...
Nesneler Nasl Oluturulur? ..
Referans Deikenleri ve Atama ..
Metotlar .
Building Snfna Bir Metot Eklemek .

63
64
64
65
68
69
70
72
74

77

78
79
82
85
87
87
88
88
94
97
97
99
99

101

102
103
104
105
109
109
112
117
119
120
120
123
123
124

127

128
128
129
134
135
135
136


HERKES N C#
4
KISIM I C# DL

Metottan Dn
Bir Deer Dndrmek .
Parametre Kullanmak .
Building'e Parametreli Bir Metot Eklemek
Eriilemeyen Kodlar nlemek ..
Yaplandrclar .
Parametreli Yaplandrclar ...
Building Snfna Bir Yaplandrc Eklemek .
new Operatrne Tekrar Bir Bak ...
new'u Deer Tipleriyle Birlikte Kullanmak
Anlamsz Verilerin Toplanmas ve Yok ediciler ..
Yok Ediciler ..
this Anahtar Kelimesi ..

BLM 7: DZLER VE KARAKTER KATARLARI
Diziler
Tek Boyutlu Diziler ..
Diziyi lk Kullanma Hazrlamak .
Snrlar Zorlanr
ok Boyutlu Diziler ..
ki Boyutlu Diziler .
veya Daha Fazla Boyutlu Diziler .
ok Boyutlu Dizileri ilk Kullanma Hazrlamak
Dzensiz Diziler ...
Dizi Referanslarn Atamak
Length zelliini Kullanmak ..
Dzensiz Dizilerde Length Kullanmak .
foreach Dngs .
Karakter Katarlar
Karakter Katarlarn Oluturmak
Karakter Katarlar zerinde ilem Yapmak .
Karakter Katar Dizileri
Karakter Katarlar Deimez .
Karakter Katarlar switch ifadelerinde Kullanlabilir

BLM 8: METOT VE SINIFLARA DAHA YAKINDAN BR BAKI ..
Snf yelerine Eriimi Kontrol Etmek ..
C# ' ta Eriim Belirleyicileri .
Public ve Private Eriimi Uygulamak
Eriimi Kontrol Altna Almak: Bir rnek alma
Metotlara Nesne Aktarmak
Argmanlar Nasl Aktarlr?
ref ve out Parametrelerini Kullanmak ...
ref Kullanmak ...
out Kullanmak ..
Referans Parametrelerinde ref ve out Kullanmak ..
Deien Sayda Argman Kullanmak ..
Nesneleri Dndrmek .
Bir Diziyi Dndrmek ..
Metotlarn An Yklenmesi ...
Yaplandrclar Ar Yklemek

139
140
142
145
146
147
148
149
150
151
152
152
154

157

158
158
161
162
162
162
164
165
166
168
169
172
173
177
177
178
181
182
184

185

186
186
188
189
194
195
198
198
200
202
204
207
209
210
216
NDEKLER
HERKES N C#
5
this Araclyla Ar Yklenmi Bir Yaplandrcy armak .
Main() Metodu ..
Main()'den Deer Dndrmek ...
Main()'e Argman Aktarmak ..
Yinelenme .
static'i Anlamak
static Yaplandrclar ..

BLM 9: OPERATRLERN AIRI YKLENMES ..
Operatrlerin Ar Yklenmesiyle lgili Temel Kavramlar
kili Operatrleri Ar Yklemek
Tekli Operatrleri Ar Yklemek .
Standart C# Tipleri zerindeki lemleri Kontrol Altna Almak .
likisel Operatrleri Ar Yklemek
true ve false' Ar Yklemek
Mantksal Operatrleri Ar Yklemek
Mantksal Operatrlerin Ar Yklenmesine Basit Bir Yaklam .
Ksa Devre Operatrleri Mmkn Klmak
Dnm Operatrleri
Operatrleri Ar Yklemekle ilgili pular ve Kstlamalar ..
Operatrlerin Ar Yklenmesine Bir Baka rnek ..

BLM 10: NDEKSLEYCLER VE ZELLKLER .
ndeksleyiciler ..
Tek Boyutlu indeksleyici Oluturmak
ndeksleyiciler Ar Yklenebilir
ndeksleyiciler, Temel Niteliinde Bir Dizi Gerektirmez .
ok Boyutlu ndeksleyiciler
zellikler ...
zelliklerle lgili Kstlamalar ..
ndeksleyiciler ve zelliklerin Kullanm ..

BLM 11: KALITIM
Kaltmn Temel Unsurlar ..
ye Eriimi ve Kaltm
protected Eriim Kullanm .
Yaplandrclar ve Kaltm ..
Temel Snfn Yaplandrclarn armak .
Kaltm ve isim Gizleme ..
Gizli Bir isme Erimek in base Kullanm .
ok Katmanl Hiyerari Oluturmak .
Yaplandrclar Ne Zaman arlr?
Temel Snf Referanslar ve Tretilmi Nesneler ...
Sanal Metotlar ve Devre D Brakma (Overriding) ..
Devre D Braklan Metotlara Neden Gerek Var?
Sanal Metotlar Uygulamak ..
zet Snflarn Kullanm
Kaltm nlemek in sealed Kullanmak .
object Snf ..

220
221
221
222
224
227
232

234

235
236
238
242
246
248
251
251
253
257
262
263

268

269
269
273
275
276
278
284
284

290

291
294
297
298
300
305
306
308
311
312
316
320
321
324
328
329


HERKES N C#
6
KISIM I C# DL

Kutulama ve Kutudan karma
object Genel Bir Veri Tipi midir?

BLM 12: ARAYZLER, YAPILAR VE NUMARALANDIRMALAR
Arayzler ..
Arayzleri Uygulamak .
Arayz Referanslarnn Kullanm .
Arayz zellikleri .
Arayz ndeksleyiciler .
Arayzler Kaltm Yoluyla Aktarlabilir ..
Arayz Kaltm le Birlikte sim Gizleme ..
Ak Uygulamalar
zel Bir Uygulama Gelitirmek .
Belirsizlii Ortadan Kaldrmak in Ak Uygulamalarn Kullanm ..
Bir Arayz ve zet Snf Arasnda Tercihte Bulunmak .
.NET Standart Arayzleri ...
Arayzlerle ilgili Bir rnek alma ..
Yaplar ...
Yaplara Neden Gerek Vardr? ..
Numaralandrmalar .
Bir Numaralandrmaya ilk Deer Atamak
Bir Numaralandrmann Temel Tipini Belirtmek ..
Numaralandrmalarn Kullanm

BLM 13: KURALDII DURUM YNETM .
System.Exception Snf .
Kural D Durum Ynetimiyle lgili Esaslar .
try ve catch'in Kullanm ..
Basit Bir Kural D Durum rnei
kinci Bir Kural D Durum rnei ..
Yakalanmayan Kural D Durumlarn Sonular
Kural D Durumlar, Hatalar Zarife Kontrol Altna Almanza Olanak Tanr
Birden Fazla catch fadesinin Kullanm ..
Kural D Durumlarn Tmn Yakalamak
try Bloklarn Kmelemek ...
Bir Kural D Durum Frlatmak .
Kural D Durumu Yeniden Frlatmak .
finally'nin Kullanm .
Kural D Durumlara Yakndan Bir Bak ...
Ska Kullanlan Kural D Durumlar ...
Kural D Durum Snflarn Tretmek .
Tretilmi Snflarla lgili Kural D Durumlar Yakalamak ...
checked ve unchecked Kullanm .

BLM 14: I/O KULLANIMI
C#'n I/O Sistemi, Aklar zerine Kurulmutur .
Byte Aklar ve Karakter Aklar .
nceden Tanml Aklar
Ak Snflar .
Stream Snf
331
333

335

336
337
341
344
345
347
348
348
349
350
351
351
352
357
360
362
364
365
365

367

368
369
369
370
371
373
374
375
376
377
379
380
381
383
384
386
390
392

396

397
397
397
398
398
NDEKLER
HERKES N C#
7

Byte Stream Snflar ...
Karakter Akn Saran Snflar ..
kili Aklar .
Konsol I/O .
Konsol Girdisini Okumak
Konsol kts Yazmak
FileStream ve Byte Ynelimli Dosya I/O ilemleri .
Bir Dosyay Amak ve Kapatmak .
Bir Filestream'den Byte'lar Okumak .
Bir Dosyaya Yazmak ..
Dosya Kopyalamak in Filestream Kullanmak ..
Karakter Tabanl Dosya I/O lemleri ...
StreamWriter Kullanm ..
StreamReader Kullanm
Standart Aklar Ynlendirmek
kili Verileri Okumak ve Yazmak ...
BinaryWriter ..
BinaryReader ...
kili l/O lemlerinin Gsterilmesi ..
Rasgele Eriimli Dosyalar ..
MemoryStream'in Kullanm ..
StringReader ve StringWriter Kullanm ..
Nmerik Karakter Katarlarn Dahili Gsterimlerine Dntrmek ..

BLM 15: DELEGELER VE OLAYLAR
Delegeler .
oklu ar ..
System. Delegate
Delegelere Neden Gerek Vardr? .
Olaylar ...
Bir oklu ar Olay rnei ..
Olay Yneticileri Olarak static Metotlara Kar rnek Metotlar
Olay Eriimcilerinn Kullanm
Olaylarn eitli zelikleri ..
.NET'te Olaylarla lgili Esaslar ...
EventHandler Kullanm ..
Olaylar Uygulamak: Bir rnek alma ..

BLM 16: SM UZAYLARI, NLEMC VE ASSEMBLY'LER .
sim Uzaylar
sim Uzayn Deklare Etmek ..
using ..
using'in kinci Kullanm ekli ..
sim Uzaylar Eklenebilir .
sim Uzaylar Kmelenebilir ...
Varsaylan sim Uzay .
nilemci ..
#define ..
#if ve #endif ..
#else ve #elif

399
400
401
402
402
404
405
405
407
408
410
411
412
414
415
417
417
418
419
423
425
427
429

432

433
437
439
440
440
442
444
446
450
451
453
454

456

457
457
461
463
464
466
467
467
468
468
470

HERKES N C#
8
KISIM I C# DL


#undef
#error .
#warning
#line ...
#region ve #endregion
Assembly'ler ve internal Eriim Niteleyicisi .
internal Eriim Niteleyicisi ..

BLM 17: ALIMA ZAMANI TP TANIMLAMASI, YANSIMA VE
NTELKLER .
alma Zaman Tip Tanmlamas ...
Bir Tipi is le Test Etmek .
as Kullanm ..
typeof Kullanm ...
Yansma ..
Yansmann ekirdei: System.Type ...
Yansmann Kullanm
Metotlar Hakknda Bilgi Edinmek ..
Metotlar Yansma Kullanarak armak .
Type'n Yaplandrclarn Elde Etmek .
Assembly'lerden Tip Elde Etmek ..
Tiplerin Ortaya karlmasn Tam Olarak Otomatize Etmek ...
Nitelikler
Niteliklerle ilgili Temel Bilgiler
Konumsal ve simlendirilmi Parametreler ..
Standart Niteliklerin Kullanm ...
AttributeUsage .
Conditional Nitelii ..
Obsolete Nitelii ..

BLM 18: EMNYETSZ KOD, ARETLER VE ETL KONULAR ..
Emniyetsiz Kod
aretilerin Esaslar
unsafe Kullanm ..
fixed Kullanm .
Yap yelerine Bir areti Araclyla Erimek .
areti Aritmetii .
aretilerin Karlatrlmas .
aretiler ve Diziler .
aretiler ve Karakter Katarlar .
oklu Dolayllk
areti Dizileri ..
eitli Anahtar Kelimeler
sizeof .
lock .
readonly
stackalloc .
using ifadesi
const ve volatile ...


472
472
472
472
473
473
474



475

476
476
477
479
480
480
481
482
486
489
493
499
501
502
505
509
509
510
511

513

514
515
517
517
518
519
520
521
523
524
526
526
526
526
527
527
528
529
NDEKLER
HERKES N C#
9



KISIM II: C# KTPHANESN KEFETMEK .
BLM 19: SYSTEM SM UZAYI .
System 'in yeleri
Math Snf
Deer Tipindeki Yaplar ..
Tamsay Tipinde Yaplar
Kayan Nokta Tipinde Yaplar .
Decimal .
Char ...
Boolean Yaps .
Array snf
Dizileri Sralamak ve Aramak
Diziyi Ters evirmek ...
Diziyi Kopyalamak ...
BitConverter .
Random ile Rasgele Saylar retmek ..
Bellek Ynetimi ve GC Snf .
Object
IComparable Arayz .
IConvertible Arayz ..
ICloneable Arayz .
IFormatProvider ve IFormattable ..

BLM 20: KARAKTER KATARLARI VE BMLENDRME
C#'ta Karakter Katarlar ..
String Snf ..
String Yaplandrclar
String Alan, ndeksleyici ve zellik ..
String Operatrleri ...
String Metotlar .
Karakter Katarlarn Doldurmak ve Budamak .
Ekleme, kartma ve Deitirme ..
Harf Kipini Deitirmek ...
Substring() Metodunun Kullanm .
Biimlendirme ..
Biimlendirmeye Genel Bak
Nmerik Biim Belirleyicileri ..
Verileri Biimlendirmek iin String.Format() ve ToString() Kullanm ..
Deerleri Biimlendirmek in String.Format( ) Kullanm .
Verileri Biimlendirmek in ToString() Kullanm ...
zel Bir Nmerik Biim Oluturmak .
zel Biim Yer Tutucu Karakterleri ..
Tarih ve Saati Biimlendirmek ..
zel Tarih ve Saat Biiminizi Oluturmak ...
Numaralandrmalar Biimlendirmek





530

531

532
533
538
539
541
544
549
553
554
554
557
557
563
566
567
568
569
569
570
572

573

574
574
575
576
576
577
589
590
592
592
593
593
594
596
597
599
600
601
604
607
609


HERKES N C#
10
KISIM I C# DL

BLM 21: OK KANALLI PROGRAMLAMA
ok Kanalllkla lgili Esaslar .
Thread Snfnn Kullanm .
Bir Kanal Oluturmak ..
Baz Basit Yenilikler
Birden Fazla Kanal Oluturmak
alma Kanalnn Ne Zaman Sona Ereceini Belirlemek ...
IsBackground zellii .
Kanal ncelikleri .
Senkronizasyon ...
Alternatif Yaklam ..
Bir Statik Metodu Kilitlemek ...
Monitr Snf ve lock ..
Wait(), Pulse() ve PulseAll() Kullanarak Kanal letiimi .
Wait() ve Pulse() Kullanan Bir rnek ...
Kilitlenme ..
MethodlmplAttribute Kullanm ..
Kanallar Askya Almak, Srdrmek ve Durdurmak ..
Alternatif Abort()
Abort()'u ptal Etmek
alma Kanalnn Durumunu Belirlemek ...
Temel Kanaln Kullanm
ok Kanalllk nerileri ...
Ayr Bir Grevi Balatmak ..

BLM 22: KOLEKSYONLARLA ALIMAK .
Koleksiyonlara Genel Bak ..
Koleksiyon Arayzleri .
ICollection Arayz .
IList Arayz .
Dictionary Arayz .
lEnumerable, lEnumerator ve IDictionaryEnumerator ...
IComparer .
IHashCodeProvider .
The DictionaryEntry Yaps
Genel Amal Koleksiyon Snflar
ArrayList
Hashtable ..
SortedList ..
Stack ..
Queue
BitArray le Bitleri Saklamak ..
zelletirilmi Koleksiyonlar ..
Bir Numaralandrc zerinden Bir Koleksiyona Erimek .
Numaralandrc Kullanmak
IDictionaryEnumerator Kullanm .
Koleksiyonlar iinde Kullanc Tarafndan Tanmlanan Snflar Saklamak
IComparable'i Uygulamak ..
IComparer'i Belirtmek .
Koleksiyonlarn zeti ..



611

612
613
613
616
617
619
622
623
625
629
631
631
632
633
636
637
639
641
642
644
645
646
646

649

650
651
651
652
653
655
655
655
656
656
656
664
666
670
672
675
678
678
679
680
682
683
685
687


NDEKLER
HERKES N C#
11
BLM 23: INTERNET LE A UYGULAMALARI .
System.Net yeleri .
Uniform Resource Identifier'lar .
Internet Eriim Esaslar ..
WebRequest .
WebResponse .
HttpWebRequest ve HttpWebResponse .
lk Basit rnek ..
A Hatalarn Kontrol Altna Almak ...
Create() Tarafndan retilen Kural D Durumlar .
GetReponse() Tarafndan retilen Kural D Durumlar ...
GetResponseStream() Tarafndan retilen Kural D Durumlar
Kural D Durum Ynetimini Kullanmak .
URI Snf ..
Ek HTTP Yant Bilgilerine Eriim ..
Bala Eriim ..
erezlere Eriim ..
LastModified zelliinin Kullanm
MiniCrawler: rnek alma .
WebClient Kullanm ...

KISIM III: C#'l UYGULAMAYA GERMEK .
BLM 24: BLEENLERN OLUTURULMASI .
Bileen Nedir? .
Bileen Modeli ..
C# Bileeni Nedir? ..
Konteynerler ve Siteler ...
C# ite COM Bileenlerinin Karlatrmas ..
IComponent ..
Bileen .
Basit Bir Bileen ..
CipherLib'i Derlemek ...
CipherComp Kullanan Bir stemci .
Dispose()'u Devre D Brakmak .
Dispose(bool)'un Kullanm
Dispose Edilmi Bir Bileenin Kullanmn nlemek ..
using fadesini Kullanmak ..
Konteynerler .
Konteynerin Gsterilmesi ...
Bileenler, Programlamann Gelecei mi? ..

BLM 25: FORM TABANLI WNDOWS UYGULAMALARI GELTRMEK .
Windows Programlamann Ksa Tarihesi ..
Form Tabanl Bir Wndows Uygulamas Yazmann ki Yntemi ..
Windows'un Kullanc ile Etkileimi ..
Windows Formlar ...
Form Snf
Form Tabanl Bir Windows Program Tasla ..


688

689
690
691
692
693
694
694
697
697
698
698
698
700
701
702
703
705
706
709

713

714

715
715
716
716
716
717
717
719
720
720
721
723
728
729
730
732
733

734

735
736
736
737
737
737


HERKES N C#
12
KISIM I C# DL

Windows Taslan Derlemek
Dme Eklemek ....
Button Snfnn Esaslar .
Bir Forma Dme Eklemek
Basit Bir Dme rnei ..
Mesajlar Ynetmek
Alternatif Uygulama .
Mesaj Kutusunun Kullanm ...
Men Eklemek .
imdi Ne Yapabilirsiniz?

BLM 26: YNELENEREK NEN BR DEYM AYRITIRICISI .
Deyimler
Deyimleri Ayrtrmak: Problem
Bir Deyimi Ayrtrmak
Bir Deyimi Paralara Ayrmak ...
Basit Bir Deyim Ayrtrcs ...
Ayrtrcy Anlayalm .
Ayrtrcya Deiken Eklemek ...
Yinelenerek inen Ayrtrcda Sz Dizimi Kontrol
Denenecek Birka ey ...

EK A: XML AIKLAMALARI REFERANSI
XML Aklama mleri ...
XML Belgelemesinin Derlenmesi .
XML Belgeleme rnei .

EK B: C# VE ROBOTK ..




















740
741
741
742
742
743
746
746
749
754

755

756
757
758
759
762
767
768
776
777

779

780
781
782

784
























B R N C B L M

C#'IN DOUU











































1

HERKES N C#
KISIM I C# DL

14
C#, programlama dillerinin sregelen geliiminde bir sonraki adm temsil eder, C#n
ortaya knn kkleri derinlere, gemi birka yl boyunca bilgisayar dillerinin geliimini
nitelemekte olan gelitirme ve adaptasyon srelerine kadar uzanr. Daha nce ortaya kan
baarl dillerin tmnde olduu gibi, C# da bir yandan programlama sanatn daha ileriye
tarken, te yandan gemiin zerine ina edilmitir.
Microsoft tarafndan .NET Frameworkn (.NET ats) geliimini desteklemek amacyla
gelitirilen C#, zamann snavndan gemi zelliklerinin ve en son teknolojik yeniliklerin
gcnden yararlanmaktadr. C#, modern kurumsal biliim ortamlar iin programlar yazmaya
ynelik olduka kullanl ve verimli yntemlerden biridir. Windows, internet, eitli bileenler
vs, bu modern kurumsal biliim ortamlar kapsamnda yer almaktadr. Bu srete C#, program-
lama manzarasn yeniden tanmlamtr.
Bu blmn amac C# tarihsel adan yerine yerletirmektir. Bunu gerekletirirken
C#n ortaya kna neden olan faktrler, C#n tasarm felsefesi ve dier bilgisayar
dillerinden nasl etkilendii de bu kapsamda ele alnacaktr. Bu blmde ayrca, C# ile .NET
Framework arasnda nasl bir iliki olduu da aklanmaktadr.
C# Aile Aac
Bilgisayar dilleri bolukta asl deildir. Aslnda, bilgisayar dilleri birbirleriyle
balantldr; her yeni dil, kendisinden nceki dillerden bir ekilde etkilenmitir. Farkl bitki
trlerinin, birbirlerinin polenlerini kullanarak yeni bitki trleri oluturmas gibi bir durum sz
konusudur. Benzer ekilde, bir dilin zellikleri bir dierine uyarlanm, varolan bir dile bir
yenilik eklenmi veya eski bir zellik varolandan karlmtr, Bu ekilde diller gelimekte ve
programlama sanat ilerlemekledir. C# da bu balamda bir istisna deildir.
C# zengin bir programlama mirasna sahiptir. C# direkt olarak dnyann en baarl
programlama dillerinin ikisinden tretilmitir: C ve C++ . Ayrca bir bakasyla da yakndan
ilikilidir, Java. Bu ilikilerin doasn anlamak, C# anlamak iin kritik neme sahiptir. Bu
nedenle, C# bu dilin tarihi erevesine oturtarak incelemeye balyoruz.
C: Modern Programlama ann Balangc
Cnin ortaya k programlamann modern ann balangcna iaret eder. C, Dennis
Ritchie tarafndan 1970te, UNIX iletim sistemi kullanan DEC PDP-11 zerinde icat edildi.
Daha nceki baz diller, zellikle Pascal, kayda deer bir baar elde etmi olsa da, bugnk
programlamann gidiatn belirleyen modeli kuran C olmutur,
C, 1960larn yapsal programlama (structured programming) devrimi ile ortaya kt.
Yapsal programlama ncesinde byk programlar yazmak zordu, nk program mant
"spagetti kod" olarak bilinen, takibi g, bir takm arapsana dnm atlamalar, arlar ve
dnlerden ibaret olan bir program yapsna dnme eilimindeydi. Yapsal dillerin bu
probleme getirdii are; dzgn tanmlanm kontrol ifadeleri, yerel deikenli alt rutinler
(subroutines) ve dier gelimi zelliklerdir. Yapsal dilleri kullanarak bir dereceye kadar
byk programlar yazmak mmkn hale geldi.
BLM 1: C#IN DOUU

HERKES N C#
15
O zamanlar baka yapsal diller de mevcut olmasna ramen gc, estetii ve ifade
edilebilirlii baaryla birletiren ilk dil C oldu. Cnin ksa ve z ama ayn zamanda kullanm
kolay sz dizimi, kontroln (dilde deil de) programcda olmasna dayanan felsefesiyle
birleince ok ksa bir srede birok kiinin dier dilleri brakp Cye dnmesiyle sonuland.
Bugnn bak asyla anlalmas biraz g olabilir ama C, programclarn uzun zamandr
bekledii taze bir soluktu. Sonu olarak; C, 1980'lerin en yaygn olarak kullanlan yapsal
programlama dili halini ald.
Her eye ramen, saygn C dilinin bile kstlayc ynleri vard. En zahmetli ynlerinden
biri byk programlar ele almadaki yetersizliiydi. Proje belirli bir boyuta ulat zaman C
dili adeta bir engele arpar ve bu noktadan sonra C programlar anlalmas ve srdrlmesi zor
bir hal alr. Bu limite tam olarak ne zaman ulalaca programa, programcya ve eldeki ara-
lara bal olmakla birlikte 5,000 satr gibi ksa bir kodda bile bu durumla karlalabilmektedir.
Nesne Ynelimli Programlamann ve C++n Douu
1970'lerin sonlarna doru birok projenin boyutu, yapsal programlama
yntembilimlerinin ve C dilinin baa kabilecei snrlara ya yaklamt ya da ulamt. Bu
problemi zmek amacyla nesne ynelimli programlama (OOP Object Oriented
Programming) denilen yeni bir programlama yntemi ortaya kmaya balad. Nesne ynelimli
programlamay kullanarak, bir programc ok daha byk programlarn stesinden
gelebilecekti. Sorun, o zamanlar en popler dil olan Cnin nesne ynelimli programlamay
desteklememesiydi. Cnin nesne ynelimli bir versiyonu iin duyulan istek en sonunda C++n
ortaya kmasna neden oldu.
C++, Bjarne Stroustrup tarafndan Murray Hill, New Jerseydeki Bell Laboratuarlarnda
I979da icat edilmeye baland. Stroustrup, bu yeni dili ilk nce "C with Classes" ("Snfl C")
olarak adlandrd. Ancak, 1983'te dilin ismi C++ olarak deitirildi. C++ , C dilinin btnn
iermektedir. Bu nedenle C, C++n zerine ina edildii bir temeldir. Stroustrup'un C zerine
yapt deiikliklerin pek ou, nesne ynelimli programlamay desteklemek amacyla
tasarlanmt. Yeni dili C temeli zerine ina ederek Stroustrup, nesne ynelimli programla-
maya yumuak bir gei salamtr. Bir C programcsnn nesne ynelimli yntembilimin
avantajlarndan yararlanmadan nce, btnyle yeni bir dil renmek zorunda kalmak yerine,
sadece bir-iki yeni zellik renmesi gerekecekti.
C++ 1980lerin byk blmn, arka planda, kapsaml bir gelime kaydederek geirdi.
1990'larn bandan itibaren C++ genel kullanm iin hazrd; stelik, poplaritesi de adeta
patlama yapmt. On yllk srecin sonuna gelindiinde C++ en yaygn olarak kullanlan prog-
ramlama dili halini almt. Bugn halen, yksek performansl, sistem seviyesinde kod gelitir-
mek iin C++ stn bir dildir.
C++n kefinin bir programlama dili ortaya karmaya ynelik bir giriim olmadn anla-
mak kritik neme sahiptir. Bilakis, C++ zaten ok baarl bir dilin gelitirilmi haliydi. Dillerin
geliimi ile ilgili bu yaklam - mevcut bir dil ile balayp, onu daha da ileriye tamak - bugn
bile devam etmekte olan bir trendin ncs oldu.

HERKES N C#
KISIM I C# DL

16
nternet ve Javann Gelii
Programlama dillerindeki bir sonraki balca ilerleme Java ile gerekletirilmitir. nceleri
Oak olarak adlandrlan Java ile ilgili almalar I99lde Sun Microsystemsda balad. Java'nn
tasarmnn arkasnda yer alan esas src g James Gosling'di. Patrick Naughton, Chris
Warth, Ed Frank ve Mike Sheridann da Java zerinde ayrca rol oldu.
Java, sz dizimi ve felsefesi C++tan alnan yapsal ve nesne ynelimli bir dildir. Javann
yeniliki zellikleri, programlama sanatndaki ilerlemelerden ok fazla etkilenmedi (geri bu
ilerlemelerin bir ksmnn kukusuz etkisi olmutur); bu zellikleri daha ziyade biliim orta-
mnda yaanan deiiklikler biimlendirdi. nternet'in genel kullanma almas ncesinde,
programlarn birou belirli bir CPU ve belirli bir iletim sistemi iin yazlyor, derleniyor ve
ynlendiriliyordu. Programclarn kodlarn yeniden kullanmay sevdikleri her zaman iin ge-
erli bir durum olsa da, bir program kolaylkla bir ortamdan dierine aktarma becerisi halen
eriilmesi gereken bir zellikti ve tanabilirlik (portability), dier acil problemlerin yannda,
ancak arka koltukta yer bulabiliyordu. Ancak, birok farkl tipte CPUnun ve iletim sisteminin
birletirildii nternet'in kyla birlikte, eski tanabilirlik problemi de yeniden gndeme
geldi. Tanabilirlik problemini zmek iin yeni bir dile ihtiya vard. te bu yeni dil Java'yd.
Java'nn tek nemli zellii (ayrca, hzla kabul grmesinin de nedeni), platformlar
arasnda tanabilir kod gelitirme becerisi olmasna ramen Java'y tevik eden asl enerjinin
nternet olmadn kaydetmek enteresandr. Asl tevik, gml denetleyiciler (embedded
controllers) iin yazlm gelitirmek amacyla kullanlabilecek platformdan bamsz bir dile
(cross-platform language) olan ihtiyatr. 1993'te, gml denetleyiciler iin kod gelitirirken
ortaya kan platformlar arasnda tanabilirlii ile ilgili hususlarla nternet iin kod
gelitirmeye alrken de karlald arlk netlemiti. Hatrlaynz: nternet, birok farkl
tipte bilgisayarn yaad ok geni, datk bir biliim evrenidir. Tanabilirlik problemini
kk lekte zen tekniklerin aynlar, byk lekte nternet'e de uygulanabilir.
Java, programn kaynak kodunu bytecode denilen bir ara dile dntrerek tanabilirlii
salyordu. Bu bytecode daha sonra Java Sanal Makinesi (Java Virtual Machine - JVM)
tarafndan altrlyordu. Bu nedenle, bir Java kodu JVMin mevcut olduu her ortamda
altrlabilecekti. Ayrca, JVMi uygulamak nispeten kolay olduu iin JVM ok sayda
ortamda kolayca kullanlabiliyordu.
Javann "bytecode" kullanm hem Cye hem de C++a gre kkten farkllk gsteriyordu.
C ve C++ derlendiinde hemen hemen her zaman altrlabilir makine kodu elde ediliyordu.
Makine kodu ise belirli bir CPU ve iletim sistemine sk skya baldr. Yani, bir C/C++
programn farkl bir sistemde altrmak istemiseniz, programn yeniden derlenmesi ve bu
ortam iin spesifik olarak makine kodunun retilmesi gerekecekti. Bu nedenle, ok eitli
ortamlarda alacak bir C/C++ program gelitirmek iin programn birka farkl altrlabilir
versiyonuna ihtiya vard. Bu pratik olmad gibi ayn zamanda maliyetliydi de. Java'nn ara
dil kullanm zarif ve maliyet asndan hesapl bir zmd. Aynca bu, C#n kendi amalar
dorultusunda adapte edecei bir zmd.
BLM 1: C#IN DOUU

HERKES N C#
17
nceden bahsedildii gibi, Java; C ve C++n soyundan gelmektedir. Sz dizimi Cyi
temel alr; nesne modeli ise C++tan gelitirilmitir. Java kodu ne ileri ne de geri ynde C veya
C++ ile uyumlu olmasa da, Java'nn sz dizimi yeteri kadar benzer olduu iin, ok sayda
programcdan oluan mevcut C/C++ programclar ekibi ok az bir aba ile Javaya
kayabileceklerdi. stelik Java mevcut bir yntemin zerine ina edilmi ve gelitirilmi olduu
iin Gosling ve arkadalar yeni ve yeniliki zelliklere odaklanmakta serbesttiler. Tpk
Stroustrupun C++ gelitirirken tekerlei yeniden icat etmesine gerek olmad gibi,
Gosling'in de Javay gelitirirken btnyle yeni bir dil icat etmesi gerekmiyordu. laveten,
Javann ortaya kyla C ve C++ yeni bilgisayar dillerinin zerine ina edilecei onaylanm
bir katman olmu oluyordu.
C#n Douu
Java, nternet ortamnda tanabilirlii evreleyen birok hususu baaryla ortaya koymu
olmasna ramen, Javann da yetersiz kald baz zellikler hala mevcuttur. Bunlardan biri,
diller arasnda uyum iinde alma (cross-language interoperability) olarak tarif edilebilecek
zelliidir Buna ayrca, kark dillerde programlama (mixed-language programming) da denir.
Bu, bir dilde retilmi bir kodun bir baka dilde retilmi kodla birlikte kolaylkla alma
becerisidir. Diller arasnda uyum iinde alma zellii byk, datk yazlm sistemleri
gelitirirken gereklidir. Bu, ayrca programlama yazlm bileenleri iin de istenilen bir zellik-
tir. nk en kymetli bileen; en ok sayda iletim ortamnda, en eitli bilgisayar dilli
yelpazesinde kullanlabilen bileendir.
Java'nn yoksun olduu bir dier zellik ise Windows platformlaryla tam entegrasyondur.
Java programlar (Java Sanal Makinesinin kurulmu olduunu varsayarak) Windows ortamnda
altrlabilir olmalarna ramen, Java ve Windows yakndan ilikili deildir. Windows dn-
yada en yaygn olarak kullanlan iletim sistemi olduundan, Windows iin dorudan destekten
yoksun olmas, Java iin bir dezavantajdr.
Bu ve dier ihtiyalara cevap vermek amacyla Microsoft, C# gelitirdi. C#, 1990larn
sonlarna doru Microsoftta ortaya kt ve Microsoftun .NET stratejisinin btnnn bir par-
as oldu. C# ilk kez 2000in ortalarnda alfa versiyonu olarak piyasaya kt. C#n ba mimar,
eitli byk baarlara imza atm bulunan, dnyann nde gelen dil uzmanlarndan Anders
Hejlsbergdir. rnein, Hejlsberg 1980'lerde ok baarl ve gl bir dil olan Turbo Pascaln
orijinal yazardr. Turbo Pascaln sadeletirilmi uygulamas, gelecein tm derleyicileri iin
standartlar belirlemiti.

C#; C, C++ ve Java ile dorudan balantldr. Bu tesadf deildir. Bunlar, dnyada en
yaygn olarak kullanlan - ve en fazla sevilen - programlama dillerinden dr. stelik bugn
profesyonel programclarn neredeyse tamam C ve C++, birou da Java'y bilmektedir. C#
salam ve iyi anlalr bir temel zerine ina ederek bu dillerden C#a kolay bir gei de
salanm oldu. Hejlsberg iin tekerlei yeniden icat etmek ne gerekli ne de istenilir bir du-
rum olmad iin, kendisi belirli gelimelere ve yeniliklere odaklanmakta serbestti.

HERKES N C#
KISIM I C# DL

18
C#n aile aac ekil 1.1de gsterilmektedir. C#n dedesi Cdir. Cden C# sz dizimini,
anahtar kelimelerinin birounu ve operatrlerini almtr. C#, C++ ile tanmlanan nesne
modeli zerine kurulmutur ve bu nesne modelini gelitirmitir. C veya C++ biliyorsanz C#
ile adeta kendinizi evinizde hissedeceksiniz.
C# ve Java arasndaki iliki biraz daha karmaktr. Daha nce akland gibi, Java da C
ve C++ 'tan tremitir. Java da C/C++ sz dizimini ve nesne modelini paylamaktadr. Tpk
Java gibi, C# da tanabilir kod retmek amacyla tasarlanmtr. Ancak C#, Javadan
trememitir. Aksine, C# ve Java ortak bir soyu paylaan, fakat birok nemli adan farkllk
gsteren birer kuzen gibidir. Her eye ramen, bunun iyi bir taraf da vardr: Eer Javay
biliyorsanz birok C# kavram size tandk gelecektir. Aksi de dorudur: ayet gelecekte Java
renmeniz gerekli olursa, C# ile rendiiniz birok ey Java'da da geerli olacaktr.
Bu kitabn konular iinde uzun uzadya inceleyeceimiz C#n pek ok yeni zellii
mevcuttur. Ancak C#n en nemli zelliklerinden bir ksm, standart olarak mevcut olan ve
yazlm bileenleri iin sunulan destek ile balantldr. Aslnda, C# bileen ynelimli bir dil
(component-oriented language) olarak nitelenmektedir; nk C#, yazlm bileenlerini yazmak
iin btnleik destek iermektedir.
rnein C#, bileenleri oluturan eleri, mesela zellikleri, metotlar ve olaylar dorudan
destekleyen zellikler ierir. Ancak, C#n kark dillerin hkim olduu bir ortamda ala-
bilme becerisi belki de C#n bileen ynelimli zelliklerinden en nemlisidir.








EKL 1.1: C# aile aac

C# ile .NET Framework Arasndaki Balant
C# kendi bana incelenebilecek bir bilgisayar dili olmasna ramen C#n altrma
ortam (runtime environment) ile, yani .NET Framework ile zel bir ilikisi vardr. Bunun iki
sebebi vardr. Birincisi, C# balangta Microsoft tarafndan .NET Framework iin kod
gelitirmek amacyla tasarlanmt. kincisi, C# tarafndan kullanlan ktphaneler, .NET
Framework tarafndan tanmlanan ktphanelerdi. Yani, C# dilini .NET ortamndan ayrmak
C
C++
Java C#
BLM 1: C#IN DOUU

HERKES N C#
19
mmkn olsa dahi her ikisi birbiriyle sk skya baldr. Bu nedenle, .NET Framework' genel
olarak anlamak ve bunun C# iin nemini kavramak gereklidir.
.NET Framework Nedir?
.NET Framework, ok datk (highly-distributed), bileen ynelimli uygulamalarn
gelitirilmesini ve yrtlmesini destekleyen bir ortam tanmlamaktadr. .NET Framework,
farkllk gsteren bilgisayar dillerinin birlikte almasn mmkn klar ve Windows platformu
iin gvenlik, tanabilirlik (programlar asndan) ve ortak bir programlama modeli salar.
.NET Frameworkn doas gerei yalnzca Windows ile snrl olmadn (geri bugn iin
mevcut tek ortam bu olmasna ramen) belirtmemiz gereklidir. Bunun anlam udur: .NET
Framework iin yazlm programlar gelecekte Windows olmayan ortamlara da tanabilecektir.
.NET Framework C# ile ilikili olduu iin iki ok nemli unsuru tanmlamaktadr.
Bunlardan ilki Common Language Runtimedr (CLR - Ortak Dil alma Zaman) Bu,
programnzn almasn idare eden sistemdir. Dier avantajlarnn yan sra CLR, .NET
Frameworkn programlarn tanabilirliini mmkn klan, kark dilde programlamay
destekleyen ve gvenlii salayan bir parasdr.
kinci unsur ise .NET snf ktphanesidir. Bu ktphane, programnzn altrma
ortamna erimesine imkn verir. rnein, ekranda bir ey gstermek gibi bir I/O (Giri/k)
ilemi gerekletirmek istiyorsanz, bunun iin .NET snf ktphanesini kullanacaksnz. ayet
programlamay yeni reniyorsanz, snf terimi size yeni gelebilir. Bu terim kitabn daha son-
raki blmlerinde ayrntl aklanyor olmakla birlikte, imdilik ksa bir tanm yeterli olacaktr:
Snf, programlar organize etmeye yarayan nesne ynelimli bir zelliktir. Bir program .NET
snf ktphanesinde tanmlanan zelliklerle kstl kalrsa, .NET alma zaman sisteminin
desteklendii her yerde altrlabilir. C# otomatik olarak .NET snf ktphanesini kulland
iin, C# programlar .NET ortamlarnn tmne otomatik olarak tanabilir,
Common Language Runtime Nasl alr?
CLR, .NET kodunun altrlmasn (yrtlmesini) idare eder. CLR u ekilde alr: Bir
C# programn derlediinizde, derleyiciden elde edilen kt altrlabilir bir kod deildir.
Bilakis bu, Microsoft Intermediate Language (MSIL) denilen zel bir tipte szde kod
(pseudocode) ieren bir dosyadr. MSIL, spesifik bir CPUdan bamsz olan birtakm
tanabilir komutlar tanmlar. Astnda, MSIL tanabilir bir Assembly dili tanmlar. Dier bir
husus da udur: MSIL her ne kadar Java'nn bytecode'una benziyor ise de her ikisi ayn
deildir.
Program alt zaman ara kodu altrlabilir bir koda dntrmek CLRin grevidir.
Bylece, MSIL elde edilecek ekilde derlenen her program CLRin gereklendii her ortamda
altrlabilir. Bu. .NET Framework'n tanabilirimi temin etme biiminin bir parasdr.
Microsoft Intermediate Language, bir JIT derleyici kullanlarak altrlabilir bir koda
evrilir, J1T, Just-In-Timea karlk gelir (yani, Tam Zamannda demektir). Sre yle

HERKES N C#
KISIM I C# DL

20
geliir: Bir .NET program alt zaman CLR, JIT derleyiciyi etkin klar. JIT derleyici
programnzn paralarnn her birine duyulan ihtiyac temel alarak MSIL'i yerel dile
dntrr. Bylece, C# programnz balangta MSIL retecek ekilde derlenmi olsa bile
aslnda yerel kod gibi alacaktr. Bunun anlam udur: Programnz balangta yerel kod
retecek ekilde derlenmi olsayd, elde etmi olaca alma hzna yakn bir hzda alacak,
stelik MSIL'in tanabilirlik avantajlarna da kavuacaktr.
Bir C# programn derlendiinizde, MSlLe ek olarak elde edilen bir dier ey de metadata
olarak adlandrlan ktdr. Metadata, programnzn kulland verileri tarif eder ve kodunuzun
dier kodlarla etkilemesini mmkn klar. Metadata, MSIL ile ayn dosya iinde yer alr.
Kontrol Altna Alnan ve Alnmayan Kodlar
Genel olarak, bir C# program yazdnzda kontrol altna alnan kod (managed code)
denilen bir kod gelitirirsiniz. Kontrol altna alnan kod, Common Language Runtime'n
kontrolnde az nce anlatlan ekilde altrlr. Kontrol altna alnan kod CLRin kontrolnde
alt iin, belirli kstlamalara tabidir - bunun yannda, baz avantajlar da elde eder.
Kstlamalar kolaylkla tarif edilir ve karlanr: Derleyici, CLRa ynelik bir MSIL dosyas
retmelidir (C# bunu gerekletirir) ve .NET Framework ktphanelerini kullanmaldr (C#
bunu da gerekletirir). Kontrol altna alnan kodun avantajlar pek oktur. Modern bellek
ynetimi, dilleri kartrma becerisi, daha sk gvenlik, srm kontrol destei ve etkileecek
yazlm bileenleri iin net bir yntem, bu avantajlar arasnda yer alr.
Kontrol altna alnan kodun tam tersi ise kontrol altna alnmayan koddur (unmanaged
code). Kontrol altna alnmayan kod, Common Language Runtime allnda almaz. Yani,
.NET Frameworkn gelitirilmesi ncesinde yer alan Windows programlarnn tm kontrol
altna alnmayan kod kullanrlar. Kontrol allna alnan ve alnmayan kodlarn bir arada
almas mmkndr; bylece C#n kontrol altna alnabilir kod rettii gerei, C#n
nceden mevcut programlarla birlikte alabilme becerisini kstlamaz.
Common Language Specification
Kontrol altna alnan kodlarn tm CLR ile salanan avantajlardan yararlanyor olsa da,
ayet kodunuz farkl dillerde yazlm programlar tarafndan kullanlacaksa, kullanlabilirlii en
st seviyeye karmak iin kodunuzun Common Language Specificationa (CLS - Ortak Dil
Spesifikasyonu) sk skya yapmas gereklidir. CLS, farkl dillerde ortak olan zellikleri tarif
eder. CLS uyumu, dier diller tarafndan kullanlacak yazlm bileenleri gelitirirken zellikle
nemlidir. CLS, Common Type Systemin (CTS - Ortak Tip Sistemi) bir altkmesini ierir.
CTS, veri tiplerini ilgilendiren kurallar tarif eder. Elbette, C# hem CLSi hem de CTSi
desteklemektedir.





K N C B L M

C#A GENEL BR BAKI











































2

HERKES N C#
KISIM I C# DL

22
Bir programlama dilini renirken zorlanlan konularn ak farkla en banda yer alan
husus, elerin bi birinin tek bana mevcut olmad gereidir. Aksine, dilin bileenleri
birlikle alrlar. Bu ekilde birbiriyle bantl olmak, C#n dier zelliklerine dokunmadan
tek zelliini anlatmay zorlatrr. Genellikle, bir zellii ele alrken bir bakas hakknda n
bilgi sahibi olmak gereklidir. Bu problemin stesinden gelmeye yardmc olmak amacyla, bu
blmde baz C# zelliklerinin ksa bir zeti sunulmaktadr. Bir C# programnn genel yaps,
baz temel kontrol ifadeleri ve operatrler, bu blmde ele alnan zellikler arasnda yer
almaktadr. Bu blmde ok fazla ayrntya girilmezken, daha ok herhangi bir C#
programnda rastlanabilen genel kavramlar zerine konsantre olunuyor. Burada ele alnan
konularn birou, Ksm Iin kalan blmlerinde daha ayrntl olarak incelenmektedir.
Nesne Ynelimli Programlama
C#n merkezinde nesne ynelimli programlama (OOP - Object Oriented Programming)
yer almaktadr Nesne ynelimli yntembilim C#tan ayrlmaz; tm C# programlar en azndan
bir lye kadar nesne ynelimlidir. Nesne ynelimli programlamann C# iin neminden
dolay, basit bile olsa bir C# program yazmaya balamadan nce nesne ynelimli
programlamann temel prensiplerini kavramak yararldr.
Nesne ynelimli programlama, programlama yaklam iin gl bir yntemdir.
Bilgisayarn icadyla birlikte programlama yntembilimleri, her eyden nce programlarn
artan karmaklna uyum salamak amacyla ok ciddi lde deiti. rnein,
bilgisayarlarn icat edildii yllarda programlama, bilgisayarn n paneli kutlanlarak, ikili
(binary) makine komutlarna karlk gelen dmelere basmak suretiyle gerekletiriliyordu.
Programlar birka yz satr uzunluunda olduu mddete bu yntem ise yaryordu.
Programlar byynce Assembly dili icat edildi; bylece programclar, makine komutlarna
karlk gelen sembolik iaretleri kullanarak daha byk ve artan karmaklktaki programlar
ele alabileceklerdi. Programlar bymeye devam ettike, programclara karmaklkla baa
kabilmek iin daha fazla ara sunan FORTRAN ve COBOL gibi yksek seviyeli diller
ortaya kt. Bu ilk diller, artk atlama noktasna geldiinde yapsal programlama icat edildi.
unu bir dnn: Programlamann her bir kilometre tanda, programclarn giderek
daha da artan karmaklkla baa kmalarna imkn veren teknikler ve aralar gelitirilmitir.
Bu srecin her admnda yeni yntem, nceki yntemlerin en iyi elemanlarn alm ve
ilerlemitir. Bu, nesne ynelimli programlama iin de geerlidir. Nesne ynelimli
programlama ncesinde birok proje, yapsal programlamann artk ie yaramad noktaya
yaklamt (veya amt). Karmakl daha iyi ele alabilen bir yntemlere ihtiya vard ve
zm, nesne ynelimli programlamayd.
Nesne ynelimli programlama, yapsal programlamaya zg en iyi kavramlar alm ve
bunlar baz yeni kavramlarla birletirmiti. Sonuta programlar farkl ve daha iyi ekilde
organize edilebilecekti. En genel anlamda, bir program iki yntemden biri kullanlarak
organize edilebilir: kodu etrafnda (meydana gelenler) veya verileri etrafnda (etkilenenler).
Sadece yapsal programlama teknikleri kullanlarak programlar genellikle kod etrafnda
organize edilir. Bu yntem ayrca veriye etki eden kod olarak da dnlebilir.
BLM 2: C#A GENEL BR BAKI

HERKES N C#
23
Nesne ynelimli programlar dier ekilde alrlar. Bu tr programlar koda eriimi
kontrol eden veri temel prensibine dayanarak veri etrafnda organize edilirler. Nesne
ynelimli bir dilde, verileri ve bu verilere etki etmeye izin verilen kodu tanmlarsnz.
Bylece, bir veri tipi bu veri zerine uygulanabilecek ilemleri tam olarak tanmlar.
Nesne ynelimli programlamann prensiplerini desteklemek amacyla, C# da dhil olmak
zere tm nesne ynelimli diller ortak zellie sahiptir: ilikili verilerin paketlenmesi
(encapsulation), ok biimlilik (polymorphism) ve kaltm. imdi bunlar tek tek inceleyelim.
likili Verilerin Paketlenmesi
Verilerin paketlenmesi (encapsulation), kodun maniple ettii verilerle kodu birbirine
balayan ve her ikisini dardan gelebilecek istenmeyen etkilerden ve hatal kullanmlardan
koruyan bir programlama mekanizmasdr. Nesne ynelimli bir dilde kod ve veri, kendi
kendisini ieren bir kara kutu oluturacak ekilde birbirlerine balanabilir. Gerekli veri ve
kodun tm kutunun iinde mevcuttur. Kod ve veri bu ekilde balannca bir nesne (object)
oluturulmu olur. Dier bir deyile nesne, verilerin paketlenmesini (encapsulation)
destekleyen bir aygttr.
Nesne iindeki kod, veri veya her ikisi de bu nesneye zel (private) veya ak (public)
olabilirler. zel kod veya veri, sadece bu nesnenin paralar tarafndan bilinir ve eriilebilir.
Yani zel kod veya veri, sz konusu nesnenin dnda kalan program paralar tarafndan
eriilemez. Kod veya veri ak olduunda ise, sz konusu kod ve veri bir nesnenin iinde
tanmlanm olsa bile programnzn dier paralar tarafndan eriebilirler. Nesnelerin ak
ksmlar tipik olarak, zel elere kontroll bir arayz salamak amacyla kullanlr.
C#n temel veri paketleme birimi snftr (class). Snf, bir nesnenin eklini tanmlar.
Snf, hem verileri hem de bu veriler zerinde ilem yapacak kodu belirtir. C#ta, nesneleri
ina etmek amacyla snf spesifikasyonu kullanlmaktadr. Nesneler bir snfn rnekleridir.
Yani, snf aslnda bir nesnenin ne ekilde ina edileceini belirten birtakm planlardan
ibarettir.
Snf oluturan kod ve veri sz konusu snfn yeleri (members) olarak adlandrlrlar.
zellikle, snf tarafndan tanmlanan verilerden ye deikenler (member variables) veya
rnek deikenler (instance variables) olarak sz edilir. Metot (method), C#ta alt rutin iin
kullanlan bir terimdir. Eer C/C++a ainaysanz C# programcsnn metot diye adlandrd
eyin C/C++ programcs tarafndan fonksiyon (ilev) olarak adlandrldn bilmek yararl
olabilir. C# dili C++tan dorudan tredii iin C# metotlarndan sz edildiinde fonksiyon
(ilev) terimi de yaygn olarak kullanlmaktadr.
ok Biimlilik
ok biimlilik (polymorphism - Yunanca'da birok form anlamna gelir), genel bir
etkinlikler snfna erimek iin bir arayze imkn veren bir zelliktir. ok biimliliin en
basit rnei, otomobil direksiyonudur. Gerekte hangi tipte bir vites mekanizmas kullanlrsa

HERKES N C#
KISIM I C# DL

24
kullanlsn direksiyon (arayz) hep ayn ekildedir. Yani, arabanz ister manuel vitesli, ister
otomatik vitesli olsun, direksiyon hep ayn ekilde alr, Bylece, direksiyonu sola
evirmek, hangi tipte vites kullanlrsa kutlanlsn arabann sola dnmesine neden olur. Tek
tip bir arayzn avantaj, elbette, direksiyonun nasl altracanz bildikten sonra herhangi
bir tipte arabay srebilecek olmanzda yatar.
Ayn prensip programlamaya da uygulanabilir. rnein, bir yn (ilk giren son kar
esasna dayanan bir liste) dnn. farkl tipte yna gereksinim duyan bir programnz
olabilir. yle ki, ynlardan biri tamsaylar iin, biri kayan noktal deerler iin, dieri de
karakterler iin kullanlmaktadr. Bu rnekte, ynlarda saklanan veriler farkl bile olsa,
ynlarn her birini gerekleyen algoritma ayndr. Nesne ynelimli olmayan bir dilde, her
biri farkl bir isim kullanan farkl yn rutini gelitirmeniz gerekecekti. Ancak, C#ta ok
biimlilik zelliinden tr spesifik durumun yle de alan tek bir genel yn rutini
gelitirebilirsiniz. Bu sayede, bir yn kullanmay rendiiniz andan itibaren hepsini
kullanabilirsiniz.
Daha genel bir yaklamla, ok biimlilik kavram sk sk tek arayz, ok sayda metot
deyiiyle de ifade edilir. Bu, bir grup ilikili etkinlik iin genel bir arayz tasarlamak
mmkndr, anlamna gelmektedir. ok biimlilik, genel bir etkinlik snfn belirtmek
amacyla ayn arayzn kullanlmasna imkn vererek karmakl azaltmaya yarar. Her bir
durum iin hangi spesifik etkinliin (yani metodun) uygulanacan tercih etmek derleyicinin
grevidir. Siz programclarn bu tercihi elle yapmanza gerek yoktur. Sizin sadece genel
arayz hatrlamanz ve deerlendirmeniz gerekir.
Kaltm
Kaltm (inheritance), bir nesnenin dier bir nesnenin zelliklerini ele geirebilmesini
salayan bir yntemdir. Bu nemlidir, nk kaltm, hiyerarik snflandrma kavramn
destekler. Bir dnrseniz, bilgilerin byk blm hiyerarik (yani, yukardan aaya
doru) snflandrma sayesinde ynetilebilir klnr. rnein, krmz tatl elma, elma
snflandrmasnn bir parasdr. Elma, meyve snfnn bir parasdr. Meyve ise daha byk
bir snf olan yiyecek snfnn altnda yer alr. Yani, yiyecek snf, ayn zamanda mantksal
olarak kendisinin bir alt snf olan meyve snfna da uygulanabilecek belirli zelliklere
(yenilebilir, besleyici vs.) sahiptir. Bu zelliklere ek olarak, meyve snfnn da kendisini dier
snflardan ayrt eden, kendisine zg zellikleri (sulu, tatl vs.) vardr. Elma snf bu tr
zelliklerden elmaya zg olanlar (aata yetiir, tropik meyve deildir vs.) tanmlar.
Krmz Tatl elma bu durumda, kendisinden nce gelen tm snflarn tm zelliklerini
kaltm yoluyla devralacaktr ve bu zelliklerden sadece kendisini esiz klanlar
tanmlayacaktr.
Kaltm kullanlmasayd, her nesne kendi zelliklerinin tmn aka tanmlamak
zorunda kalacakt. Kaltm sayesinde bir nesnenin kendi snf iinde sadece kendisini esiz
klan zellikleri tanmlamas yeterlidir. Nesne, genel zelliklerini atalarndan kaltm yoluyla
devralabilir. Bylece, bir nesnenin daha genel bir durumun spesifik bir rnei olmasn
mmkn klan, kaltm mekanizmasdr.
BLM 2: C#A GENEL BR BAKI

HERKES N C#
25
lk Basit Program
Artk gerek bir C# programna gz atma zaman geldi. Aada gsterilen program
derleyerek ve altrarak balayacaz:
/*
Bu basit bir C# programidir.
Bu programa Example.cs adini verelim.
*/
using System;

class Example {

// Bir C# programi Main()e cagrida bulunarak baslar.
public static void Main() {
Console.WriteLine(Basit bir C# programi.);
}
}
Bu kitap baskya hazrlanrken mevcut tek C# ortam Visual Studio .NET idi. Visual
Studio .NETi kullanarak bir C# programn iki ekilde dzenleyip derleyebilir ve
altrabilirsiniz.
Birincisi, komut satrndan altrlan derleyiciyi (csc.exe) kullanabilirsiniz, kincisi,
Visual Studio Integrated Development Environment (IDE - Btnleik Gelitirme Ortam)
kullanabilirsiniz. Burada her iki yntem de ele alnyor, (ayet farkl bir derleyici
kullanyorsanz, derleyicinizin talimatlarm izleyin.)
C# Komut Satr Derleyicisini (csc.exe) Kullanmak
Ticari projelerinizde muhtemelen Visual Studio IDEyi kullanacak olmanza ramen C#
komut satr derleyicisi, bu kitapta yer alan rnek programlarn birounu derlemek ve
altrmak iin en kolay yntemdir. Programlar C# komut satr derleyicisi kullanarak
gelitirmek ve altrmak iin aada yer alan adm izleyeceksiniz:
1. Bir metin editr kullanarak program kodlayn.
2. Program derleyin.
3. Program altrrn.
Program Kodlamak
Bu kitapta yer alan programlar Osborneun Web sitesinde mevcuttur: www.osborne.com.
Ancak, programlar elle kodlamak isterseniz, bu konuda zgrsnz. Bu durumda, Notepad
gibi bir metin editr kullanarak program bilgisayarnza kodlamalsnz. Unutmayn, salt
metin dosyalar oluturmalsnz; biimlendirilmi kelime ilemci dosyalar oluturmamaya
dikkat edin, nk kelime ilemci dosyasndaki biimlendirme bilgileri C# derleyicisini
artacaktr. Program kodlarken, dosyaya Example.cs adn verin.

HERKES N C#
KISIM I C# DL

26
Program Derlemek
Program derlemek iin, kaynak dosyann ismini komut satrnda aada gsterildii gibi
belirterek. C# derleyicisini (csc.exe) altrn:
C:\>csc Example.cs
csc derleyicisi, programn MSIL versiyonunu ieren Example.exe adnda bir dosya
oluturur. MSIL altrlabilir bir kod olmamasna ramen, yine de bir exe uzantl dosya
iinde yer alr. Example.exe dosyasn altrmaya kalktnzda Common Language
Runtime otomatik olarak JIT derleyiciyi arr. Her eye ramen dikkatli olun; ayet .NET
Frameworkn kurulu olmad bir bilgisayarda Example.exe dosyasn (veya MSIL ieren
herhangi bir baka exe dosyasn) altrmay deniyorsanz, CLR mevcut olmad iin
program almayacaktr.

NOT




csc.exe derleyicisini altrmaya balamadan nce tipik olarak //Program
Files/Microsoft Visual Studio .NET/Vc7/Bin dizini altnda yer alan
vcvars32.bat isimli toplu ilem (batch) dosyasn altrmanz gerekebilir.
Alternatif olarak, C# iin halen ilk kullanma hazrlanm bir komut satr
oturumunu da balatabilirsiniz. Bunun iin, grev ubuunun Start | Programs
mensndeki Microsoft Visual Studio .NET seenei altnda gsterilen ara
listesinden Visual Studio .NET Command Prompt seeneini iaretlemelisiniz.
Program altrmak
Program gerekten altrmak iin, aada gsterildii gibi, komut satrnda sadece
programn ismini yazmak yeterlidir:
C:\>Example
Program altnda, aadaki kt ekranda grnr:
Basit bir C# programi.
Visual Studio IDE'yi Kullanmak
Visual Studio .NET srm 7den itibaren Visual Studio IDE, C# programlarn
derleyebilir. Visual Studio .NET srm 7'yi kullanarak bir C# programn dzenlemek,
derlemek ve altrmak iin aadaki aamalar izleyeceksiniz. (Visual Studio'nun farkl bir
srmne sahipseniz, farkl aamalar izlemeniz gerekebilir.)

1. File | New | Project komutunu seerek yeni, bo bir C# projesi oluturun.

BLM 2: C#A GENEL BR BAKI

HERKES N C#
27
2. Visual C# | Windows seeneini iaretleyin, sonra aada gsterildii gibi Empty
Project seeneini iaretleyin.





3. Proje oluturulduktan sonra, Solution Explorer penceresinde grnen proje isminin
zerine sa fare tuuyla tklayn. Daha sonra, kan balamsal meny kullanarak
Add seeneini iaretleyin. Bundan sonra, Add New tem komutunu sein.
Ekrannz u ekilde grnecektir:












HERKES N C#
KISIM I C# DL

28



4. Add New Item iletiim kurusunu grnce Visual C# Items | Code seeneini ve son
olarak da, Code File seeneini iaretleyin. Ekrannz u ekilde grnecektir:

BLM 2: C#A GENEL BR BAKI

HERKES N C#
29


5. Programnz kodlayn ve dosyaya Example.cs ismini vererek kaydedin. (Bu
kitaptaki kodlar www.osborne.com adresinden indirebileceinizi hatrnzdan
karmayn.) Kaydetme ilemi bittiinde ekrannz ekil 2.1'deki gibi grnecektir.

6. Build | Build Solution komutunu seerek program derleyin.

7. Debug | Start Without Debugging komutunu seerek program altrn.

Program altrdnzda ekil 2.2'deki pencereyi greceksiniz.

NOT


Bu kitaptaki rnek programlar derlemek ve altrmak amacyla her biri iin
yeni bir proje dosyas oluturmanza gerek yoktur. Bunun yerine, ayn C#
projesini kullanabilirsiniz. Tek yapmanz gereken mevcut dosyay silip yeni
dosyay eklemekten ibarettir. Bunun ardndan yeniden derleyin ve altrn.
nceden akland gibi, bu kitabn birinci ksmndaki ksa programlar iin csc komut
satr derleyicisini kullanmak ok daha basit bir yaklamdr. Elbette tercih sizindir.

HERKES N C#
KISIM I C# DL

30

EKL 2.1: Example.cs proje ekran


EKL 2.2: Example programnn Visual Studio IDE altnda alrken kts

Satr Satr lk rnek Program
Example.cs olduka ksa olmasna ramen, tm C# programlarnda ortak olan temel
zelliklerden birkan ierir. imdi gelin, programn isminden balayarak her parasn
yakndan inceleyelim.
C# programnn ismi istee baldr. Program dosyasnn isminin ok nem tad baz
bilgisayar dillerinden (en mehurlarndan biri Java) farkl olarak, C#la byle bir durum sz
konusu deildir. rnek programa Example.cs ismini vermeniz istendi, bylece program
derleme ve altrma ile ilgili komutlar etkili olacakt. Fakat, C# sz konusu olduu
mddete dosyaya baka bir isim de verebilirdiniz. rnein, nceki rnek program
Sample.cs, Test.cs , hatta x.cs olarak adlandrlabilirdi.
BLM 2: C#A GENEL BR BAKI

HERKES N C#
31
Geleneksel olarak, C# programlar .cs uzantsn kullanrlar. Siz de bu gelenee
uymalsnz. Ayrca, birok programc dosyaya dosya iinde tanmlanm ana snfn ismini
verirler. Example.cs dosya isminin tercih edilmesinin nedeni de budur. C# programlarnn
isimleri keyfi olduu iin, bu kitaptaki rnek programlarn birounda isimler aka
belirtilmiyor. Kendi tercih ettiiniz isimleri kullanabilirsiniz.
Program aadaki satrlarla balyor:
/*
Bu basit bir C# programidir.
Bu programa Example.cs adini verelim.
*/
Bu bir aklamadr (comment). Dier pek ok programlama dilinde olduu gibi. C# da
programn kaynak dosyasna kendi grlerinizi eklemenize imkan verir. Aklamann ierii,
derleyici tarafndan dikkate alnmaz. Aklama, programn ileyiini programn kaynak
kodunu okumakta olan herhangi birine tarif eder veya aklar. Bu rnekteki aklama,
program tarif ediyor ve kaynak dosyay Example.cs olarak adlandracanz hatrlatyor.
Elbette, gerek uygulamalarda aklamalar, genellikle programn baz paralarnn ileyiini
veya belirli bir zelliin ne ie yaradn aklarlar.
C# farkl aklama stilini destekler. Programn en stnde yer alan ve yukarda da
gsterilen birden ok satrdan oluan aklamadr. (multiline comment). Bu tr bir aklama
/* ila balamal ve */ ile sona ermelidir. Bu iki aklama simgesi arasnda yer alanlarn
hibiri derleyici tarafndan dikkate alnmaz. sminden anlalaca gibi, birden ok satrdan
oluan aklama, birka satr uzunluunda olabilir. Programdaki bir sonraki satr udur:
using System;
Bu satr programn System isim uzayn kullandn gsteriyor. C#ta isim uzay
(namespace), deklaratif (tanmlamalara ayrlan) bir blge tanmlar. sim uzaylarn daha sonra
ayrntl olarak ele alacaz. imdilik u kadar bahsedelim: Bir isim uzay, bir takm isimleri
dierlerinden ayrmaya yarayan yntemlerden biridir, Aslnda, bir isim uzaynda deklare
edilen isimler baka bir isim uzaynda deklare edilen ayn isimlerle elimeyecektir. rnek
programda System isim uzay kullanlyor System, C#n kulland bir ktphane olan .NET
Framework snf ktphanesi ile ilikili eler iin ayrlm bir isim uzaydr, using anahtar
kelimesi sadece, programn belirtilen isim uzayndaki isimleri kullandn ifade eder.
Programda yer alan bir sonraki kod satr udur:
class Example {
Bu satrda yeni bir snfn tanmlandn deklare etmek iin class anahtar kelimesi
kullanlyor nceden bahsedildii gibi snf, C#n temel veri paketleme birimidir. Example
snfn ismidir. Snf tanm al kme parantezi ({) ile balar ve kapan kme parantezi (})
ile sona erer. ki kme parantezi arasnda yer alan elemanlar snfn yeleridir. u an iin
snfn ayrntlarn ok fazla dert etmeyin. Yalnz, C#ta tm program faaliyetlerinin tek bir

HERKES N C#
KISIM I C# DL

32
snf iinde meydana geldiini de gzden karmayn. C# programlarnn tmnn neden (en
azndan bir para) nesne ynelimli olduunun bir sebebi de ite budur.
Programdaki bir sonraki satr aada da gsterilen tek satrlk aklamadr:
// Bir C# programi Main()e cagrida bulunarak baslar.
Bu, C# tarafndan desteklenen bir dier aklama tipidir. Tek satrlk aklama //
ile balar ve satrn sonunda biter. Genel bir kural olarak, programclar birka satrlk
aklamalar daha uzun grlerini aklamak iin, tek satrlk aklamalar ise ksa, satr-satr
aklamalar iin tercih ederler.
Bir sonraki kod satr aada gsterilmitir:
public static void Main() {
Bu satr Main() metodu ile balyor. nceden bahsedildii gibi, C#ta alt rutinler metot
olarak adlandrlr. Bu satrn ncesinde yer alan aklamadan da anlalaca gibi bu satr,
programn almaya balayaca satrdr. C# uygulamalarnn tm Main()i ararak
almaya balarlar. (Bu, C/C++ programlarnn almaya main()'den balamalarna
benzer.) Bu satrn her parasn tam olarak aklamak iin henz erken, nk bu, baz baka
C# zelliklerinin ayrntl olarak anlalmasn gerektiriyor. Ancak, bu kitaptaki rneklerin
birou bu kod satrn kullanaca iin imdi buna ksaca gz atalm.
public anahtar kelimesi bir eriim belirleyicisidir, Bir eriim belirleyicisi (access
specifier), programn dier blmlerinin bir snfn yesine nasl eriebileceklerini belirler.
Bir snf yesinin ncesinde public yer alyorsa bu ye, deklare edildii snfn dnda kalan
kod tarafndan eriilebilir. (publicin kart privatedr. private, bir yenin tanml
olduu snfn dndaki kod tarafndan kullanlmasn nler.) Bu rnekte Main(), public
olarak deklare edilmektedir, nk Main(), program altnda kendisinin ait olduu snf
dndaki kod (yani, iletim sistemi) tarafndan arlacaktr.

NOT




Bu kitap baskya hazrlanrken, C# aslnda Main()in public olarak deklare
edilmesini art komuyordu. Ancak, Visual Studio ,NET tarafndan desteklenen
bir ok rnekte bu ekilde deklare edilmektedir. Bu, ayrca birok C#
programcsnn da tercih ettii bir yntemdir. Bu nedenlerden tr, bu kitapta
da Main(), public olarak deklare edilecektir. Yine de, biraz farkl bir ekilde
deklare edildiini grrseniz armayn.
static anahtar kelimesi Main()in snfna ait bir nesne tanmlanmadan nce
Main()in arlmasna imkan veriyor. Main(), programn balangcnda arld iin
static anahtar kelimesinin kullanlmas gereklidir. void anahtar kelimesi sadece
Main()in bir ey dndrmediini derleyiciye bildiriyor. Daha sonra reneceiniz gibi,
metotlar da deer dndrebilir. Mainin peinden gelen bo parantezler, Main'e hibir bilgi
aktarlmadn gsteriyor. Main()e veya herhangi bir baka metoda bilgi aktarmann
mmkn olduunu daha sonra reneceksiniz. Bu satrdaki en son karakter ise { karakteridir.
BLM 2: C#A GENEL BR BAKI

HERKES N C#
33
Bu, Main()in gvdesinin baladna iaret ediyor. Bir metodu oluturan kodun tm,
metodun al kme parantezi ile kapan parantezi arasnda yer alacaktr.
Kodun bir sonraki satr aada gsterilmitir. Bu satrn Main()in iinde yer aldna
dikkat edin.
Console.WriteLine("Basit bir C# programi.");
Bu satr ekranda Basit bir C# programi." karakter katarn kt olarak gsterir.
Bu karakter katarnn peinden yeni satr gelir. Program kts aslnda standart olarak yerleik
bir metot olan WriteLine() ile gerekletirilir, Bu rnekte WriteLine(), kendisine
aktarlan karakter katarn ekranda gsterir. Bir metoda aktarlan bilgiye argman (argument)
denir. WriteLine(), karakter katarlarna ek olarak baka tr bilgilerin gsterilmesi iin de
kullanlabilir. Bu satr, konsol giri/klarn (l/O) destekleyen bir nceden tanml snfn
ismi olan Console ile balyor. Consoleu WriteLine() ile birletirerek
WriteLine()n Console snfnn bir yesi olduu derleyiciye bildiriliyor. C#n konsol
ktsn tanmlamak iin nesne kullanyor olmas gerei, C#n nesne ynelimli zelliinin
bir baka kantdr.
Dikkat ederseniz. WriteLine() ifadesi noktal virgl ile sona eriyor, keza programn
balarnda yer alan using System ifadesi de. C#ta tm ifadeler noktal virgl ile sona erer.
Programdaki kimi dier satrlarn noktal virgl ile sona ermemesinin nedeni bunlarn teknik
olarak birer ifade olmamasdr.
Program iindeki ilk } simgesi Main()i sonlandryor, sonuncu } simgesi de Example
snf tanmn sona erdiriyor.
Son bir husus: C#ta byk - kk harf (harf kipi) ayrm vardr. Bunu unutmak ciddi
problemlere neden olabilir. rnein, kazara Main yerine main ya da WriteLine yerine
writeline yazarsanz, yukardaki program hatal olacaktr. stelik, C# derleyicisi Main()
metodunu iermeyen snflar derleyecek olmasna ramen, bunlar altrmann yolu mevcut
deildir. Bu nedenle, Maini yanl yazm olsanz bile derleyici programnz derleyecektir.
Ancak, Example.exenin balang noktasnn tanmlanmadn bildiren bir de hata mesaj
ile karlaacaksnz.
Sz Dizimi Hatalarn Kontrol Altna Almak
Eer imdiye kadar yapmamsanz nceki program kodlayn, derleyin ve altrn.
nceden sahip olduunuz programlama deneyiminizden de bilebileceiniz gibi,
bilgisayarnza kodlar girerken bir eyi kazara hatal yazmak olduka kolaydr. Neyse ki,
hatal bir ey girdiinizde ve derleyici bunu derlemeye altnda, sz dizimi hatas (syntax
error) mesajn verecektir. C# derleyicisi ne yazm olursanz olun kaynak kodunuzdan
anlaml bir eyler karmaya alr. Bu nedenle, rapor edilen hata problemin asl nedenini her
zaman yanstmayabilir. nceki programda, rnein, Main() metodundan sonraki al kme
parantezinin kazara eksik olmas, csc komut satr derleyicisi kullanlarak derlendiinde,

HERKES N C#
KISIM I C# DL

34
aadaki bir dizi hata mesajnn retilmesine neden olur. (IDE kullanlarak derlendiinde de
benzer hatalar ortaya kar.)
Example.cs(12, 28) : error CS1002: ; expected
Example.cs(12, 22) : error CS1002: Invalid token ( in class,
struct, or interface member declaration
Example.cs(15, 1) : error CS1022: Type or namespace
definition, or end-of-file expected
Aka grlyor ki, ilk hata mesaj tamamen yanltr, nk eksik olan noktal virgl
deil, kme parantezidir. Son iki mesaj ise ayn lde karktr.
Konunun zeti u: Programnz bir sz dizimi hatas ierdiinde, derleyicinin mesajlarn
her zaman olduu gibi deerlendirmeyin. Bu mesajlar sizi yanltabilir. Problemi saptamak iin
bir hata mesajn "ikinci kere tahmin etmeniz" gerekebilir. Ayrca, hata olduu rapor edilen
satrn hemen ncesinde yer alan son birka kod satrna da bakn. Kimi zaman bir hata
gerekten meydana geldii noktadan birka satr sonrasnda rapor edilebilir.
Kk Bir Deiiklik
Bu kitaptaki programlarn tmnde kullanlyor olsa da ilk programn banda yer alan
using System;
ifadesi teknik olarak gerekli deildir. Ancak, bu ifade ayn zamanda deerli bir
kolaylktr. Bunun gerekli olmamasnn nedeni, C#ta her zaman bir ismi ait olduu isim uzay
ile tam olarak niteleyebiliyor olmanzdr. rnein, u satr
Console.WriteLine(Basit bir C# programi.);
u ekilde yeniden yazlabilir:
System.Console.WriteLine(Bait bir C# programi.);
Yani, ilk rnek aada gsterildii gibi yeniden kodlanabilir:
//Bu versiyon, using System ifadesini iermiyor
class Example{
// Bir C# programi Main()'e cagrida bulunarak baslar.
public static void Main(){
// Burada, Console.WriteLine tam olarak niteleniyor
System.Console.WriteLine(Basit bir C# programi.);
}
}

System isim uzayna ait bir ye kullanldnda, her seferinde System isim uzayn
belirtmek okluka bezdirici olduu iin, C# programclarnn birou, bu kitaptaki
programlarn tmnde olduu gibi programlarnn en bana using System ifadesini dhil
ederler. Yine de, bir ismi, gerekli olduunda isim uzay ile aka niteleyebileceinizi
kavramak nemlidir.
BLM 2: C#A GENEL BR BAKI

HERKES N C#
35
kinci Basit Program
Bir programlama dilinde belki de hibir zellik, bir deikene deer atama ilemi kadar
nemli deildir. Deiken, bir deer atanabilen ve ismi olan bellek alandr. stelik, bir
deikenin deeri programn almas esnasnda deitirilebilir. Yani, deikenin ierii sabit
deildir, deitirilebilir.
Aadaki program, x ve y adnda iki deiken tanmlyor.
//Bu program degiskenleri tanitiyor.

using System;

class Example2 {
public static void Main(){
int x; //bu, bir degisken deklare ediyor
int y; //bu, baska bir degisken deklare ediyor

x = 100; //bu, xe 100 degerini atiyor

Console.WriteLine("x contains " + x) ;

y = x / 2;

Console.Write("y contains x / 2: ");
Console.WriteLine(y);
}
}

Bu program altrdnzda, aadaki kty ekranda greceksiniz:

x contains 100
y contains x / 2 : 50

Bu program birka yeni kavram tantyor. ncelikle,
int x; //bu, bir deisken deklare ediyor
ifadesi tamsay tipinde x adnda bir deikeni deklare ediyor. C#ta tm deikenler
kullanlmadan nce deklare edilmelidir. stelik, deikenin tutabilecei deerlerin cinsi de
ayrca belirtilmelidir. Buna deikenin tipi denir. Bu rnekte x, tamsay deerleri tutabilir.
C#ta bir deikeni tamsay tipinde deklare etmek iin isminin nne int anahtar kelimesini
yerletirin. Bylece, nceki ifadede int tipinde x adnda bir deiken deklare ediliyor.
Bir sonraki satrda, y adnda bir deiken deklare edilmektedir.
int y; //bu, baska bir degisken deklare ediyor
Dikkat ederseniz bu, bir ncekiyle ayn biimi kullanyor; yalnzca, deiken isimleri
farkllk gsteriyor.

HERKES N C#
KISIM I C# DL

36
Genel olarak, bir deiken deklare etmek iin u tr bir ifade kullanacaksnz:
tip deiken-ismi;
Burada, tip deklare edilen deikenin tipini, deiken-ismi ise deikenin ismini
belirtiyor. inte ek olarak C# baz baka veri tiplerini de destekler, Aadaki kod satr xe
100 deerini atyor:
x = 100; //bu, xe 100 deerini atiyor
C#ta deer atama operatr tek eittir iaretidir. Atama operatr, sa tarafndaki deeri
sol tarafndaki deikene kopyalar.
Bir sonraki kod satr, nce "x contains" karakter katarn, bunun peinden de xin
deerini ekranda gsterir.
console.WriteLine("x contains " + x);
Bu ifadedeki art iareti xin deerinin, xin nnde yer alan karakter katarndan sonra
ekranda gsterilmesine neden olur. Bu yaklam genelletirilebilir. + operatrn kullanarak
tek WriteLine() ifadesi iinde istediiniz kadar ok sayda eyi ekranda pe pee
gsterebilirsiniz.
Bir sonraki kod satrnda, xin 2'ye blnm deeri yye atanyor:
y = x / 2;
Bu satr xdeki deeri 2ye bler, sonucu yde saklar. Bylece, bu satr altrldktan
sonra y, 50 deerini ierecektir. xin deeri ise deimeyecektir. Dier bilgisayar dillerinin
pek ounda olduu gibi C# da aada gsterilenlerin yan sra aritmetik operatrlerinin
tmn desteklemektedir:
+ Toplama
- kartma
* arpma
/ Blme
Programn dier iki satr u ekildedir:
Console.Write(y contains x / 2: ");
Console.WriteLine(y);
Burada iki yeni durum sz konusudur. ncelikle, "y contains x / 2: " karakter
katarn gstermek iin standart Write() metodu kullanlyor. Bu karakter katarnn peinden
yeni bir satr gelmiyor. Bunun anlam udur: Bir sonraki kt retildiinde bu kt ekranda
ayn satrdan balayacaktr. Write() metodu tpk WriteLine() gibidir; yalnzca, Write()
metodu, her ardan sonra yeni bir satrdan balamaz. kincisi, WriteLine() arsnda
ynin kendisinin kullanldna dikkat edin. C#ta tanml herhangi bir standart tipteki
deerlerin ktsn almak iin hem Write() hem de WriteLine() kullanlabilir.
BLM 2: C#A GENEL BR BAKI

HERKES N C#
37
Bir baka konuya gemeden nce deikenleri deklare etmekle ilgili bir hususa daha
deinelim: Ayn deklarasyon ifadesini kullanarak bir veya daha fazla deikeni deklare
etmeniz mmkndr. Sadece deiken isimlerini virgl ile ayrmanz yeterlidir. rnein, x ve
y u ekilde de deklare edilebilirdi:

int x, y; //tek bir ifade ile ikisi de deklare ediliyor
Baka Bir Veri Tipi
nceki programda int tipinde bir deiken kullanlmt. Ancak, int tipinde bir
deiken yalnzca tamsaylar tutabilir. Yani, ondalk ksm gerekli olduunda int
kullanlamaz. rnein, bir int deikeni 18 deerini tutabilir, fakat 18.3 deerini tutamaz.
Neyse ki int, C#ta tanml olan birka veri tipinden yalnzca biridir. Ondalk ksm olan
saylara da imkn vermek amacyla C#ta iki kayan noktal tip tanmlanyor: float ve
double. Bunlar srasyla tek ve ift duyarlkl saylar simgelerler. Bu ikisinden double,
genellikle daha yaygn olarak kullanlr,
double tipinde bir deikeni deklare etmek iin aadakine benzer bir ifade kullann:
double result;
Burada result, double tipindeki deikenin ismidir, result deikeni kayan noktal
bir tipte olduu iin 122.23, 0.034 veya -19.0 gibi deerleri tutabilir.
int ve double arasndaki fark daha iyi anlamak iin aadaki program deneyin:
/*
Bu program, int ve double arasindaki
farki ortaya koyar.
*/

using System;

class Example3 {
public static void Main() {
int ivar; // bu
s
bir int degisken deklare eder
double dvar; //bu, kayan noktal bir degisken deklare eder

ivar = 100; // ivar'a 100 degerini atar

dvar = 100,0; // dvar'a 100.0 degerini atar

Console.WriteLine("Original value of ivar: " + ivar);
Console.WrteLine("Original value of dvar: " + dvar);

Console.WriteLine(); // bos bir satir basar

// simdi, her ikisini de 3e bol
ivar = ivar / 3;
dvar = dvar / 3.0;

HERKES N C#
KISIM I C# DL

38

Console.WriteLine(ivar after division: + ivar);
Console.WriteLine(dvar after division: + dvar);
}
}
Bu programn kts aada gsterilmitir:
Original value of ivar: 100
Original value of dvar: 100

ivar after division: 33
dvar after division: 33.3333333333333
Grdnz gibi, ivar 3 ile blndnde tamsay blme ilemi gerekletiriliyor ve
sonu 33 oluyor - ondalk ksm anlyor. Ancak, dvar 3 ile blndnde ondalk ksm
korunuyor.
Programda gsterildii gibi, bir programda kayan noktal bir deer belirtmek istiyorsanz
ondalk noktay dhil etmelisiniz. Eer dhil etmezseniz, sz konusu deer tamsay olarak
yorumlanacaktr. rnein, C#ta 100 deeri bir tamsaydr; fakat 100.0 ise kayan noktal bir
deerdir.
Programda dikkat edilecek bir baka yeni durum daha var. Bo bir satr yazmak iin
WriteLine() argmansz olarak armanz yeterlidir.
Kayan noktal veri tipleri genellikle, ondalk bileenlerin sk sk gerekli olduu gerek
dnyaya ait niceliklerle alrken kullanlr. rnein, aadaki program dairenin alann
hesaplyor. Program pi iin 3.1416 deerini kullanyor.
// Bir dairenin alanini hesaplar.
using System;
class Circle {
static void Main() {
double radius;
double area;
radius = 10.0;
area = radius * radius * 3,1416;
Console.WriteLine("Area is " + area);
}
}

Bu programn kts yledir:
Area is 314.16
phesiz, dairenin alan kayan noktal veriler kullanlmadan tam olarak hesaplanamazd.
BLM 2: C#A GENEL BR BAKI

HERKES N C#
39
ki Kontrol fadesi
Bir metodun iinde kontrol, yukardan aaya doru bir ifadeden dierine geerek ilerler.
Ancak, bu ak C# tarafndan desteklenen eitli program kontrol ifadeleri kullanarak
deitirmek de mmkndr. Kontrol ifadelerine daha sonra yakndan gz atacak olmamza
ramen, iki tanesini burada ksaca tantacaz, nk rnek programlar yazmak iin bunlar
kullanacaz.
if fadesi
C#n koul ifadesini kullanarak programn bir parasn seerek altrabilirsiniz. Bu
koul ifadesi if'dir. C#'taki if ifadesi dier dillerdeki if ifadesine ok benzer ekilde alr.
rnein, C#taki if ifadesi C, C++ ve Java'daki if ifadeleriyle ayn sz dizimine sahiptir. Bu
ifade en basit ekliyle yledir:
if(koul) ifade;
Burada, koul bir Boolean (yani, true (doru) veya false (yanl)) deyimdir. Eer
koul doruysa, ifade gereklenir, koul yanl ise ifade atlanr. te bir rnek;
if (10 < 11) Console.WriteLine("10 is less than 11");
Bu rnekte 10, 11den kk olduu iin koul deyimi doru olur ve WriteLine()
gereklenir. Ancak, bir de aadakine bakn:
if (10 < 9) Console.WriteLine(this won't be displayed");
Bu durumda 10, 9dan kk deildir. Yani, WriteLine() ars gereklenmeyecektir.
C#, koul deyimlerinde kullanlan ilikisel operatrlerin tam kadro tanmn ierir. Bunlar
aada gsterilmitir:
Operatr Anlam
< Kktr
<= Kktr veya eittir
> Byktr
>= Byktr veya eittir
== Eittir
!= Eit deildir
Aada, if ifadesini gsteren bir program rnei bulunuyor:
// if'i tanitir.
using System;
class IfDemo {
public static void Main() {

HERKES N C#
KISIM I C# DL

40
int a, b, c;
a = 2;
b = 3;
if(a < b) Console.WriteLine("a is less than b");
// bu, ekranda hicbir sey gstermez
if(a == b) Console.WriteLine("you won't see this"};
Console.WriteLine();

c = a - b; // c, -1 degerini icerir

Console.WriteLine(c contains 1);
if(c >= 0) Console.WriteLine(c is non-negative");
if(c < 0) Console.WriteLine("c is negative");

Console.WriteLine();

c = b - a; // c simdi 1 degerini icerir
Console.WriteLine("c contains 1");
if(c >= 0) Console.WriteLine( "c is non-negative");
if(c < 0) Console.WriteLine("c is negative");

}
}
Bu programn kts aadaki gibidir;
a is less than b

c contains -1
c is negative

c contains 1
c is non-negative

Bu programdaki bir baka noktaya dikkat edin. Aadaki satr, virgl ile ayrlm bir liste
kullanarak a, b ve c isimli deiken deklare eder:
int a, b, c;
nceden bahsedildii gibi, ayn tipte iki veya daha fazla deikene ihtiyacnz varsa bu
deikenler tek bir ifade ile deklare edilebilir. Tek yapmanz gereken, deiken isimlerini
virgl ile ayrmaktr.
for Dngs
Kod paralarn bir dng oluturarak tekrar tekrar altrabilirsiniz, C#, ok eitli
dng ifadelerinden oluan gl dng zelliklerine sahiptir. Burada for dngsn ele
atacaz. C, C++ veya Java'ya ainaysanz, C#taki for dngsnn bu dillerdekiyle ayn
ekilde altn renmek sizi mutlu edecektir, for dngsnn en basit ekli aada
gsterilmitir:
BLM 2: C#A GENEL BR BAKI

HERKES N C#
41
for (balang; koul; iterasyon) ifade;
En yaygn ekliyle dngnn balang blm, dng kontrol deikenine ilk deer
atar. koul, dng kontrol deikenini test eden bir Boolean deyimdir. Bu testin sonucu
doruysa for dngs iterasyona devam eder. Testin sonucu yanlsa dng sona erer.
iterasyon deyimi, dngnn her iterasyonunda dng kontrol deikeninin ne ekilde
deieceini belirler. te, for dngsn gz nnde canlandran ksa bir program:
// for dongusunu tanitir.

using System;

class ForDemo {
public static void Main() {
int count;

for (count = 0; count < 5; count = count + 1)
Console.WriteLine("This is count: * + count);

Console.WriteLine("Done!");
}
}

Programn kts aada gsterilmitir:
This is count: 0
This is count: 1
This is count: 2
This is count: 3
This is count: 4
Done!

Bu rnekte count, dng kontrol deikenidir, count, for dngsnn ilk deer
atamas blmnde 0 deerini alr. Her iterasyonun banda (ilk iterasyon da dhil olmak
zere) count < 5 koul testi gerekletirilir. Bu testin sonucu doruysa, WriteLine()
ifadesi gereklenir, sonra da dngnn iterasyon blm altrlr. Bu ilemler koul testi
yanl olana kadar srer. Koul testi yanl olduunda kontrol, dngnn sonuna geer.
lgin olan udur: Profesyonel olarak yazlm C# programlarnda, nceki rnekte
gsterildii gibi dngnn iterasyon blmne hemen hemen hi rastlamazsnz. Yani, u tr
ifadelerle nadiren karlarsnz:
count = count + 1;
Bunun nedeni, C#ta bu ilemi daha verimli biimde gerekletiren zel bir artrma
operatrnn mevcut olmasdr. Artrma operatr ++dr (yani, pe pee art iaretleri).
Artrma operatr, operandn bir artrr. Artrma operatrn kullanarak nceki ifade u
ekilde yazlabilir:
count++;

HERKES N C#
KISIM I C# DL

42
Bylece, nceki programdaki for dngs genellikle yle yazlr:
for (count = 0; count < 5; count++)
Bunu denemek isleyebilirsiniz. Dngnn ncekiyle tamamen ayn ekilde altn
greceksiniz.
C#ta ayrca, - - olarak belirtilen eksiltme operatr de bulunur. Bu operatr, operandn
bir azaltr.
Kod Bloklarn Kullanmak
C#'n bir baka temel esi kod bloudur. Bir kod blou iki veya daha fazla ifadenin
gruplanmasdr. Bu, ifadeleri al ve kapan kme parantezleri iine alarak gerekletirilir.
Kod blounun hazrlanmasyla, sz konusu kod blou arlk tek bir ifadenin kullanlabilecei
her yerde kullanlabilecek olan mantksal bir birim halini alr. rnein, bir blok if ve for
ifadeleri iin hedef olabilir. u if ifadesine bir gz atn:
if (w < h) {
v = w * h;
w = 0;
}

Burada w, hden kkse bloun iindeki her iki ifade de gereklenecektir. Bylece,
bloun iindeki iki ifade mantksal bir birim olutururlar; bir ifade ancak dieri de
gereklendiinde gereklenebilir. Buradaki temel konu, iki veya daha fazla ifadeyi ne zaman
birbirine balamanz gerekse, bunu bir blok oluturarak yapabilecek olmanzdr. Kod bloklar
algoritmalarn birounun daha net ve verimli uygulanmasna imkn verir.
imdi, sfra blmeyi nleyen bir kod blou kullanan bir programa gz atalm:
// Bir kod blogunu gosterir.

using System;

class BlockDemo {
public static void Main() {
int i, j, d;

i = 5;
j = 10;

// bu ifin hedefi bir kod blogudur.
if (i != 0) {
Console.WriteLine("i does not equal zero");
d = j / i;
Console.WriteLine( j / i is + d);
}
}
}
BLM 2: C#A GENEL BR BAKI

HERKES N C#
43
Bu programn kts u ekildedir:
i does not equal to zero
j / i is 2
Bu rnekte if ifadesinin hedefi tek bir ifade deil, bir kod bloudur, ifi kontrol eden
koul doruysa (bu rnekle olduu gibi), bloun iindeki ifade gereklenecektir. i
deikenine sfr deerini vermeye aln ve sonucu gzleyin.
te bir baka rnek. Bu kez, 1den 10a kadar saylarn toplamlarn ve arpmlarn
hesaplamak iin kod blou kullanlyor.
// 1den 10a kadar sayilarin toplam ve carpimlarini hesaplar.

using System;

class ProdSum {
static void Main() {
int prod;
int sum;
int i;

sum = 0;
prod = 1;

for (i = 1; i <= 10; i++) {
sum = sum + i;
prod = prod * i;
}
Console.WriteLine(Sum is + sum);
Console.WriteLine(Product is + prod);
}
}

kt aadadr:
Sum is 55
Product is 3628800
Burada kod blou sayesinde, toplam ve arpmn her ikisinin tek bir dng iinde
hesaplanmas mmkn oluyor. Blok kullanlmasayd iki ayr for dngs gerekecekti.
Son bir husus: Kod bloklar programn almasyla ilgili verimsizlie neden olmazlar.
Baka bir deyile, { ve } programn almas srasnda ekstra zaman harcamaz. Aslnda,
belirli algoritmalar sadeletirme becerilerinden tr, kod bloklarnn kullanm genellikle
hz ve verimlilii artrr.
Noktal Virgller ve Konumlandrma
C#ta noktal virgl, ifadenin sonunu gsterir. Yani, tek bana ifadelerin her biri, noktal
virgl ile sona ermelidir.

HERKES N C#
KISIM I C# DL

44
Bildiiniz gibi bir blok, al ve kapan kme parantezleri ile evrelenmi mantksal
olarak birbirine bal bir takm ifadelerden oluur. Blok noktal virgl ile sona ermez. Blok,
her biri noktal virgl ile sona eren bir grup ifadeden olutuu iin bloun noktal virgl ile
bitmemesi mantkldr. Noktal virgl yerine kapan kme parantezi bloun sonuna iaret
eder.
C# satrn sonunu ifadenin sonu olarak alglamaz - sadece noktal virgl ifadeyi
sonlandrr. Bu nedenle, ifadeyi satr zerinde nereye yerletirdiiniz nemli deildir.
rnein. C#ta u,
x = y;
y = y + 1;
Console.WriteLine(x + " " + y) ;
aadaki ile ayndr:
x = y; y = y + 1; Console.WriteLine(x + " " + y);
stelik, bir ifadeyi oluturan elemanlar da tek tek ayr satrlara yerletirebilirsiniz.
rnein, aadaki tamamen kabul edilebilir:
Console.WriteLine("This is a long line of output" +
x + y + z +
more output);
Uzun satrlar bu ekilde blmek, genellikle programlan daha okunakl klar. Ayrca ar
uzun satrlarn bir sonraki satra tamasn da nlemeye yardmc alabilir.
Girintileme Altrmalar
nceki rneklerde, belirli ifadelerin girintili olduuna dikkat etmisinizdir. C# serbest
formlu bir dildir. Yani, ifadeleri satr zerinde birbirine kyasla nereye yerletirdiiniz nemli
deildir. Ancak, yllar getike, ok okunakl programlara imkn veren ortak ve onaylanm
bir girintileme stili gelimitir. Bu kitaptaki rnekler bu stili izliyorlar; sizin de bu ekilde
yapmanz tavsiye edilir. Bu stili kullanarak, her al kme parantezinden sonra girintiyi bir
seviye artrrsnz ve her kapan kme parantezinden sonra da bir seviye azaltrsnz. Kimi
ifadeler ilave baz girintileri de tevik eder; bunlar daha sonra ele alnacaktr.

TABLO 2.1: C# Anahtar Kelimeleri
abstract as base bool break
byte case catch char checked
class const continue decimal default
delegate do double else enum
event explicit extern false finally
BLM 2: C#A GENEL BR BAKI

HERKES N C#
45
fixed float for foreach goto
if implicit in int interface
internal is lock long namespace
new null object operator out
override params private protected public
readonly ref return sbyte sealed
short sizeof stackalloc static string
struct switch this throw true
try typeof unit ulong unchecked
unsafe ushort using virtual volatile
void while

C# Anahtar Kelimeleri
C# dilinde tanml halihazrda 77 anahtar kelime mevcuttur (Tablo 2.1 'e bakn). Bu
anahtar kelimeler, operatr ve separatr szdizimleriyle birletirilerek C# dilinin tanmn
olutururlar. Bu anahtar kelimeler deiken, snf ve metot ismi olarak kullanlamazlar.
Tanmlayclar
C#ta bir tanmlayc (identifier), bir metoda, deikene veya kullanc tarafndan
tanmlanan herhangi baka bir eye atanan isimdir. Tanmlayclar bir karakterden birka
karaktere kadar deien uzunluklarda olabilir. Deiken isimleri alfabenin herhangi bir harfi
ile veya alt izgi (_) ile balayabilir. Sonra harf, rakam veya alt izgi ile devam edebilir. Alt
izgi, deiken isminin okunaklln artrmak iin kullanlabilir; line_count rneinde
olduu gibi. Byk ve kk harfler farkldr; yani, C#ta myvar ve MyVar ayr isimlerdir.
Kabul edilebilir tanmlayclar iin u rnekler verilebilir:
Test x y2 MaxLoad
up _top my_var sample23
Bir tanmlaycnn rakam ile balamayacan hatrnzdan karmayn. Yani, rnein 12x
geerli deildir. simlendirilen enin anlamn ya da kullanmn yanstan tanmlayc isimleri
kullanmak, iyi bir programlama alkanldr.
C# anahtar kelimelerinden hi birini tanmlayc smi olarak kullanamyor olmanza
ramen C#, bir anahtar kelimenin nnde @ kullanmanza izin vererek sz konusu anahtar
kelimenin geerli bir tanmlayc olmasn mmkn klar. rnein, @for geerli bir
tanmlaycdr. Bu rnekte, tanmlayc aslnda fordur; @ dikkate alnmaz. te, @
tanmlaycsnn kullanmn gz nnde canlandran bir program:
// @ tanimlayicisini gostermektedir.
using System;


HERKES N C#
KISIM I C# DL

46
class IdTest {
static void Main() {
int @if; // ifi tanimlayici olarak kullan

for (@if = 0; @if < 10; @if++)
Console.WriteLine(@if is " + @if);
}
}

Burada gsterilen kt, @ifin gerekten de bir tanmlayc olarak yorumlandn
kantlamaktadr:
@if is 0
@if is 1
@if is 2
@if is 3
@if is 4
@if is 5
@if is 6
@if is 7
@if is 8
@if is 9

Drst olmak gerekirse, zel amalar hari tanmlayclar in @ 1le nitelenen anahtar
kelimeler kullanmak tavsiye edilmez. Ayrca, @ herhangi bir tanmlaycnn nnde de
kullanlabilir, fakat bu kt bir programlama alkanl olarak dikkate alnr.

C# Snf Ktphaneleri
Bu blmde gsterilen rnek programlar C#n standart metotlarnn ikisinden
yararlanyor: WriteLine() ve Write(). nceden bahsedildii gibi, bu metotlar System
isim uzaynn bir paras olan Console snfnn yeleridir. System isim uzay ise .NET
Frameworkn snf ktphaneleri ile tanmlanr. Bu blmde daha nceden akland gibi
C# ortam; I/O, karakter katarlarnn ele alnmas, a uygulamalar ve GUI gibi ilemler iin
destek salamak amacyla, .NET Framework snf ktphanelerine dayanmaktadr. Yani, C#
btn olarak C# dilinin kendisinin ve .NET standart snflarnn birleiminden olumaktadr.
Daha sonra greceiniz zere, herhangi bir C# programnn paras olan ilevselliin byk
blmn snf ktphaneleri salar. Gerekten, C# programcs olmann bir paras da bu
snf ktphanelerini kullanmay renmektir. Ksm I boyunca .NET snf ktphanelerinin
ve metotlarnn eitli elemanlar ele alnyor. Ksm IIde .NET ktphanesi daha ayrntl
inceleniyor.





N C B L M



VER TPLER,
LTERALLER VE
DEKENLER
























3

HERKES N C#
KISIM I C# DL

48
Bu blmde C#n temel esi inceleniyor: Veri tipleri, literaller ve deikenler. Genel
olarak, bir dilin sunduu veri tipleri, bu veri tiplerinin uygulanabilecei problem snflarn
tanmlar, Tahmin edebileceiniz gibi, C# zengin bir standart veri tipleri kmesi ierir. Bu, C#
ok eitli uygulamalar iin uygun klar. Bu tiplerin herhangi birinden deikenler
oluturabilirsiniz. Her tipten sabit de belirtebilirsiniz. C# dilinde bu sabitler literal olarak
adlandrlr.
Veri Tipleri Neden nemlidir?
Veri tipleri C#ta zellikle nemlidir, nk C# sk skya tipe dayal bir dildir. Bu, tip
uyumu iin tm ilemlerin derleyici tarafndan tip kontrolnden geirilecei anlamna gelir.
Kural d lemler derlenmeyecektir. Bylece, sk tip kontrol, hatalar nlemeye yardmc
olur ve gvenilirlii artrr. Sk tip kontroln mmkn klmak iin tm deikenler, deyimler
ve deerler bir tipe sahiptir. Tipsiz bir deiken eklinde bir kavram sz konusu deildir
rnein. stelik bir deerin tipi, bu deer zerinde hangi ilemlere izin verildiini belirler. Bir
tip zerinde izin verilen ilemlere bir baka tip zerinde izin verilmeyebilir.
C#'n Deer Tipleri
C#n ierdii yerleik veri tipleri iki genel kategoride toplanr: deer tipleri ve referans
tipleri. C#n referans tipleri snflarla tanmlanr; snflarla ilgili tartma ise daha sonra ele
alnacaktr, Ancak, C#n znde 13 deer tipi yer alr. Bunlar Tablo 3.1de gsterilmitir. Bu
deer tipleri, C# dilinin anahtar kelimeleri tarafndan tanmlanan yerleik tiplerdir ve herhangi
bir C# program tarafndan kullanlmak zere hazrdr.
Deer tipi terimi, bu tipteki deikenlerin, deerlerini dorudan ierdiklerini belirtir. (Bu;
deikenin, gerek deere bir referans ierdii referans tiplerinden farkldr.) Bylece, deer
tipleri dier programlama dillerinde, mesela C++ta, bulunan veri tiplerine ok benzer ekilde
davranrlar. Deer tipleri ayrca basit tipler olarak da bilinir.
C#, her deer tipi iin deimez bir deer aral ve davran biimi belirler. Tanabilirlik
gereksinimlerinden dolay C# bu konuda taviz vermez. rnein, int tm alma ortamlarnda
ayndr. Kodu, belirli bir platforma uydurmak iin yeniden yazmaya gerek yoktur. Deer
tiplerinin bykln deimez biimde belirlemek, kk bir performans kaybna neden
olabilirken, tanabilirlii mmkn klmak iin gereklidir.
TABLO 3.1: C# Deer Tipleri


Tip Anlam
bool
true/false deerlerini simgeler
byte
8 bit iaretsiz tamsay
char
Karakter
decimal
Mali hesaplamalar iin nmerik tip
BLM 3: VER TPLER, LTERALLER VE DEKENLER

HERKES N C#
49
double
ift duyarlkl kayan noktal say
float
Tek duyarlkl kayan noktal say
int
Tamsay
long
Uzun tamsay
sbyte
8 bit iaretli tamsay
short
Ksa tamsay
uint aretsiz tamsay

ulong
aretsiz uzun tamsay
ushort
aretsiz ksa tamsay


Tamsaylar
C#'ta dokuz tamsay tipi tanmldr: char, byte, sbyte, short, ushort, int, uint,
long ve ulong. Ancak, char tipi zellikle karakterleri simgelemek iin kullanlr ve bu
blmde daha sonra ele alnacaktr. Geriye kalan sekiz tamsay tipi nmerik hesaplamalar iin
kullanlr. Bunlarn bit genilii ve deer aralklar aada gsterilmitir:
Tip Bit Olarak Deer Aral
Genilik
byte 8 0dan 255e
sbyte 8 -128den 127ye
short 16 -32,768den 32,767ye
ushort 16 0dan 65,535e
int 32 -2,147,483,648'den 2,147,483,647ye
uint 32 0dan 4,294,967,295e
long 64 -9,223,372,036,854,775,808den
9,223,372,036,854,775,807'ye
ulong 64 0dan 18,446,744,073,709,551,615'e
Tablodan grld gibi, C#'ta eitli tamsay tiplerinin hem iaretli hem de iaretsiz versi-
yonlar tanmldr. aretli ve iaretsiz tamsaylar arasndaki fark, tamsaynn st bitinin (high-
order) yorumlanma ekline baldr. Bir iaretli tamsay belirtildiinde C# derleyicisi,
tamsaynn st bitinin iaret bayra (sign flag) olarak kullanlacan varsayan bir kod retir.
Eer iaret bayra 0 ise say pozitiftir; eer 1 ise, say negatiftir. Negatif saylar hemen hemen
her zaman ikinin tmleyeni (two's complement) yntemi kullanlarak simgelenirler. Bu
yntemde, saynn tm bitleri (iaret bayra hari) ters evrilir ve sayya 1 eklenir. Son olarak,
iaret bayra 1 olarak ayarlanr.
aretli tamsaylar pek ok sayda algoritma iin nemlidir ama, iaretsiz akrabalarnn
mutlak byklnn sadece yansna sahiptirler. rnein, short olarak 32.767 u ekildedir:
01111111 11111111

HERKES N C#
KISIM I C# DL

50
aretli bir deer iin eer st bit 1 olarak ayarlanrsa, say -1 olarak yorumlanacaktr
(ikinin tmleyeni ynteminin kullanldn varsayyoruz). Ancak, eer bu say ushort
olarak deklare edilmemise, st bit'i 1 olarak ayarlandnda say 65.535 olur.
Muhtemelen en yaygn olarak kullanlan tamsay tipi inttir. int tipinde deikenler
genellikle dngleri kontrol etmek iin, dizi indekslerinde ve genel amal tamsay
matematiinde kullanlr. intten daha geni deer aralna sahip bir tamsayya ihtiyacnz
olduunda, birok seeneiniz vardr. Eer saklamak istediiniz deer iaretsiz ise, uinti
kullanabilirsiniz. Byk, iaretli saylar iin long'u kullann. Byk, iaretsiz saylar iin
ulong'u kullann. rnein ite size dnyadan gnee olan uzakl in cinsinden hesaplayan
bir program. Bu deer ok byk olduu iin program, bu deeri tutmak amacyla long tipinde
bir deiken kullanyor.
// Dunyadan gunese inc cinsinden uzakligi hesaplar.

using System;

class Inches {
public static void Main(){
long inches;
long miles;

miles = 93000000; // Gunes 93,000,000 mil uzakliktadir

// Bir mil 5,280 ayaktir, bir ayak 12 inctir,
inches = miles * 5280 * 12;

Console.WriteLine(Distance to the sun: + inches +
inches.);
}
}
Programn kts ite yledir;
Distance to the sun: 5892480000000 inches.
Aka grlyor ki, sonu bir int veya uint deikeninde saklanamazd.
En kk tamsay tipleri byte ve sbytetr. byte tipi, 0 ile 255 arasnda iaretsiz bir
deerdir. byte tipinde deikenler zellikle ham ikili verilerle (raw binary data) alrken,
rnein bir aygt tarafndan retilen bytestream halindeki veri kullanlrken, yararl olur.
Kk, iaretli tamsaylar iin sbyte kulann. Aada rnek bir program yer alyor. Bu rnek
programda 100e kadar olan tamsaylarn toplamn hesaplayan bir for dngsn kontrol
etmek iin byte tipinde bir deiken kullanlyor.
// byte kullan.
using System;

class Use_byte {
public static void Main() {
BLM 3: VER TPLER, LTERALLER VE DEKENLER

HERKES N C#
51
byte x;
int sum;

sum = 0;
for (x = 1; x <= 100; x++)
sum = sum + x;

Console.WriteLine("Summation of 100 is " + sum);
}
}
Programn kts aadaki gibidir:





















HERKES N C#
KISIM I C# DL

52







// Math.Sin(), Math.Cos() ve Math.Tan()i tanitir.

using System;

class Trigonometry {
public static void Main() {
Double theta; // aci radyan cinsinden.

for (theta = 0.1; theta <= 1.0; theta = theta + 0.1) {
Console.WriteLine("Sine of " + theta + " is +
Math.Sin(theta));
Console.WriteLine("Cosine of " + theta + is " +
Math.Cos(theta));
Console.WriteLine("Tangent of " + theta + " is " +
Math.Tan (theta));
Console.WriteLine ();
}
}
}
Program ktsnn bir ksm u ekildedir:
Sine of 0.1 is 0.0998334166468282
Cosine of 0.1 is 0.995004165278026
Tangent of 0.1 is 0.100334672085451

Sine of 0.2 is 0.198669330795061
Cosine of 0.2 is 0.980066577841242
Tangent of 0.2 is 0.202710035508673

Sine of 0.3 is 0.29552020666134
Cosine of 0.3 is 0.955336489125606
Tangent of 0.3 is 0.309336249609623
Sins, kosins ve tanjant hesaplamak iin standart ktphane metotlar olan Math.Sin(),
Math.Cos() ve Math.Tan() kullanlmaktadr. Tpk Math.Sqrt() gibi, trigonometrik
metotlar da bir double argman ile arlr ve double bir sonu dndrrler. Alar radyan
olarak belirtilmelidir.
BLM 3: VER TPLER, LTERALLER VE DEKENLER

HERKES N C#
53
decimal Tipi
C# nmerik tiplerinin belki de en ilginci, parasal hesaplamalarda kullanlmas planlanan
decimal tipidir, decimal tipi, 1E-28 ile 7.9E+28 arasndaki deerleri simgelemek iin 128
bit kullanr. Bildiiniz gibi, kayan noktal normal aritmetik, ondalk saylara uygulandnda
eitli yuvarlama hatalarna maruz kalr. decimal tipi bu hatalar ortadan kaldrr ve saylar
28 ondalk basamaa kadar (baz durumlarda 29 basamaa kadar) hatasz simgeleyebilir.
Ondalk saylar yuvarlama hatalar olmadan temsil etme becerisi, bu tipi, zellikle bellek
gerektiren hesaplamalarda kullanl klar.
te size, decimal tipini mali hesaplamada kullanan bir program. Program, orijinal fiyat
ve indirim yzdesi verildiinde indirimli fiyat hesaplyor.
//Bir fiyat indirimini hesaplamak iin decimal tipini kullanmak.

using System;

class UseDecimal {
public static void Main() {
decimal price;
decimal discount;
decimal discounted_price;

// indirilmis fiyati hesapla
price = 19.95m;
discount = 0.15m; // indirim orani: %15

discounted_price = price - (price * discount);

Console.WriteLine("Discounted price: $" + discounted_price);
}
}
Bu programn kts aada gsterilmitir:
Discounted price: $16.9575
Programda, ondalk sabitlerin m soneki ile bitliine dikkat edin. Bu gereklidir, nk m so-
neki olmadan bu deerler, decimal veri tipi ile uyumlu olmayan standart kayan noktal
sabitler olarak yorumlanr. Her eye ramen, bir decimal deikene m sonekini kullanmadan,
mesela 10 gibi bir tamsay deer atayabilirsiniz. (Nmerik sabitlerin ne ekilde belirtildiine bu
blm iinde daha yakndan gz atacaz.)
Aada, decimal tipini kullanan bir baka rnek grlyor. Bu rnekle, bir yatrmn
sabit faiz oran zerinden birka yl sonundaki deeri hesaplanyor.
/*
Bir yatirimin gelecekteki degerini hesaplamak icin decimal
tipini kullanmak.
*/

HERKES N C#
KISIM I C# DL

54

using System;

class FutVal {
public static void Main() {
decimal amount;
decimal rate_of_return;
int years, i;

amount = 1000.0m;
rate_of_return = 0.07m;
years = 10;

Console.WriteLine("Original investment: $" + amount);
Console.WriteLine("Rate of return: " + rate_of_return);
Console.WriteLine("Over " + years + " years);

for (i = 0; i < years; i++)
amount = amount + (amount * rate_of_return);
Console.WriteLine("Future value is $ + amount);
}
}
te programn kts:
Original investment: $1000
Rate of return; 0.07
Over 10 years
Future value is $1967.15135728956532249
Sonucun birka ondalk basamaa - bu, muhtemelen arzu edeceinizden daha da fazladr! -
kadar hatasz olduuna dikkat edin. Bu tr bir ktnn daha ho grnecek ekilde nasl
biimlendirileceini bu blmde reneceksiniz.
Karakterler
C#'ta karakterler, dier bilgisayar dillerinde, rnein C++ta, olduu gibi 8 bitlik nicelikler
deildir. Bunun yerine C#ta, Unicode denilen 16 bit karakter tipi kullanlr. Unicode, btn in-
sani dillerde mevcut olan karakterlerin tmn simgelemeye yetecek kadar byk bir karakter
seti tanmlar. ngilizce, Franszca veya Almanca gibi birok dil nispeten kk alfabeler
kullanyor olsa da, baz diller, rnein ince, sadece 8 bit kullanlarak simgelenemeyen ok
byk karakter setleri kullanr. Tm dillerin karakter setlerine yer vermek iin 16 bit deerler
gereklidir. Bylece, C#ta char, 0dan 65.535e uzanan bir menzile (deer aralna) sahip,
iaretsiz bir 16 bit tiptir. Standart 8 bit ASCII karakter seti, Unicode'un bir alt kmesidir ve
0dan 127ye kadar uzanr. Yani, ASCII karakterleri halen geerli C# karakterleridir.
Bir karakter deikenine tek trnak iine alnan bir karakter ile deer atanabilir. rnein,
aada ch deikenine X deeri atanyor:
char ch;
ch = X;
BLM 3: VER TPLER, LTERALLER VE DEKENLER

HERKES N C#
55
Bir char deerinin ktsn bir WriteLine() ifadesini kullanarak elde edebilirsiniz.
rnein aadaki satrda, chin deeri kt olarak elde ediliyor:
Console.WriteLine("This is ch: " + ch);
char, C#ta tamsay tipi olarak tanmlanm olmasna ramen her hal ve artta
tamsaylarla serbeste kartrlarak kullanlamaz. Bu, tamsaylardan char'a otomatik tip
dnm olmamasndan kaynaklanmaktadr. rnein, aadaki program paras geerli
deildir:
char ch;
ch = 10; //hata; bu, calismaz
Yukardaki kodun almayacak olmasnn nedeni, 10un bir tamsay deer olmasdr. 10,
char'a otomatik olarak dntrlmeyecektir. Bu kodu derleme giriiminde bulunursanz, bir
hata mesaj ile karlarsnz. Bu blm iinde ileriki sayfalarda bu kstlamadan kurtulmann
yntemini reneceksiniz.
bool Tipi
bool tipi doru/yanl deerlerini simgeler. C#ta doru ve yanl deerleri true ve
false zel amal kelimeleriyle tanmlanr. Yani, bool tipinde bir deiken veya deyim bu iki
deerden birine eit olabilir. Ayrca, bool ve tamsay deerler arasnda tanml bir tip
dnm sz konusu deildir. rnein, 1 true'ya dntrlmez; 0 da false'a
dntrlmez. le, bool tipini gsteren bir program:
// bool degerleri gosterir.

using System;

class BoolDemo {
public static void Main() {
bool b;

b = false;
Console.WriteLine(b is + b);
b = true;
Console.WriteLine("b is " + b);

// bir bool degeri, if ifadesini kontrol edebilir
if(b) Console.WriteLine("This is executed,");

b = false;
if(b) Console.WriteLine("This is not executed.");

// ilikisel operatorun sonucu bir bool degerdir
Console.WriteLine("10 > 9 is + (10 > 9));
}
}
Bu programn rettii kt aada gsterilmitir:

HERKES N C#
KISIM I C# DL

56
b is False
b is True
This is executed.
10 > 9 is True
Bu programda dikkat eken ilgin nokta var. ncelikle, grdnz gibi, bir bool
deerin WriteLine() ile kts alndnda ekranda "True" veya "False" grnyor.
kincisi, if ifadesini kontrol etmek iin bool deikenin deeri kendi bana yeterlidir. u
ekilde bir if ifadesi yazmaya gerek yoktur:
if (b = = true)...
ncs, bir ilikisel operatrn, rnein < operatrnn kts bir bool deerdir. 10
> 9 deyiminin ekranda "True" deerini gstermesi bu sebeptendir. Ayrca, 10 > 9 deyiminin
etrafndaki ekstra parantez ifti gereklidir, nk + operatr, > operatrnden daha yksek
ncelie sahiptir.
Baz kt Seenekleri
u ana kadar, WriteLine() ifadesi kullanlarak verilerin kts alndnda kt, C#
tarafndan salanan varsaylan biim kullanlarak grntleniyordu. Ancak, C# verinin nasl
gsterilecei konusunda size ayrntl kontrol olanaklar sunan gelikin bir biimlendirme
mekanizmasna sahiptir. Biimlendirilmi I/O (formatted I/O) bu kitapta daha sonra ele
alnacak olmasna ramen, u aamada baz biimlendirme seeneklerini tantmak yararl
olacaktr. Bu seenekleri kullanarak deerlerin WriteLine() ifadesi zerinden ktlar
alndnda ne ekilde grneceklerini belirleyebilirsiniz. Bu, ok daha ho kt retmenizi
mmkn klar. C# biimlendirme mekanizmasnn burada anlatlan zelliklerden ok daha
fazlasn desteklediini hatrnzdan karmayn.
Verinin listeler halinde ktsn alrken, listenin her parasn art iareti ile birbirinden
ayrabilirsiniz:
Console.WriteLine("You ordered + 2 + items at $" + 3 + " each.");
ok uygun olmakla birlikte, nmerik bilgilerin bu ekilde ktsn almak bu bilgilerin
grnmleri zerinde size hibir kontrol salamaz. rnein, kayan noktal bir deer iin
grntlenecek ondalk basamak saysn kontrol edemezsiniz. Aadaki ifadeyi ele aln:
Console.WriteLine("Here is 10/3: " + 10.0/3.0);
Bu, u kty retir:
Here is 10/3: 3.33333333333333
Baz amalar iin bu makul olsa da, bu kadar ok ondalk basamak gstermek dier ama-
lar iin uygun olmayabilir. rnein, mali hesaplamalarda genellikle iki ondalk basamak
gstermeyi tercih edeceksiniz.
BLM 3: VER TPLER, LTERALLER VE DEKENLER

HERKES N C#
57
Nmerik verilerin ne ekilde biimlendirildiini kontrol etmek iin, aada gsterildii
gibi, biimlendirme bilgisini ifadenin iine gmmenize imkn veren ikinci bir WriteLine()
stili kullanmanz gerekecektir:
WriteLine("bicimlendirme karakter katari", arg0, arg1, , argN);
Bu versiyonda WriteLine()a aktarlan argmanlar + iareti ile deil, virgl ile ayrlr.
biimlendirme karakter katar, olduu gibi gsterilen sradan bask karakterleri ve
biimlendirme belirleyicileri olmak zere iki e ierir. Biimlendirme belirleyicileri aadaki
gibi bir genel grne sahiptir:
{argno, genilik:fmt}
Burada argno, gsterilecek argman saysn (0'dan balayarak) belirtir. Minimum alan
genilii genilik ile; biim ise fmt ile belirtilir.
Programn almas srasnda, biimlendirme karakter katar iinde bir biimlendirme
belirleyicisine rastlannca, argno'ya karlk gelen argman argno'nun yerine yerletirilir ve
ekranda gsterilir. Yani argno, elenecek verinin nerede gsterileceini belirleyen,
biimlendirme karakter katarnn iindeki biimlendirme spesifikasyonunun konumudur.
genilik ve fmtnin her ikisi de istee baldr. Bu nedenle, bir biimlendirme belirleyicisi,
en basit ekliyle, sadece hangi argmann gsterileceini belirtir. rnein {0}, arg0 gsterir;
{1}, arg1i gsterir vs.
Gelin, basit bir rnek ile balayalm. u ifade
Console.WriteLine(February has {0} or {1} days. 28, 29);
aadaki kty retir:
February has 28 or 29 days.
Grdnz gibi, {0} iin 28 ve {1} iin de 29 deeri yerine yerletiriliyor. Yani,
biimlendirme belirleyicileri, sonradan gelen argmanlarn, bu rnekte 28 ve 29un, karakter
katar iinde gsterilecei konumlar belirtiyorlar. Ayrca, ekstra deerler + iareti ile deil,
virgl ile ayrlyor.
imdi de nceki ifadenin minimum alan geniliini de belirten bir versiyonuna bakalm:
Console.WriteLine("February has {0, 10} or (1,5} days", 28, 29};
Bu ifade aadaki kty retir:
February has 28 or 29 days
Grdnz gibi alanlarn kullanlmayan ksmlarn doldurmak iin boluk karakterleri
ilave ediliyor. Minimum alan geniliinin aslnda, sadece minimum genilikten ibaret olduunu
hatrnzdan karmayn. Gerektiinde kt, bu genilii aabilir.

HERKES N C#
KISIM I C# DL

58
Bir biimlendirme komutuyla ilgili argmanlarn elbette sabit olmas gereklidir. rnein
aadaki program, kareler ve kplerden oluan bir tabloyu ekranda gsteriyor. Program,
deerlerin ktsn alrken biimlendirme komutlarn kullanyor.
// Bicimlendirme komutlarini kullan.

using System;

class DisplayOptions {
public static void Main() {
int i;

Console.WriteLine("Value\tSquared\tCubed);

for (i = t; i < 10); i++)
Console.WriteLine("{0}\t{1}\t{2}, i, i*i, i*i*i);
}
}
kt aada gsterilmitir:
Value Squared Cubed
1 1 1
2 4 8
3 9 27
4 16 64
5 25 125
6



36 216
7 49 343
8 64 512
9 81 729

nceki rneklerde deerlerin kendilerine herhangi bir biimlendirme uygulanmamt.
Biimlendirme belirleyicileri kullanlmasnn nedeni elbette, verilerin grnlerini kontrol et-
mektir. En ok biimlendirilen veri tipleri kayan noktal ve ondalk deerlerdir. Bir biimi
belirtmenin en kolay yollarndan biri, WriteLine()n kullanaca bir ablon tarif etmektir.
Bunun iin, rakam konumlarn iaret elmek amacyla # iaretleri kullanarak istediiniz biimin
bir rneini gsterin. Ayrca, ondalk noktay ve virglleri de belirtebilirsiniz. rnein, 10/3
deerini gstermenin daha iyi bir yolu u ekildedir:
Console.WriteLine("Here is 10/3: {0:#.##}", 10.0/3.0);
Bu ifadenin kts aadaki gibidir:
Here is 10/3: 3.33
Bu rnekle ablon, WriteLine()a iki ondalk basamak ayrmasn syleyen #.##
karakterleridir. Ancak, WriteLine()n gerektiinde, deeri hatal gstermemek iin ondalk
noktann solunda birden fazla basamaklk yer brakacan kavramak nemlidir.
BLM 3: VER TPLER, LTERALLER VE DEKENLER

HERKES N C#
59
te bir baka rnek daha.
Console.WriteLine({0:###,###.###}, 123456.56);
Bu ifade aadaki kty retir;
123,456.56
ayet deerleri dolar ve sent biimini kullanarak gstermek istiyorsanz, C biimlendirme
belirleyicisini kullann. rnein,
decimal balance;
balance = 12323.09m;
Console.WriteLine(Current balance is {0:C}, balance);
Bu kod parasnn kts ite yledir:
Current balance is $12,323.09
Daha nce verilen fiyat indirimi programnda kty daha k gstermek amacyla C biimi
kullanlabilir:
/
Dolar ve cent'lerin ciktisini almak iin C bicimlendirme
Belirleyicisini kullanmak.
*/

using System;

class UseDecimal {
public static void Main() {
decimal price;
decimal discount;
decimal discounted_price;

// indirimli fiyati hesapla
price = 19.95m;
discount = 0.15m; // indirim orani: %15

discounted_price = price - (price * discount);

Console.WriteLine("Discounted price: {0:C}", discounted_price);
}
}
kt artk, ile yle grnyor:
Discounted price: $16.96
Literaller
C#ta literaller, insanlarn okuyabilecei biimde temsil edilen sabit deerlere karlk
gelir. rnein, 100 says bir literaldir. Literaller ayrca yaygn olarak sabit (constant) olarak da

HERKES N C#
KISIM I C# DL

60
adlandrlr. ounlukla literallerin kendileri ve kullanmlar o kadar bellidir ki nceki rnek
programlarn tmnde, u veya bu ekilde literal kullanlmtr. Artk bunlar kurall olarak
aklamann zaman geldi.
C# literalleri herhangi bir deer tipinde olabilir, Her literalin gsterili ekli sz konusu
literalin tipine baldr. nceden akland gibi, karakter sabitleri tek trnak iine alnr. rne-
in, a ve % karakter sabitleridir.
Tamsay literaller ondalk ksm olmayan saylar eklinde belirtilir. rnein 10 ve -100
tamsay sabitlerdir. Kayan noktal sabitler, saynn ondalk ksmnn peinden geldii ondalk
nokta kullanmn gerektirir. rnein, 11.123 bir kayan noktal sabittir. C# ayrca, kayan
noktal saylar iin bilimsel (scientific) notasyon kullanmna da imkan verir.
C# tipe sk skya bal bir dil olduu iin literallerin de tipi vardr. Bu, doal olarak akla
u soruyu getirir: Nmerik bir literalin tipi nedir? rnein, 12,123987 veya 0.23n tipi
nedir? Neyse ki C#, bu sorulara yant niteliinde baz takibi kolay kurallar da belirtir.
Oncellikle, tamsay literaller iin literalin tipi, sz konusu literalin tutabilecei intten
balayarak en kk tamsay tipidir. Bylece, bir tamsay literal, deerine bal olarak ya int,
uint, long ya da ulong tipinde olabilir. kincisi, kayan noktal literailer double tipindedir.
Eer C#n varsaylan tipi, sizin literal iin dndnz tipten deilse, literalin tipini bir
sonek ilave ederek aka belirtebilirsiniz. Bir long literali belirtmek iin l veya L ekleyin.
rnein 12, int tipindedir, fakat 12L, long tipindedir. aretsiz bir tamsay deeri belirtmek
iin u veya U ekleyin. Yani 100, int tipindedir, fakat 100U, uint tipindedir. aretsiz uzun bir
tamsayy belirtmek iin ul veya UL kullann. rnein, 984375UL ulong tipindedir.
Bir float lilerali belirtmek iin sabite F veya f ekleyin. rnein, 10.19F float
tipindedir.
Bir decimal literali belirtmek iin deerinin peine m veya M yerletirin. rnein, 9.95M
bir decimal literaldir.
Tamsay literaller varsaylan durumda int, uint, long veya ulong tipinde bir deer
oluturuyor olsa da, atanan deer hedef tip tarafndan simgelenebildii mddete tamsay
literaller, her eye ramen byte, sbyte, short veya ushort tipindeki deikenlere
atanabilir. Bir tamsay literal bir long deikene her zaman atanabilir.
Onaltlk Literaller
Muhtemelen biliyorsunuzdur, programlamada onluk taban yerine kimi zaman onalt
tabanna dayanan say sistemini kullanmak daha kolaydr. Onalt tabanna dayanan say
sistemine onaltlk (hexadecimal) denir ve bu sistem, 0 ile 9 arasndaki rakamlarla, A ile F
arasndaki harfleri kullanr. Adan Fye kadar olan harfler 10, 11, 12, 13, 14 ve 15e karlk
gelir. rnein, onaltlk sistemdeki 10 says, onluk sistemde l6dr. Onaltlk saylarn
BLM 3: VER TPLER, LTERALLER VE DEKENLER

HERKES N C#
61
kullanm sklndan dolay C#, tamsay sabitleri onaltlk biimde belirtmenize imkn verir.
Bir onaltlk literal 0x (sfr ve x) ile balamaldr. te birka rnek:
count = 0xFF; //ondalik tabanda 255
incr = 0x1a; //ondalik tabanda 26
Karakter Ka Sekanslar
Karakter sabitlerini tek trnak iine almak, baslan karakterlerin pek ou iin ie yarar;
fakat, metin editr kullanldnda birka karakter, mesela carriage return (paragraf sonu)
karakteri, zel bir problemin ortaya kmasna neden olur. stelik, baz baka karakterlerin,
mesela tek ve ift trnan C#ta zel bir anlam da vardr. Bu yzden, bunlar dorudan
kullanamazsnz. Bu nedenlerden tr C# birka tane ka sekans sunmaktadr. Tablo 3.2de
gsterilen bu karakterlerden kimi zaman ters bl iaretli karakter sabitleri olarak da sz edilir.
Bu ka sekanslar simgeledikleri karakterlerin yerine kullanlrlar.
rnein, aadaki ifade ch deikenine sekme karakterini atyor:
ch = \t;
Sradaki rnek ise ch deikenine tek trnak karakterini atar:
ch = \;


TABLO 3.2: Ka Sekanslar


Ka Sekans Anlam
\a
Uyar (Zil)
\b
Backspace (Geri al)
\f
Form feed (Form besleme)
\n
Newline (Yeni satr)
\r
Carriage return (Paragraf sonu)
\t
Yatay sekme
\v
Dey sekme
\0
Null
\
Tek trnak
\
ift trnak
\\ Ters bl





HERKES N C#
KISIM I C# DL

62
Karakter Katar Literalleri
C# bir baka tipte literali daha destekler: Karakter katar literali. Karakter katar, ift trnak
iine alnan bir karakter kmesidir, rnein, aada bir karakter katar gryorsunuz.
"bu bir denemedir"
nceki rnek programlardaki WriteLine() ifadelerinin birounda karakter katar
rneklerini grmtnz.
Normal karakterlere ek olarak bir karakter katan literali ayrca, az nce bahsedilen ka
sekanslarndan bir veya daha fazla ierebilir. rnein, aadaki program ele aln. Bu program
\n, \t ve \ ka sekanslarn kullanyor.
// Karakter katarlari icindeki kacis sekanslarini gosterir.

using System;

class StrDemo {
public static void Main() {
Console.WriteLine("Line One\nLine Two\nLine Three");
Console.WriteLine("One\tTwo\tThree");
Console.WriteLine("Four\tFive\tSix);

// tirnak isaretlerini gom
Console.WriteLine("Why?\", he asked.");
}
}
kt aada gsterilmitir:
Line One
Line Two
Line Three
One Two Three
Four Five Six
"Why?, he asked.
\n ka sekansnn yeni bir satr oluturmak iin nasl kullanldna dikkat edin. ok
satrl kt almak iin birka tane WriteLine() ifadesi kullanmanza gerek yoktur. Uzunca
bir karakter katar iinde hangi noktalarda yeni bir satr oluturulmasn istiyorsanz bu
noktalara \n yerletirmeniz yeterlidir. Ayrca, bir karakter katar iinde soru iaretinin nasl
oluturulduuna da dikkat edin.
imdi bahsedilen karakter katar literal stiline ek olarak, ayrca harfi harfine karakter
katar literali (verbatim string literal) de belirtebilirsiniz. Harfi harfine karakter katar literali @
ile balar ve bunu trnak iine alnm karakter katar izler. Trnak iine alnm karakter
katarnn ierii deiiklik yaplmakszn kabul edilir ve iki veya daha fazla satr uzunluunda
olabilir. Yani, newline, sekme gibi karakterleri dhil edebilirsiniz, fakat ka sekanslarn
kullanmanza gerek yoktur. Tek bir istisna, ift trnak (") elde etmek iin bir satrda iki adet
BLM 3: VER TPLER, LTERALLER VE DEKENLER

HERKES N C#
63
ift trnak () kullanmanz gerektiidir. te size, harfi harfine karakter katar literallerini
gsteren bir program:
// harfi harfine karakter katari literallerini gosterir.

using System;

class Verbatim {
public static void Main() {
Console.WriteLine(@This is a verbatim
string literal that
spans several lines.
);
Console.WriteLine(@Here is some tabbed output:
1 2 3 4
5 6 7 8
);
Console.WriteLine(@Programmers say, I like C#. );
}
}
Bu programn kts aada gsterilmitir:
This is a verbatim
string literal
that spans several lines.
Here is some tabbed output:
1 2 3 4
5 6 7 8
Programmers say, I like C#.
nceki programla ilgili dikkat eken nemli bir konu, harfi harfine karakter katar
literallerinin tam olarak programa girildikleri ekliyle gsterilmeleridir.
Harfi harfine karakter katar literallerinin avantaj, kty aynen ekranda grlecei
ekliyle programda belirtebiliyor olmanzdr. Ancak, ok satrl karakter katarlar sz konusu
olduunda, karakter katarnn satrdan tamas programnzn hizasn (girintilenmesini)
anlalmaz hale getirebilir. Bu nedenle, bu kitaptaki programlarda harfi harfine karakter katar
literallerinden sadece kstl oranda yararlanlacaktr Buna ramen, bir ok biimlendirme
durumunda harfi harfine karakter katar literalleri halen mthi bir avantaj salamaktadr.
Son bir husus: Karakter katarlarn karakterlerle kartrmayn. Bir karakter literali, mesela
X, char tipinde tek bir harfi simgeler. Sadece tek bir harf ieren bir karakter katar, mesela
X, yine de bir karakter katardr.
Deikenlere Yakndan Bir Bak
Deikenler Blm 2de tantlmt. Daha nceden rendiiniz gibi, deikenler u ifade
stili kullanlarak deklare edilirler:
tip deiken-ismi

HERKES N C#
KISIM I C# DL

64
Bu ifadede tip, deikenin veri tipi; deiken-ismi ise deikenin ismidir. Ksa bir
sre nce bahsedilen veri tipleri de dhil olmak zere, herhangi geerli bir tipte deiken
deklare edebilirsiniz. Bir deiken tanmladnzda deikenin tipinin bir rneini de
tanmlarsnz. Bylece, bir deikenin becerileri deikenin tipi ile belirlenir. rnein, bool
tipinde bir deiken, kayan noktal deerleri saklamak iin kullanlamaz. Ayrca, bir deikenin
tipi, deikenin yaam sresi iinde deitirilemez. rnein, bir int deiken, char deikene
dntrlemez.
C#taki tm deikenler kullanlmadan nce deklare edilmelidir. Bu gereklidir, nk
derleyici, sz konusu deikeni kullanan herhangi bir ifadeyi derlemeden nce deikenin ne
tr bir veri ierdiini tam olarak bilmelidir. Bu ayrca C#n sk bir tip kontrol yapmasn da
mmkn klar.
C#ta birka deiik trde deiken tanmlanr. Bizim kullanmakta olduumuz tr yerel
deikenler olarak adlandrlr, nk bunlar bir metot iinde deklare edilirler.
Bir Deikene lk Deer Atamak
Bir deikeni kullanmadan nce deikene bir deer vermelisiniz. Bunu gerekletirmenin
bir yolu, nceden grdnz gibi atama ifadesi araclyladr. Dier bir yolu ise deiken
deklare edildii srada deikene bir ilk deer atamaktr. Bunu gerekletirmek iin deikenin
isminin ardndan eittir iareti ve atanacak deeri yazn, lk deer atamasnn genel ekli
aadaki gibidir:
tip deiken - deer;
Burada deer, deiken oluturulduunda deiken'e verilen deerdir. Deer, belirtilen tip
ile uyumlu olmaldr.
te birka rnek:
int count = 10; // counta baslangicta 10 deerini ver
char ch = 'X'; // ch'e X ilk deerini ata
float f = 1.2F; // fe 1.2 ilk deeri atanir
Virgl ile ayrlm bir liste kullanarak ayn tipte iki veya daha fazla deikeni deklare eder-
ken, bu deikenlerden bir veya daha fazlasna ilk deer atayabilirsiniz. rnein:
int a, b = 8, c = 19, d; // b ve c baslangic degerine sahipler
Bu durumda yalnzca b ve cye ilk deer atanyor.
Dinamik lk Deer Atamas
nceki rneklerde ilk deer olarak yalnzca sabitler kullanlm olmasna ramen C#,
deikenin deklare edildii anda, geerli olan herhangi bir deyim kullanlarak, deikenlere
dinamik olarak ilk deer atamanza imkn verir. rnein aada, iki dik kenar verilen bir dik
genin hipotensn hesaplayan ksa bir program grlyor:
BLM 3: VER TPLER, LTERALLER VE DEKENLER

HERKES N C#
65
// Dinamik ilk deger atamasi islemini gosterir.

using System;

class DynInit {
public static void Main() {
double s1 = 4.0, s2 = 5.0; // kenarlarin uzunluklari

// hypot'a dinamik olarak ilk deger ata
double hypot = Math.sqrt( (s1 * s1) + (s2 * s2) );
Console,Write(Hipotenuse of triangle with sides + s1 +
by + s2 + is );

Console.WriteLine({0:#.###}., hypot);
}
}
kt ise yle olur:
Hypotenuse of triangle with sides 4 by 5 is 6.403.
Burada yerel deiken - sl, s2 ve hypot - deklare edilmektedir. lk ikisine, - s1 ve
s2 - sabitlerle ilk deer atanmaktadr. Ancak, hypot'a hipotensn uzunluu dinamik olarak
atanmaktadr. Dikkat ederseniz, ilk deer atama ilemi Math.Sqrt() arsn da
iermektedir. Daha nce akland gibi, deklarasyon srasnda geerli olan herhangi bir
deyimi kullanabilirsiniz. Bu noktada Math.Sqrt()a (veya dier herhangi bir ktphane
metoduna) yaplan ar geerli olduu iin hypot'a ilk deer atamak zere Math.Sqrt()
kullanlabilir. Buradaki en nemli nokta, ilk deer atayan deyimin, ilk deer atanrken geerli
olan herhangi bir eyi; metot arlar, dier deikenler veya literaller de dhil olmak zere
kullanabilmesidir.
Deikenlerin Kapsam ve Yaam Sreleri
imdiye kadar kullanmakta olduumuz deikenlerin tm, Main() metodunun banda
deklare edilmekteydi. Ancak, C# bir yerel deikenin herhangi bir blok iinde deklare
edilmesine imkn vermektedir. Blok, al kme parantezi ile balar ve kapan kme parantezi
ile sona erer. Blok, bir deklarasyon uzay (declaration space) veya kapsam (scope) tanmlar.
Bylece, her yeni blok balattnzda yeni bir kapsam tanmlarsnz. Kapsam, programnzn
dier blmleri tarafndan hangi nesnelerin eriilebileceini belirler. Ayrca, bu nesnelerin
yaam srelerini de saptar.
C#taki en nemli kapsamlar, bir snf ve bir metot tarafndan tanmlananlardr. Snflarn
kapsam (ve bu kapsam iinde tanml deikenler) ile ilgili tartma snflar ele alnana kadar
ertelenmitir. imdilik bir metot tarafndan veya bir metot iinde tanmlanan kapsamlar
inceleyeceiz.
Bir metot tarafndan tanmlanan kapsam, metodun al kme parantezi ile balar. Ancak,
sz konusu metodun parametreleri varsa onlar da metodun kapsamna dhil edilir.

HERKES N C#
KISIM I C# DL

66
Genel bir kural olarak, bir kapsam iinde tanmlanan deikenler, bu kapsamn dnda
tanmlanm kod tarafndan grlemezler (yani. eriilemezler). Bylece, bir kapsam iinde bir
deiken deklare ettiiniz zaman, sz konusu deikeni yerelletirmi ve izinsiz eriimden
ve/veya deiikliklerden korumu olursunuz. Gerekten de, kapsam kurallar, verilerin
paketlenmesi (encapsulation) kavramnn temelini oluturmaktadr.
Kapsamlar kmelenebilir. rnein, bir kod blou oluturduunuz anda bir de yeni,
kmelenmi bir kapsam da tanmlam olursunuz. Bu durum sz konusu olduunda dtaki
kapsam itekini kuatr. Bu. dtaki kapsam iinde deklare edilen nesnelerin iteki kapsam
iindeki kod tarafndan grlecei anlamna gelir. Ancak, bunun tersi doru deildir. teki
kapsam iinde deklare edilen nesneler, bu kapsam dndan grlemeyeceklerdir.
Kmelenmi kapsamlarn etkisini anlamak amacyla aadaki programa bir gz atn:
// Bloklarn kapsamlarini gosterir.

using System;

class ScopeDemo {
public static void Main() {
int x; // Main() icindeki kodlarin tumu tarafindan bilinir

x = 10;
if(x == 10) { // yeri bir kapsam baslat

int y = 20; // sadece bu blok tarafindan bilinir

// x ve ynin her ikisi de biliniyor
Console.WriteLine("x and y: + x + " " + y};
x = y * 2;
}
// y = 100; // Hata! y burada bilinmiyor

// x hala biliniyor.
Console.WriteLine("x is * + x);
}
}
Aklamalardan grlecei gibi, x deikeni Main() in kapsamnn en banda deklare
edilmektedir ve Main() iindeki kalan kodun tm tarafndan eriilebilir. y, if blou iinde
deklare edilmektedir, Blok, bir kapsam tanmlad iin y sadece kendi blou iindeki dier
kodlar tararndan grlebilir. ynin blou dnda kalan y = 100; satrnn aklama yoluyla
koddan karlmasnn nedeni budur. Satrn banda yer alan aklama simgesini kaldrrsanz,
derleme srasnda hata ortaya kar, nk y, blou dnda eriilemez. x, if blou iinde
kullanlabilir, nk bir blok iindeki kod (yani, kmelenmi kapsam), kendisini kuatan
kapsam tarafndan deklare edilen deikenlere eriim hakkna sahiptir
Blok iinde, deikenler herhangi bir noktada deklare edilebilir, fakat ancak deklare
edildikten sonra geerlidirler. Yani, bir metodun en banda bir deiken tanmlyorsanz, bu
deiken sz konusu metot iindeki kodun btnnn kullanmna hazrdr. Aksi halde, bir blo-
BLM 3: VER TPLER, LTERALLER VE DEKENLER

HERKES N C#
67
un sonunda bir deiken tanmlyorsanz, bu gerekte ie yaramaz, nk hi bir kod buna
eriemeyecektir.
Hatrnzda tutmanzn nemli olduu bir baka konu da udur: Deikenler, kendi
kapsamlarna girildii zaman oluturulurlar ve kapsamlarndan knca yok edilirler. Bu, bir
deikenin kapsamn terk ettii andan itibaren deerini saklamayaca anlamna gelir. Bu
nedenle, bir metot iinde deklare edilen deikenler, bu metoda yaplan arlar arasnda
deerlerini saklamayacaklardr. Ayrca, bir blok iinde deklare edilen bir deiken, blok terk
edildiinde kendi deerini kaybedecektir. Yani, bir deikenin yaam sresi, deikenin
kapsam ile snrldr.
ayet bir deiken deklarasyonu ilk deer atamas ieriyorsa, bu deikenin deklare
edildii blok iine her girite, deikene yeniden ilk deer atanacaktr. rnein, u programa
bir gz atn:
// Bir degiskenin yasam suresini gosterir.

using System;

class VarlnitDemo (
public static void Main() {
int x;

for[x = 0; x < 3; x++} {
int y = -1; // bloga her giriste yye ilk deger atanir
Console.WriteLine("y is: " + y); // bu, daima -1 yazar
y - 100;
Console.WriteLine{"y is now: + y);
}
}
}
Bu programn rettii kt aada gsterilmitir:
y is: -1
y is now: 100
y is: -1
y is now: 100
y is: -1
y is now: 100
Grdnz gibi, for dngsne her girite yye -1 deeri yeniden atanyor, y'ye
sonradan 100 deeri atanyor olsa bile, bu deer yitiriliyor.
C#n kapsamla ilgili kurallarnn sizi artabilecek garip bir taraf da vardr: Bloklar
kmelenebilmelerine ramen, iteki kapsam iinde deklare edilen deikenlerin hibiri, iteki
kapsam kuatan kapsam tarafndan deklare edilen deikenlerle ayn isimde olamaz. rnein,
ayn isimde iki ayr deiken deklare etmeye alan aadaki program derlenmeyecektir.
/*
Bu program, distaki kapsam icinde tanimli

HERKES N C#
KISIM I C# DL

68
bir degisken ile ayni isimde, icteki kapsam icinde bir
degisken deklare etmeye calisir.
*** Bu program derlenmez, ***
*/

using System;

class NestVar {
public static void Main() {
int count;

for(count = 0; count < 10; count = count+1) {
Console.WriteLine("This is count: " + count);

int count; // kural disi!!!
for(count = 0; count < 2; count++)
Console.WriteLine{"This program is in error!");
}
}
}
C/C++ biliyorsanz, bu dillerde, iteki kapsam iinde deklare edilen deikenlere verilen
isimler zerinde hibir kstlama olmadn bilirsiniz. Yani, C/C++ ta dtaki for dngs
blou iinde yer alan count deklarasyonu tamamen geerlidir. Ancak. C/C++ta bu tr bir
deklarasyon, dtaki deikeni gizler. C# tasarmclar isim gizleme (name hiding) adl bu
zelliin kolaylkla programlama hatalarna yol aabileceini hissettiler ve buna izin
vermediler.
Tip Dnmleri ve Tip Atamalar
Programlama yaparken bir tipteki deikeni bir bakasna atamak ok yaygndr. rnein,
aada gsterildii gibi bir int deerini bir float deikenine atamak isteyebilirsiniz:
int i;
float f;
i = 10;
f = i; // inti floata atiyor
Birbiriyle uyumlu tipler bir atama ifadesi iinde kark biimde kullanlrsa, sa taraftaki
deer otomatik olarak sol taraftakinin tipine dntrlr. Yani, yukardaki program parasnda
inin iindeki deer floata dntrlr, sonra fye atanr. Ancak, C#n sk tip
kontrolnden tr tiplerin tm uyumlu deildir. Bu nedenle, tip dnmlerinin tmne
kapal olarak izin verilmez. rnein, bool ve int uyumlu deildir. Neyse ki, bir tip atamas
(cast) kullanarak uyumsuz tipler arasnda dnm elde etmek, her eye ramen mmkndr.
Tip atamas, tip dnmn aka gerekletirir. Hem otomatik tip dnm, hem de tip
atamalar aada ele alnmaktadr.


BLM 3: VER TPLER, LTERALLER VE DEKENLER

HERKES N C#
69
Otomatik Dnmler
Bir tipteki bir veri, bir baka tipteki deikene atandnda, aadaki artlar saland
takdirde otomatik tip dnm sz konusu olur:
Her iki tip uyumludur.
Hedef tip, kaynak tipten daha byktr.
Bu iki koul salandnda geniletici dnm (widening conversion) sz konusu olur.
rnein, int tipi her zaman geerli byte deerlerinin tmn tutacak kadar byktr. stelik,
int ve byte tamsay tipidir; bu nedenle otomatik dnm uygulanabilir.
Geniletici dnmler iin nmerik tipler, tamsay ve kayan noktal tipler de dahil olmak
zere birbiriyle uyumludur. rnein, aadaki program tamamen geerlidir, nk longdan
doublea yaplan dnm, otomatik olarak gerekletirilen bir geniletici dnmdr.
// longdan doublea otomatik donusum gsterir.

using System;

class LtoD {
public static void Main() {
long L;
double D;

L = 100123285L;
D = L;























HERKES N C#
KISIM I C# DL

70
















































BLM 3: VER TPLER, LTERALLER VE DEKENLER

HERKES N C#
71

































Console.WriteLine(u after assigning 64000: " + u +
-- no data lost."};

// long'u uint'e donustur, veri kaybi var
l = -12;
u = (uint) l;
Console.WriteLine("u after assigning -12: " + u + " data
lost.");
Console.WriteLine();

// int'i char'a donustur
b = 88; // x'in ASCII kodu
ch = (char) b;
Console.WriteLine("ch after assigning 88: " + ch);
}
}

HERKES N C#
KISIM I C# DL

72
Programn kts aada gsterilmitir:
Integer outcome of x / y: 3

b after assigning 255: 255 -- no data lost.
b after assigning 257: 1 --data lost.

s after assigning 32000: 32000 -- no data lost.
s after assigning 64000: -1536 -- data lost.

u after assigning 64000: 64000 -- no data lost.
u after assigning -12: 4294967284 -- data lost.

ch after assigning 88: X
imdi gelin, atamalarn her birine gz atalm. (x/y)nin tip atamas yoluyla inte
dntrlmesi ondalk ksmn kesilmesiyle sonulanr, bilgi kayb olmutur.
bye 255 deeri atandnda bilgi kayb olmaz, nk byte 255 deerini tutabilir. Ancak,
bye 257 deerini atama giriiminde bulunulunca bilgi kayb meydana gelir, nk 257
byten deer aral dndadr. Her iki durumda da tip atamas gereklidir, nk intten
bytea otomatik dnm yoktur.
short deikeni se, uint tipinde u deikeni zerinden 32.000 deeri atandnda hi
veri kayb olmaz, nk short 32.000 deerini tutabilir. Ancak, bir sonraki atamada u,
shortun deer aral dnda kalan 64.000 deerine sahiptir ve veri kayb sz konusu olur.
Her iki durumda da tip atamas gereklidir, nk uintten shorta otomatik dnm yoktur.
Bir sonraki atamada, uya long tipinde 1 deikeni zerinden 64.000 deeri atanr. Bu
durumda hi veri kayb olmaz, nk 64.000 uint menzili iindedir. Ancak, uya -12 deeri
atandnda veri kayb olur, nk uint negatif saylar tutamaz. Her iki durumda da tip
atamas gereklidir, nk longdan uinte otomatik dnm yoktur.
Son olarak, en son atamada bilgi kayb olmaz, fakat byte deerini chara atarken tip ata-
mas gereklidir.
Deyimlerde Tip Dnmleri
Bir atama ifadesinde yer alan tip dnmlerine ek olarak ayrca deyimler iinde de tip
dnmlerine rastlanr. Bir deyim iinde iki veya daha fazla sayda farkl veri tipini, tiplerin
birbirleriyle uyumlu olmalar artyla, zgrce kartrabilirsiniz. rnein, short ve longu
bir deyim iinde kark kullanabilirsiniz, nk bunlarn her ikisi de nmerik tiplerdir. Farkl
veri tipleri bir deyim iinde kartrldnda, tek tek ilem baznda ayn tipe dntrlr.
Dnmler, C#n tip terfi kurallar (type promotion rules) kullanlarak gerekletirilir.
Bu kurallarn ikili (binary) ilemler iin tanmlad algoritma u ekildedir:
BLM 3: VER TPLER, LTERALLER VE DEKENLER

HERKES N C#
73
EER bir operand decimal ise, BU DURUMDA dier operand decimale ykseltilir
(terfi ettirilir). (Dier operand, float veya double tipinde olmad srece bu dorudur. Aksi
halde hata ortaya kar.)
AKS HALDE, EER bir operand double ise, ikinci operand doublea ykseltilir.
AKS HALDE, EER bir operand float ise, ikincisi floata ykseltilir,
AKS HALDE, EER bir operand ulong ise, ikincisi ulonga ykseltilir. (kinci
operand, sbyte, short, int veya long tipinde olmad srece bu dorudur. Aksi halde, hata
ortaya kar.)
AKS HALDE. EER bir operand long ise, ikincisi longa ykseltilir.
AKS HALDE, EER bir operand uint ise ve ikincisi sbyte, short veya int tipinde
ise, her ikisi de longa ykseltilir.
AKS HALDE, EER bir operand uint ise, ikincisi uinte ykseltilir.
AKS HALDE her iki operand da inte ykseltilir.
Tip terfi kurallar ile ilgili dikkat edilmesi gereken birka nemli husus vardr. ncelikle,
bir deyim iinde tiplerin tm kartrlamaz. zellikle, float veya doubledan decimale
kapal dnm sz konusu deildir. Ayrca, ulongu da herhangi iaretsiz bir tamsay tip ile
kartrmak mmkn deildir. Bu tipleri kartrmak, ak bir tip atamas kullanmn gerektirir.
kinci olarak, son kurala zellikle dikkat edin. Bu kural, nceki kurallarn hibiri geerli
olmad takdirde dier operandlarn tmnn inte ykseltileceini bildiriyor. Bu nedenle,
bir deyim iinde tm char, sbyte, byte, ushort ve short deerleri hesaplama amal
kullanmlar iin ykseltilir. Buna tamsay terfisi (integer promotion) denir. Bu, ayrca tm
aritmetik ilemlerinin sonularnn intten daha kk olmayaca anlamna gelir.
Tip terfilerinin sadece, bir deyimin deeri hesaplanrken zerinde ilem yaplan deerler
zerine etki ettiini kavramak nemlidir. rnein, eer bir byte deikeninin deeri bir deyim
iinde inte ykseltilmise, deyimin dnda deiken hala bytedr. Tip terfisi yalnzca
deyimin deerinin hesaplann etkiler.
Tip terfisi, her eye ramen, baz beklenmedik sonulara da yol aabilir. rnein, bir
aritmetik ilem iki byte deeri ierirse, pe pee u durumlar ortaya kar, lk nce, byte
operandlar inte ykseltilir. Sonra, ilem yaplr, Bu ilem int tipinde bir sonu retir.
Bylece, iki byte deeri ieren ilemin sonucu bir int olacaktr. Bu, iten ie beklemi
olabileceiniz bir durum deildir. Bir de, aadaki program ele aln:
// Terfi surprizi!

using System;

class PromDemo {

HERKES N C#
KISIM I C# DL

74
public static void Main() {
byte b;

b = 10;
b = (byte) (b * b); // tip atamas gerekli!!

Console.WriteLine("b: "+ b);
}
}
Sezgilerimize biraz ters gelebilse de, b*b deerini tekrar bye atarken byte atamasna
gerek vardr. Bunun nedeni, b*b deyiminin deeri hesaplanrken bnin deerinin inte
ykseltilmesidir. Yani, b*b ilemi int deeri ile sonulanr ki bu, tip atamas kullanlmadan
bir byte deikenine atanamaz. Tamamen uygun olmas beklenen deyimlerde tip uyumsuzluu
ile ilgili beklenmedik hata mesajlarna rastlyorsanz, bu bahsedilen durumu hatrnzdan
karmayn.
Ayn durum, charlar zerinde gerekletirilen ilemlerde de ortaya kmaktadr. rnein,
aadaki kod parasnda, ch1 ve ch2nin deyim iinde inte ykseltilmesinden tr tip ata-
mas yardmyla tekrar chara dnm gereklidir:
char ch1 = a, ch2 = b;
ch1 = (char) (ch1 + ch2);
Tip atamas olmadan chli ch2ye ekleme ilemi int olarak sonulanr. Bu sonu ise
chara atanamaz.
Tip terfileri ayrca tekli ilemlerde de, mesela tekli - ileminde, yer alabilir. Tekli
ilemlerde, intten kk operandlar (byte, sbyte, short ve ushort) inte ykseltilir.
Ayrca, char operand da inte dntrlr. Bundan baka, bir uintin deeri negatif
olmusa longa ykseltilir.
Deyimlerde Tip Atamas Kullanmak
Byke bir deyimin belirli bir ksmna tip atamas uygulanabilir. Bu, bir deyimin deeri
hesaplanrken ortaya kan tip dnmlerinin meydana geli ekilleri zerinde hassas bir
kontrol salar. rnein, aadaki program ele aln. Bu program lden 10a kadar olan
saylarn karelerini gsteriyor. Program ayrca her sonucun hem tamsay ksmn, hem de
ondalk ksmn ayr ayr gsteriyor. Bunu gerekletirmek iin Math.sqrt()un sonucunu
inte dntrmek amacyla tip atamas kullanyor.
// Deyim icinde tip atamalari kullanmak.

using System;

class CastExpr {
public static void Main(){
double n;

BLM 3: VER TPLER, LTERALLER VE DEKENLER

HERKES N C#
75
for(n = 1.0; n <= 10; n++) {
Console.WriteLire("The square root of {0} is {1}", n,
Math.Sqrt(n));

Console.WriteLine(Whole number part: {0} , (int)
Math.Sqrt(n));

Console.writeLine(Fractional part: {O}, Math.Sqrt(n)
- (int) Math.Sqrt(n));
Console.WriteLine();
}
}
}
Programdan alnan kt yle olur:
The square root of 1 is 1
Whole number part: 1
Fractional part: 0

The square root of 2 is 1.4142135623731
Whole number part: 1
Fractional part: 0.414213562373095

The square root of 3 is 1.73205080756888
Whole number part: 1
Fractional part: 0.732050807568877

The square root of 4 is 2
Whole number part: 2
Fractional part: 0

The square root of 5 is 2.23606797749979
Whole number part: 2
Fractional part: 0.23606797749979

The square root of 6 is 2.44948974278318
Whole number part: 2
Fractional part: 0.449489742783178

The square root of 7 is 2.64575131106459
Whole number part: 2
Fractional part: 0.645751311064591

The square root of 8 is 2.82842712474619
Whole number part: 2
Fractional part: 0.82842712474619

The square root of 9 is 3
Whole number part: 3
Fractional part: 0

The Square root of 10 is 3.16227766016838
Whole number part: 3
Fractional part: 0.16227766016838

HERKES N C#
KISIM I C# DL

76
ktdan grlecei gibi, Math.Sqrt()un tip atamas yoluyla inte dntrlmesi,
sonu deerin tamsay bileenine karlk geliyor. u deyimde,
Math.Sqrt(n) (int) Math.Sqrt(n)
inte dntren tip atamas ile tamsay bileen elde ediliyor. Bu deer daha sonra, asl
deerden karlarak ondalk bileen elde ediliyor. Yani, deyimin sonucu doubledr. inte
dntrlen yalnzca Math.Sqrt()a yaplan ikinci arnn deeridir.





D R D N C B L M

OPERATRLER





















4
4

HERKES N C#
KISIM I C# DL

78
C#, programclara, deyimlerin kurulmas ve deerlerinin hesaplanmas zerinde ayrntl
bir kontrol salayan kapsaml bir operatr seti sunmaktadr, C# drt adet genel operatr snf
ierir: aritmetik, bit tabanl, ilikisel ve mantksal. Bunlar bu blmde incelenmektedir. Ayrca,
ele alnan dier konular arasnda atama operatr ve ? operatr de yer almaktadr. C#ta be-
lirli zel durumlar kontrol altna alan dier birka operatr daha tanmlanmtr. Bu zel opera-
trler bu kitapta daha sonra, bu operatrlerin uygulandklar zellikler ele alndnda incelen-
mektedir.
Aritmetik Operatrler
C#ta aadaki aritmetik operatrler tanmldr:
Operatr Anlam
+ Toplama
karma
* arpma
/ Blme
% Modls (Kalan)
++ Artrma
-- Eksiltme
+, -, * ve / operatrleri dier bilgisayar dillerinde (veya cebirde) nasl alyorlarsa, C#ta
da ayn ekilde alrlar. Bunlar herhangi bir standart nmerik veri tipine uygulanabilirler.
Aritmetik operatrlerin faaliyetleri okuyucularn tm tarafndan ok iyi biliniyor olsa da,
birka zel durumu aklamak gerekir. ncelikle, / operatr bir tamsayya uyguland
zaman, kalann kesilip atlacan hatrnzdan karmayn. rnein, 10/3 tamsay blme
ileminin sonucu 3e eit olacaktr. Bu blmenin kalann modls operatrn (%) kullanarak
elde edebilirsiniz, Modls operatr C#ta, dier dillerde alt gibi, tamsay blmesinin
kalann sonu olarak verir. rnein, 10 % 3 ileminin sonucu 1dir. C#ta % operatr hem
tamsaylara hem de kayan noktal saylara uygulanabilir. Yani, 10.0 % 3.0 ileminin de
sonucu 1dir. (Bu, modls ilemlerine yalnzca tamsay tipler zerinde izin veren C/C++tan
farkldr.) Aadaki program modls operatrn gstermektedir:
// % operatorunun kullanimini gosterir.

using System;

class ModDemo {
public static void Main() {
int iresult, irem;
double dresult, drem;

iresult = 10 / 3;
irem = 10 % 3;

BLM 4: OPERATRLER

HERKES N C#
79
dresult = 10.0 / 3.0;
drem = 10.0 % 3.0;

Console.WriteLine("Result and remainder of 10 / 3: +
iresult + " " + irem);

Console.WriteLine("Result and remainder of 10.0 / 3.0: +
dresult + + drem);
}
}
Programdan elde edilen kt aada gsterilmitir:
Result and remainder of 10 / 3: 3 1
Result and remainder of 10-0 / 3.0: 3.33333333333333 1
Grdnz gibi, % operatr hem tamsaylarla hem da kayan noktal saylarla yaplan
ilemlerde 1 kalann veriyor.
Artrma ve Eksiltme
Blm 2de tantlan ++ ve -- operatrleri, artrma ve eksiltme operatrleridir. Bu
operatrleri olduka ilgin klan baz zel zelliklere sahip olduklarn reneceksiniz. Gelin
imdi, artrma ve eksiltme operatrlerinin tam olarak ne ie yaradklarn tekrarlayarak
balayalm.
Artrma operatr operandna 1 ekler; eksiltme operatr de 1 kartr. Bu nedenle,
x = x + 1;
aadaki ifade le ayndr:
x++;
Ayrca,
x = x - 1;
u fade ile ayndr:
x--;
Artrma ve eksiltme operatrlerinin her ikisi de operandn nnde (nek) veya arkasnda
(sonek) yer alabilir. rnein, u ifade
x = x +1;
yeniden aadaki gibi yazlabilir:
++x; // nek formunda
Veya u ekilde de yanlabilir:
x--; // sonek formunda

HERKES N C#
KISIM I C# DL

80
Yukardaki rnekte artrmann nekli veya sonekli olarak uygulanmas arasnda hibir fark
yoktur. Ancak, artrma veya eksiltme operatrleri daha byk bir deyimin bir paras olarak
kullanlnca nemli bir fark vardr. Artrma veya eksiltme operatr, operandnn nnde yer
alyorsa C#, deyimin geri kalan ksmnda kullanlmak zere operandn deerini hesap etmeden
nce ilemi gerekletirecektir. Eer operatr operandnn peinden geliyorsa C#, artrma veya
eksiltme ileminden nce operandn deerini hesap edecektir. Aadaki ifadelere bir bakn;
x = 10;
y = ++x;
Bu durumda, yye 11 deeri verilecektir. Ancak, eer kod u ekilde yazlrsa
x = 10;
y = x++;
yye 10 deeri verilecektir. Her iki durumda da xe 11 deeri verilir; aradaki fark, bu
ilemin ne zaman gereklendiidir.
Artrma veya eksiltme ileminin ne zaman ele alnacan kontrol edebilmenin salad
nemli avantajlar vardr. Bir say serisi reten aadaki programa bir gz atn:
/*
++nin onek ve sonek formlari
arasindaki farki gosterir.
*/

using System;

class PrePostDemo {
public static void Main() {
int x, y;
int i;

x = 1;

Console.WriteLine("Series generated using y = x + x++;);
for(i = 0; i < 10; i++) {

y = x + x++; // sonek ++

Console.WriteLine(y + );
}
Console.WriteLine();

x = 1;
Console.WriteLine("Series generated using y = x + ++x;");

for(i = 0; i < 10; i++) {

y = a + ++x; // onek ++

Console.WriteLine(y + " ");
}
BLM 4: OPERATRLER

HERKES N C#
81

Console.WriteLine();
}
}
kt aada gsterilmitir:
Series generated using y = x + x++;
2
4
6
8
10
12
14
16
18
20
Series generated using y = x + ++x;
3
5
7
9
11
13
15
17
19
21
ktnn gsterdii gibi, u ifade
y = x + x++;
xin deerini xe ekler ve sonucu yye atar. Sonra xi 1 artrr. Ancak, u ifade
y = x + ++x;
xin deerini alr, xi 1 artrr, sonra bu deeri xin asl deerine ekler. Sonu yye atanr.
ktdan da grlecei gibi, sadece x++ deyimini, ++x ekline evirmek, say serisini ift say
serisinden tek say serisine dntrr,
nceki rnekle ilgili bir baka husus ise udur: u tr deyimlerin
x + ++x
gznz korkutmasna izin vermeyin. ki operatrn pe pee gelmesi ilk bakta biraz
rahatsz edici olmasna ramen derleyici bunu dzgn olarak gerekletirir. Bu deyimin, xi
xin artrlm deerine eklemekten ibaret olduunu hatrnzdan karmayn.


HERKES N C#
KISIM I C# DL

82
likisel ve Mantksal Operatrler
likisel operatrler (relational operators) ve mantksal operatrler (logical operators)
terimlerinde geen ilikisel szc deerlerin birbiri arasnda sahip olabilecei ilikiyi;
mantksal szc ise true ve false deerlerin birbiriyle balanabilme yollarn ifade eder.
likisel operatrler true veya false sonularn rettikleri iin, genellikle mantksal
operatrlerle birlikte kullanlrlar. Bu nedenle, burada mantksal operatrlerle birlikte ele
alnacaklardr.
likisel operatrler aadaki gibidir:
Operatr Anlam
== Eittir
!= Eit deildir
> Byktr
< Kktr
>= Byktr veya eittir
<= Kktr veya eittir

Srada mantksal operatrler yer almaktadr:
Operatr Anlam
& VE
| VEYA
^ XOR (zel VEYA)
|| Ksa devre VEYA
&& Ksa devre VE
! DEL
likisel ve mantksal operatrlerin sonucu bir bool deerdir.
C#ta == ve != kullanlarak tm nesneler eitlik veya eitsizlik asndan karlatnlabilr.
Ancak, karlatrma operatrleri olan <, >, <= veya >=, sadece sralama ilikisini destekleyen
tiplere uygulanabilir. Bu nedenle, ilikisel operatrlerin tm btn nmerik tiplere
uygulanabilir. Ancak, true ve false deerleri sral olmad iin bool tipindeki deerler sa-
dece eitlik veya eitsizlik iin karlatrabilirler. rnein, true>false deyiminin C#ta bir
anlam yoktur.
Mantksal operatrlerin operandlar bool tipinde olmaldr; mantksal bir ilemin sonucu
da bool tipinde olmaldr. Mantksal operatrler olan &, |, ^ ve !, temel mantksal ilemleri -
yani, VE, VEYA, XOR ve DEL - aadaki doruluk tablosuna gre destekler:

BLM 4: OPERATRLER

HERKES N C#
83
p q p&q p|q p^q !p
Yanl Yanl Yanl Yanl Yanl Doru
Doru Yanl Yanl Doru Doru Yanl
Yanl Doru Yanl Doru Doru Doru
Doru Doru Doru Doru Yanl Yanl

Tablodan da grld gibi, XOR ileminin sonucu, sadece ve sadece tek bir operand
doru ise dorudur.
Aada, ilikisel ve mantksal operatrlerin birkan gsteren bir program gryorsunuz:
// Iliskisel ve mantiksal operatorleri gosterir.

using System;

class RelLogOps {
public static void Main() {
int i, j;
bool bl, b2;
i = 10;
j = 11;
if(i < j) Console.WriteLine(i < j);
if(i <= j) Console.WriteLine{i <= j);
if(i != j) Console.WriteLine(i != j);
if(i == j) Console.WriteLine(this won't execute);
if(i >= j) Console.WriteLine(this won't execute);
if(i > j) Console.WriteLine(this won't execute);

b1 = true;
b2 = false;
if(b1 & b2) Console.WriteLine(this won't execute);
if(!(b1 & b2)) Console.WriteLine("!(b1 & b2) is true);
if(b1 | b2) Console.WriteLine(b1 | b2 is true);
if(b1 ^ b2) Console.WriteLine(b1 ^ b2 is true);
}
}
Programn kts aada gsterilmitir:
i < j
i <= j
i != j
!(b1 & b2) is true
b1 | b2 is true
b1 ^ b2 is true
C#n sunduu mantksal operatrler, en yaygn olarak kullanlan mantksal ilemleri
gerekletirmektedir. Bununla birlikte, genel mantk kurallar tarafndan tanmlanan birok
baka ilem de mevcuttur. Bu dier mantksal ilemler, C# tarafndan desteklenen mantksal
operatrler kullanlarak kurulabilir. Yani, C# dier mantksal ilemlerden herhangi birini
kurmak iin yeterli sayda mantksal operatr salamaktadr. rnein, bir baka mantksal

HERKES N C#
KISIM I C# DL

84
ilem ise karmdr (implication). kanm; sonucun yalnzca, soldaki operand doru ve
sadaki operand yanl iken yanl olduu, ikili bir ilemdir. (karm ilemi, dorunun yanl
anlamna gelemeyecei fikrini yanstmaktadr.) Bu sonula, karm operatrnn doruluk
tablosu aada gsterilmitir:
Operatr Anlam
p gerektirir q
(karm)
Doru Doru Doru
Doru Yanl Yanl
Yanl Yanl Doru
Yanl Doru Doru

karm operatr, aada gsterildii gibi, ! ve | operatrlerinin birletirilerek
kullanlmasyla kurulabilir:
!p | q
Bunun uygulamas aadaki programda gsterilmektedir:
// C#'ta bir cikarim operatoru olusturmak.

using System;

class Implication {
public static void Main() {
bool p = false, q=false;
int i, j;

for(i =0; i < 2; i++){
for(j = 0; j < 2; j++) {
if(i == 0) p = true;
if(i == 1) p = false;
if(j == 0) q = true;
if(j == 1) q = false;

Console.WriteLine("p is " + p + ", q is + q);
if(!p | q) Console.WriteLine(p + " implies " + q +
" is " + true);
Console.WriteLine();
}
}
}
}
kt aada gsterilmitir:
p is True, q is True
True implies True is True

p is True q is False

p is False, q is True
BLM 4: OPERATRLER

HERKES N C#
85
False implies True is True

p is False, q is False
False implies False is True
Ksa Devre Mantksal Operatrler
C#, daha verimli kod retmek amacyla kullanabilecek VE ve VEYA mantksal
operatrlerinin zel ksa devre versiyonlarn salar. Bunun neden byle olduunu anlamak iin
una bir bakn. Bir VE ileminde, eer ilk operand yanl ise ikinci operand hangi deeri
ierirse iersin sonu yanltr. Bir VEYA ileminde, eer ilk operand doru ise ikinci
operandn deeri ne olursa olsun ilemin sonucu dorudur. Yani, bu iki durumda ikinci
operandn deerini dikkate almaya gerek yoktur. kinci operandn deerini ileme almayarak
zamandan kazanlm ve daha verimli bir kod retilmi olur.
Ksa devre VE operatr && operatrdr; ksa devre VEYA operatr ise ||
operatrdr, nceden bahsedildii gibi, bunlarn normal karlklar & ve | operatrleridir.
Normal ve ksa devre versiyonlar arasndaki fark, normal operatrlerin her zaman operandlarn
her birinin deerini hesaplamas, fakat ksa devre versiyonlarn ikinci operandn deerini
yalnzca gerektiinde hesaplamasdr.
Aada, ksa devre VE operatrn gsteren bir program gryorsunuz. Program, dnin
iindeki deerin nnin bir arpan olup olmadn belirler. Bunu, modls ilemi ile
gerekletirir. Eer n/d ileminin kalan sfr ise d bir arpandr. Ancak, modls ilemi blme
ierdii iin sfra blme hatasn nlemek amacyla VEnin ksa devre versiyonu kullanlmtr.
// Kisa devre operatorleri gosterir.

using System;

class SCops {
public static void Main() {
int n, d;

n = 10;
d = 2;
if(d != 0 && (n % d) == 0)
Console.WriteLine(d + is a factor of + n);

d = 0; // simdi, d'ye sifir degerini ver

// d, sifir oldugu icin ikinci operator hesaplanmaz.
if(d != 0 && (n % d) == 0)
Console.WriteLine(d + is a factor of + n);

/*Simdi, ayni islemi ksa devre operatoru olmadan deneyin.
Bu, sifira bolme hatasina neden olur.*/
if(d != 0 & (n % d) == 0)
Console.WriteLine (d + is a factor of + n);
}

HERKES N C#
KISIM I C# DL

86
}
Sfra blme hatasn nlemek amacyla if ifadesi ncelikle dnin sfra eit olup
olmadn kontrol ediyor. Eer eitse, ksa devre VE bu noktada durur ve modls blme
ilemini gerekletirmez. Bylece, ilk testte d, 2dir ve modls ilemi gerekletirilir. kinci
test baarsz olur, nk dye sfr deeri verilmitir; modls ilemi sfra blme hatas
nlenerek atlanr. Son olarak, normal VE operatr denenmektedir. Bu, her iki operandn
deerlerinin hesaplanmasna neden olur. Bu durum, sfra blme sz konusu olduunda alma
zaman (runtime) hatasna yol aar.
Ksa devre operatrler baz durumlarda normal karlklarndan daha verimli olduklar iin
C#n niye hala normal VE ve VEYA operatrlerini saladn merak ediyor olabilirsiniz.
Bunun yant udur: Baz durumlarda, ortaya kan yan etkilerden dolay bir VE ya da VEYA
ileminin her iki operandnn da deerini hesaplamay tercih edeceksiniz. unu ele aln:
// Yan etkiler onemli olabilir.

using System;

class SideEffects {
public static void Main() {
int i;

i = 0;

/* Burada, if basarili olmasa da i, yine de
artirilir. */
if(false & (++i < oo)
Console.WriteLine(this won't be displayed");
Console.WriteLine("if statement executed: + i);
// ekranda 1 gosterir

/* Bu kez, i artirilmiyor, cunku
ksa devre operatr artirmayi atliyor */
if(false && (++i < 100))
Console.WriteLine("this won't be displayed");
Console.WriteLine(if statemant executed: + i);
// hala 1 !!
}
}
Aklamalardan grlecei gibi, ilk if ifadesinde if dorulansn veya dorulanmasn, i
artrlr. Ancak ksa devre operatr kullanldnda, ilk operand yanl olduunda i deikeni
artrlmaz. Bundan karlacak ders udur: Eer kodunuz VE ya da VEYA ileminin sadaki
operandnn deerinin hesaplanmasn gerektiriyorsa, C#n bu ilemlerle ilgili ksa devre olma-
yan formlarn kullanmalsnz.
Bir baka husus da udur: Ksa devre VE, koullu VE (conditional-AND) olarak da bilinir.
Ayrca, ksa devre VEYA ise koullu VEYA (conditional-OR) olarak da adlandrlr.
BLM 4: OPERATRLER

HERKES N C#
87
Atama Operatr
Atama operatrn Blm 2den beri kullanmaktasnz. imdi bu operatr kurall olarak
ele almann vakti geldi. Atama operatr, bir adet eittir iaretidir (=). Atama operatr C#ta
dier bilgisayar dillerindekine ok benzer ekilde alr. Genel olarak atama operatr u
stildedir:
deiken = deyim;
Burada, deikenin tipi deyimin tipi ile uyumlu olmaldr.
Atama operatr, size tandk gelmeyebilecek ilgin bir nitelie sahiptir: Atama operatr;
bir atama zinciri oluturmaya imkan verir. rnein, aadaki kod parasn ele aln:
int x, y, z;
x = y = z = 100; // x, y ve z'ye 100 degeri veriliyor
Bu kod paras tek bir ifade kullanarak x, y ve z deikenlerine 100 deerini veriyor. Bu
ie yarar, nk =, sa taraftaki deyimin deerini hesaplayan bir operatrdr. Bylece, z=100
ifadesinin deeri 100dr ve bu deer, yye atanr, sonra sras geldiinde xe atanr. Bir
atama zinciri kullanmak, bir grup deikene ortak bir deer vermenin koiay bir yoludur.
Bileik Atamalar
C#, belirli atama ifadelerinin kodlanmasn kolaylatran zel bileik atama operatrleri
salar. Gelin, bir rnek ile balayalm. Burada gsterilen atama ifadesi:
x = x + 10;
bileik atama kullanlarak yeniden yazlabilir:
x += 10;
+= operatr ifti derleyiciye, xe x art 10 deerini atamasn syler.
te bir baka rnek daha. u ifade
x = x l00;
aadaki ifadeyle ayndr:
x -= 100;
Her iki ifade de, xe x eksi 100 deerini atar.
kili operatrlerin (yani, iki operand gerektirenlerin) tm iin bileik atama operatrleri
mevcuttur. Ksayol ifadesinin genel ekli yledir:
deiken op = deyim;

HERKES N C#
KISIM I C# DL

88
Bylece, aritmetik ve mantksal atama operatrleri u ekli alr:
+= -= *= /=
%= &= |= ^=
Bileik atama ifadeleri bileik olmayan edeerlerinden daha ksa olduklar iin, bileik
atama operatrleri kimi zaman ksayol atama operatrleri olarak da adlandrlr.
Bileik atama operatrleri iki avantaj salarlar. Birincisi, uzun yoldan ifade edilen
edeerlerinden daha kompakttrlar. kincisi, daha verimli altrlabilir kod retilmesini
salayabilirler (nk operandn deeri sadece bir kez hesaplanr). Bu nedenlerden tr,
profesyonelce yazlm C# programlarnda sk sk bileik alama operatrlerinin kullanldn
greceksiniz.
Bit Tabanl Operatrler
C#, uygulanabilecei problem tiplerini genileten birtakm bit tabanl (bitwise) operatrler
sunmaktadr. Bit tabanl operatrler dorudan operandlarnn bitleri zerinde ilem yaparlar. Bit
tabanl operatrler yalnzca tamsay operandlar iin tanmldr. bool, float ve double ze-
rinde kullanlamazlar.
Bu operatrlere bit tabanl denir, nk bir tamsay deeri oluturan bitleri test etmek,
ayarlamak veya kaydrmakta kullanlrlar. Bit tabanl ilemler, sistem seviyesindeki ok eitli
grevler asndan - rnein bir aygtn durum bilgilerinin sorgulanmas veya kurulmas
gerektiinde - nemlidir. Bit tabanl operatrler Tablo 4.1 de listelenmitir.
Bit Tabanl VE, VEYA, XOR ve DEL Operatrleri
Bit tabanl VE, VEYA, XOR ve DEL operatrleri srasyla unlardr: &, |, ^ ve ~. Bu
operatrler, daha nce bahsedilen Boolean mantk edeerleriyle ayn ilemleri
gerekletirirler. kisi arasndaki fark, bit tabanl operatrlerin bitleri esas alarak tek tek bitler
zerinde ilem yapmalardr.
TABLO 4.1: Bit Tabanl Operatrler


Operatr Anlam
& Bit tabanl VE
| Bit tabanl VEYA
^ Bit tabanl XOR
>> Saa kaydrma
<< Sola kaydrma
~ Birin tmleyeni (tekli DEL)
Aadaki tablo, 1ler ve 0lar kullanarak her ilemin sonucunu gsteriyor:
BLM 4: OPERATRLER

HERKES N C#
89
p q p&q p|q p^q ~p
0 0 0 0 0 1
1 0 0 1 1 0
0 1 0 1 1 1
1 1 1 1 0 0
En yaygn kullanm ekliyle bir tabanl VE ilemini, bitleri sfrlamann bir yolu olarak
dnebilirsiniz. Yani, her iki operandn iindeki 0 deerine sahip herhangi bir bit, sonu
deerde karlk gelen bitin 0 olarak ayarlanmasna neden olur. rnein,
1101 0011
1010 1010
& ----------
1000 0010
Aadaki program, tek saylar ift saylara evirmek iin & operatrn kullanarak bu
operatr tantyor. Bu ilemi, sfrnc biti sfrlayarak gerekletiriyor. rnein 9, ikilik
dzende 0000 1001dir. Sfrnc bit sfrlandnda, bu say 8 ya da ikili dzende 0000
1000 olur.
/* Bir sayiyi cift sayiya donusturmek icin bit tabanli VE
kullanir. */

using System;

class MakeEven {
public static void Main(){
ushort num;
ushort i;

for(i = 1; i <= 10; i++) {
num = i;

Console.WriteLine(num: + num);

num = (ushort) (num & 0xFFFE); // num & 1111 1110

Console.WriteLine(num after turning off bit zero: +
num + \n);
}
}
}
Bu programn kts aada gsterilmitir:
num: 1
num after turning off bit zero: 0

num: 2
num after turning off bit zero: 2


HERKES N C#
KISIM I C# DL

90
num: 3
num after turning off bit eero: 2

num: 4
num after turning off bit zero: 4

num; 5
num after turning off bit zero: 4

num: 6
num after turning off bit zero: 6

num: 7
num after turning off bit zero: 6

num: 8
num after turning off bit zero: 8

num: 9
num after turning off bit zero: 8

num: 10
num after turning off bit zero; 10
VE ifadesinde kullanlan 0xFFFE deeri, 1111 1110 saysnn onaltlk dzendeki
gsterimidir. Bylece VE ilemi, chin sfrnc bit hari tm bitlerini deitirmeden brakr.
Sfrnc biti ise sfrlar. Yani, ift saylar deimeden kalr, ama tek saylar, say deerleri bir
azaltlarak ift say haline getirilir.
VE operatr ayrca, bir bitin 1 veya 0 olup olmadn belirlemek istediinizde de
kullanldr. rnein, aadaki program bir saynn tek say olup olmadn belirliyor:
/* Bir sayinin tek sayi olup olmadigini belirlemek icin bit
tabanli VE kullanir. */

using System;

class IsOdd {
public static void Main() {
ushort num;

num = 10;

if((num & 1) == 1)
Console.WriteLine(This won't display.);

num = 11;

if((num & 1) == 1)
Console.WriteLine(num + is odd.);
}
}
kt u ekildedir:
BLM 4: OPERATRLER

HERKES N C#
91
11 is odd.
if ifadeleri iinde num deerine 1 ile VE uygulanr. Eer numn sfrnc biti l ise, num&1
ileminin sonucu ldir; aksi halde, sonu sfrdr. Bu nedenle, if ifadesi yalnzca say tek oldu-
unda dorulanr.
Bit tabanl & operatrnn bit testi becerisini, ikili biimdeki bir byte deerinin bitlerini
gstermek zere bit tabanl & operatr kullanan bir program gelitirmek iin kullanabilirsiniz,
Aadaki gibi bir yaklam uygulanabilir:
// Bir byte icindeki bitleri gosterir.

using System;

class ShowBits {
public static void Main() {
int t;
byte val;

val = 123;
for(t = 128; t > 0; t = t/2) {
if((val & t) != 0) Console.Write(1 );
if((val & t) == 0) Console.Write(0 );
}
}
}
kt aada gsterilmitir:
01111011
for dngs, bit tabanl VE operatrn kullanarak valn bitlerinin 1 veya 0 olup
olmadn pe pee test eder. Eer bit ak (1) ise 1 rakam ekranda gsterilir; aksi halde, 0
gsterilir.
Bit tabanl VEYA, VEnin tersi olarak, bitleri 1e evirmek iin kullanlabilir. Her iki
operandda 1 deerine sahip herhangi bir bit, deiken iinde karlk gelen bitin 1 olarak
ayarlanmasna neden olacaktr. rnein,
1101 0011
1010 1010
| ----------
1111 1011
Az nce gsterilen sayiar ift sayya eviren program, VEYA kullanarak saylar tek
sayya eviren bir program haline dntrebilirsiniz:
// Bir sayiyi tek sayiya donuturmek icin bit tabanli VEYA
kullanir.

using System;


HERKES N C#
KISIM I C# DL

92
class MakeOdd {
public static void Main() {
ushort num;
ushort i;

for(i = 1; i <= 10; i++) {
num = i;

Console.WriteLine(num: + num);

num = (ushort) (num | 1); // num | 0000 0001

Console.WriteLine(num after turning on bit zero: +
num + \n);
}
}
}
Bu programn kts aada gsterilmitir:
num: 1
num after turning on bit zero: 1
num: 2
num after turning on bit zero: 3
num: 3
num after turning on bit zero: 3
num: 4
num after turning on bit zero: 5
num: 5
num after turning on bit zero: 5
num: 6
num after turning on bit zero: 7
num: 7
num after turning on bit zero: 7
num: 8
num after turning on bit zero: 9
num: 9
num after turning on bit zero: 9
num: 10
num after turning on bit zero: 11
Program, her karaktere, ikili dzende 0000 0001 olarak simgelenen 1 ile VEYA
uygulayarak almaktadr. Bylece 1, ikili dzende sadece sfrnc biti 1 olan bir deer retir.
Bu deere herhangi bir baka deer ile VEYA uygulandnda, alt (low-order) biti 1 olarak
ayarlanan, dier bitleri deimeden kalan bir sonu retir. Bylece, ift say olan bir deer bir
artrlacak ve tek say haline gelecektir.
Genellikle XOR olarak ksaltlan zel VEYA, sadece ve sadece karlatrlmakta olan
bitler farklysa bir bite 1 deerini verir. Bu durum aada gsterilmitir:
0111 1111
1011 1001
^ ----------
1100 0110
BLM 4: OPERATRLER

HERKES N C#
93
XOR operatrnn ilgin bir zellii de bir mesaj ifrelemenin kolay bir yolu olmasdr.
Herhangi bir X deerine bir baka Y deeri ile XOR uygulandnda ve sonra, sonuca tekrar Y
ile XOR uygulandnda X elde edilir. Yani, aadaki ifadelerde:
R1 = X ^ Y;
R2 = R1 ^ Y;
R2, X ile ayn deere sahiptir. Yani, ayn deerleri kullanan pe pee iki XOR ifadesinin
sonucu orijinal deeri retir. Bu prensibi, basit bir ifreleme program gelitirmek iin
kullanabilirsiniz. Bu durumda bir tamsay, mesajdaki karakterlere XOR uygulayarak hem
mesaj ifrelemek, hem de mesajn ifresini zmek iin kullanlan bir anahtardr. ifrelemek
ijn XOR ilemi ilk kez uygulanr ve ifrelenmi metin elde edilir. ifreyi zmek iin XOR
ilemi ikinci kez uygulanr ve orijinal metin elde edilir. te size, ksa bir mesaj ifrelemek ve
mesajn ifresini zmek iin bu yntemi kullanan basit bir rnek:
// Bir mesaji sifrelemek ve mesajin sifresini cozmek icin XOR
kullanir.

using System;

class Encode {
public static void Main() {
char ch1 = H;
char ch2 = i ;
char ch3 = !;

int key = 88;

Console.WriteLine(Original message: + chl + ch2 + ch3);

// mesaji sifrele
ch1 = (char) (ch1 ^ key);
ch2 = (char) (ch2 ^ key);
ch3 = (char) (ch3 ^ key);

Console.WriteLine(Encoded message: + ch1 + ch2 + ch3);

// mesajin sifresini coz
ch1 = (char) (ch1 ^ key);
ch2 = (char) (ch2 ^ key);
ch3 = (char) (ch3 ^ key);

Console.WriteLine(Decoded message: + ch1 + ch2 + ch3);
}
}
kt yle olur:
Original message: Hi!
Encoded message: ly
Decoded message: Hi!

HERKES N C#
KISIM I C# DL

94
Grdnz gibi, ayn anahtar kullanan iki XORun sonucunda ifrelenmi mesaj elde
edilir.
Tekli birin tmleyeni (DEL) operatr, operandn bitlerinin tmnn durumlarn ter-
sine evirir. rnein, A adndaki bir tamsay 1001 0110 bitlerine sahipse, ~A ile 0110 1001
bitleri sonu olarak elde edilir
Aadaki program, bir sayy ve ikili dzende bu saynn tmleyenini gstererek DEL
operatrn tantmaktadr:
// Bit tabanli DEGIL operatorunu tanitir.

using System;

class NotDemo {
public static void Main(){
sbyte b = -34;
int t;
for(t = 128; t > 0; t = t/2) {
if((b & t) != 0) Console.Write(1 );
if((b & t) == 0) Console.Write(0 );
}
Console.WriteLine();

// tum bitleri tersine cevir
b = (sbyte) -b;

for(t = 128) t > 0; t = t/2) {
if((b & t) != 0) Console.Write(1 );
if((b & t) == 0) Console.Write(0 );
}
}
}
te programn kts:
1 1 0 1 1 1 1 0
0 0 1 0 0 0 0 1
Kaydrma Operatrleri
C#ta, bir deeri oluturan bitleri saa veya sola belirli bir miktar kaydrmak mmkndr.
C#ta, aada gsterilen iki bit kaydrma operatr tanmldr:
<< Sola kaydrma
>> Saa kaydrma
Bu operatrlerin genel formlar u ekildedir:
deer << bit-says
deer >> bit-says
BLM 4: OPERATRLER

HERKES N C#
95
Yukardaki ifadede deerin bitleri, bit-says ile belirtilen sayda ve kaydrma
operatrnn belirttii ynde kaydrlmaktadr.
Sola kaydrma, belirtilen deyerin iindeki tm bitlerin bir bit sola kaydrlmasna ve sa
taraftan bir sfr bitinin eklenmesine neden olur. Saa kaydrma, tm bitlerin bir bit saa
kaydrlmasna neden olur. aretsiz bir deerin saa kaydrlmas sz konusu olduunda,
soldan bir sfr biti eklenir. aretli bir deerin saa kaydrlmas durumunda ise, iaret biti
korunur. Hatrlarsanz, negatif saylar, tamsay deerin st biti 1 yaplarak simgelenir. Yani,
kaydrlmakta olan deer negatifse, her saa kaydrma ilemi soldan bir 1 biti ekler. Eer deer
pozitifse, her saa kaydrma ilemi soldan bir 0 ekler.
Saa ve sola kaydrma ilemlerinin her ikisinde de, kaydrlp karlan bitler yitirilir.
Bylece, kaydrmak dndrmek (rotate) demek deildir; kaydrlp karlan biti geri
kazanmann hi bir yolu yoktur.
imdi, sola ve saa kaydrma ilemlerinin etkisini grafiksel olarak gz nnde canlandran
bir program inceleyelim. ncelikle, bir tamsayya ilk deer olarak 1 verilmektedir; yani bu,
saynn alt biti 1 olarak ayarlanyor demektir. Sonra, tamsay zerinde sekiz adet kaydrma i-
lemi gerekletirilmektedir. Her kaydrmadan sonra, saynn alt sekiz biti gsterilmektedir Daha
sonra, sekizinci bit konumuna yerletirilen bir 1 biti haricinde, bu ilemler tekrarlanr ve saa
kaydrmalar gerekletirilir.
// << ve >> kaydirma operatorlerini tanitir.

using System;

class ShiftDemo {
public static void Main() {
int val = 1;
int t;
int i;
for(i = 0; i < 8; i++) {
for(t = 128; t > 0; t = t/2) {
if((val & t) != 0) Console.Write(1 );
if((val & t) == 0) Console.Write(0 );
}
Console.WriteLine();
val = val << 1; // sola kaydir
}
Console.WriteLine();

val = 128;
for(i = 0; i < 8; i++) {
for(t = 128; t > 0; t = t/2) {
if((val & t) != 0) Console.Write(1 );
if((val & t) == 0) Console.Write(0 );
}
Console.WriteLine();
val = val >> 1; // saga kaydir
}

HERKES N C#
KISIM I C# DL

96
}
}
Programn kts aada gsterilmitir:
0 0 0 0 0 0 0 1
0 0 0 0 0 0 1 0
0 0 0 0 0 1 0 0
0 0 0 0 1 0 0 0
0 0 0 1 0 0 0 0
0 0 1 0 0 0 0 0
0 1 0 0 0 0 0 0
1 0 0 0 0 0 0 0

1 0 0 0 0 0 0 0
0 1 0 0 0 0 0 0
0 0 1 0 0 0 0 0
0 0 0 1 0 0 0 0
0 0 0 0 1 0 0 0
0 0 0 0 0 1 0 0
0 0 0 0 0 0 1 0
0 0 0 0 0 0 0 1
kili dzen, 2nin kuvvetlerine dayand iin kaydrma operatrleri, bir tamsayy ok hzl
bir biimde 2ye blmek veya 2 ile arpmak amacyla kullanlabilecek bir yntemdir. Sola kay-
drma, sayy ikiyle arpar. Saa kaydrma, sayy ikiye bler. Elbette bu ilem, bitleri bir utan
veya dierinden dar kaydrp, yitirmediiniz mddete ie yarar. te bir rnek:
// 2 ile carpmak ve 2ye bolmek icin kaydirma operatorlerini
kullanir.

using System;

class MultDiv {
public static void Main() {
int n;

n = 10;

Console.WriteLine(Value of n: + n);

// 2 ile carp
n = n << 1;
Console.WriteLine(Value of n after n = n * 2: + n);

// 4 ile carp
n = n << 2;
Console.WriteLine(Value of n after n = n * 4: + n);

// 2'ye bol
n = n >> 1;
Console.WriteLine(Value of n after n = n / 2: + n);

// 4'e bol
n = n >> 2;
BLM 4: OPERATRLER

HERKES N C#
97
Console.WriteLine(Value of n after n = n / 4: + n);
Console.WriteLine();

// ne yeni deger ata
n = 10;
Console.WriteLine(Value of n: + n);

// 30 kez 2 ile carp
n = n << 30; // data is lost
Console.WriteLine(Value of n after left-shifting 30
places: + n);
}
}
kt aada gsterilmitir;
Value of n: 10
Value of n after n = n * 2: 20
Value of n after n = n * 4: 80
Value of n after n = n / 2: 40
value of n after n = n / 4: 10

Value of n: 10
Value of n after left-shifting 30 places: -2147483648
ktnn son satrna dikkat edin. 10 says 30 kez sola kaydrldnda (yani, say 2
30
ile
arpldnda), bilgi kayb olur; nk, bitler intin deer aralndan darya kaydrlmtr.
Bu durumda elde edilen anlamsz (garbage) deer negatiftir, nk st bite 1 kaydrlmtr. Bu
bit iaret biti olarak kullanld iin, saynn negatif olarak yorumlanmasna neden olur. Bu,
kaydrma operatrlerini 2 ile arpma veya 2ye blme ilemlerinde kullanrken neden dikkatli
olmanz gerektiini gz nne seriyor. (aretli ve iaretsiz veri tipleriyle ilgili aklamalar iin
Blm 3e bakn.)
Bit Tabanl Bileik Atamalar
Bit tabanl ikili operatrlerin tm bileik atama ifadelerinde kullanlabilir. rnein,
aadaki iki ifadenin her biri xe, kendisinin 127 ile XOR uygulanmasndan elde edilen deeri
atamaktadr:
x = x ^ 127;
x ^= 127;
? Operatr
C#n en etkileyici operatrlerinden biri ? operatrdr. ? operatr genellikle belirli
tipteki if-then-else ifadelerinin yerine kullanlr. ? operatrne l (ternary) operatr
denir, nk ? operatr adet operand gerektirir. ? operatrnn genel formu u ekildedir:
Deyim1 ? Deyim2 : Deyim3;

HERKES N C#
KISIM I C# DL

98
Burada Deyim1 bir bool deyimdir, Deyim2 ve Deyim3 de birer deyimdir. Deyim2 ve
Deyim3n tipleri ayn olmaldr. ki nokta iaretinin kullanmna ve konumuna dikkat edin.
Bir ? deyiminin deeri u ekilde belirlenir: Deyim1in deeri hesaplanr. Eer bu deer
doru ise, Deyim2 hesaplanr ve btn ? deyiminin deeri halini alr. Eer Deyim1 yanl ise,
Deyim3 hesaplanr ve bunun deeri btn deyimin deeri olur. Aadaki rnei ele aln.
Burada absvale valin mutlak deeri atanmaktadr.
absval = val < 0 ? val : val; // valin mutlak degerini bul
Bu rnekte, eer val sfr veya sfrdan byk ise valin deeri absvale atanacaktr.
Eer val negatif ise, absvale bu deerin negatifi (ki, bu pozitif bir deer retir) atanacaktr.
Aada, ? operatrne bir baka rnek daha grlyor. Bu program iki sayy bler, ama
sfra blmeye izin vermez.
// ? kullanarak sifira bolmeyi onler.

using System;

class NoZeroDiv {
public static void Main() {
int result;
int i;
for(i = -5; i < 6; i++) {
result = i != 0 ? 100 / i : 0;
if(i != 0)
Console.WriteLine(100 / + i + is + result);
}
}
}
Bu programn kts aadaki gibidir;
100 / -5 is -20
100 / -4 is -25
100 / -3 is -33
100 / -2 is -50
100 / -1 is -100
100 / 1 is 100
100 / 2 is 50
100 / 3 is 33
100 / 4 is 25
100 / 5 is 20
Programdaki u satra dikkat edin:
result = i != 0 ? 100 / i : 0;
Burada, resulta 100n i ile blnmesiyle elde edilen sonu atanmaktadr. Ancak, bu
blme ilemi yalnzca i sfrdan farkl olduunda gereklenmektedir. i sfr olduunda,
resulta bir yer tutucu deer olarak sfr deeri atanr.
BLM 4: OPERATRLER

HERKES N C#
99
Aslnda, ? ile elde edilen deeri herhangi bir degikene atamak zorunda deilsiniz.
rnein, bu deeri, bir metoda yaplan arya argman olarak kullanabilirsiniz. Ya da, eer
deyimlerin tm bool tipinde ise ?, bir dng veya if ifadesinde koul deyimi olarak
kullanlabilir. Sz gelii, gelin imdi, nceki programn biraz daha verimli biimde yeniden
yazlm versiyonuna gz atalm. Bu program nceki ile ayn kty retmektedir.
// Prevent a division by zero usng the ?.

using System;

class NoZeroDiv2 {
public static void Main() {
int i;

for(i = -5; i < 6; i++)
if(i != 0 ? true : false)
Console.WriteLine(100 / + i + is + 100 / i);
}
}
if ifadesine dikkat edin, i sfr ise, ifin sonucu yanltr, sfra blme ilemi nlenir ve
hibir sonu ekranda gsterilmez. Aksi halde, blme ilemi gerekletirilir.

Boluklar ve Parantezler
C#nta bir deyim, sekmeler ve boluk karakterleri iererek daha okunakl hale getirilebilir,
rnein, aadaki iki deyim ayndr, fakat ikincisini okumak daha kolaydr:
x=10/y*(127/x);
x = 10 / y * (127/*);
Parantezler, tpk cebirdeki gibi, ierdikleri ilemlerin nceliini artrrlar. Gereksiz ve
ave parantez kullanm hataya neden olmaz ya da sz konusu deyimin almasn
yavalatmaz. Hesaplamann doru srasn netletirmek amacyla hem kendiniz, hem de
programnz daha sonra anlamak zorunda kalabilecek dier kiiler iin, parantez kullanmanz
tavsiye edilir. rnein, aadaki iki deyimden hangisini okumak daha kolaydr?
i
x = y/3-34*temp+127;
x = (y/3) - (34*temp) * 127;
Operatrlerin ncelik Sras
Tablo 4.2, tm C# operatrleri iin en yksekten en de doru ncelik srasn
gstermektedir. Bu tablo, bu kitapta daha sonra ele alnacak olan birka operatr de
iermektedir.

HERKES N C#
KISIM I C# DL

100
TABLO 4.2: Operatrlerin ncelik Sras


En yksek
() []
.
++
(sonek)
--
(sonek)
checked new sizeof typeof unchecked
! ~
(tip
atamas)
+(tekli) -(tekli)
++
(nek)
--
(nek)

* / %
+ -
<< >>
< > <= >= is
== !=
&
^
|
&&
||
?:
= op=
En dk





B E N C B L M

PROGRAM KONTROL
FADELER




















HERKES N C#
KISIM I C# DL

102
Bu blmde, C#n program kontrol ifadeleri ele alnyor. Program kontrol ifadeleri
kategoride toplanr: seme ifadeleri, if ve switch ifadeleridir; iterasyon ifadeleri, for,
while, do-while ve foreach dnglerinden oluur; atlama ifadeleri, break, continue,
goto, return ve throwu ierir. C#n kural d durum yrtme mekanizmasnn bir paras
olan ve Blm 13te ele alnan throwun haricindekiler burada incelenmektedir.
if fadesi
Blm 2'de if ifadesi tantlmt. Burada ayrntl olarak incelenmektedir. if ifadesinin
tamamlanm ekli yledir:
if (koul) ifade;
else ifade;
Burada if ve elsein hedefleri tek bir ifadedir, else ksm istee baldr. if ve elsein
her ikisinin de hedefleri ifade bloklar olabilir. fade bloklarnn kullanld if ifadesinin genel
formu u ekildedir:
if (koul)
{
ifade sekans
}
else
{
ifade sekans
}
Koul deyimi doru ise, ifin hedefi gereklenir; aksi halde, ifden klrsa elsein
hedefi gereklenir. Hibir zaman her ikisi ayn anda gereklenmez. ifi kontrol eden koul
deyimi bir bool sonu retmelidir.
te, bir saynn pozitif veya negatif olduunu bildirmek amacyla if ve else ifadesi
kullanan basit bir rnek:
// Bir degerin pozitif veya negatif olup olmadigini belirler.

using System;

class PosNeg {
public static void Main() {
int i;

for(i = -5; i <= 5; i++) {
Console.Write(Testing + i + : );

if(i < 0) Console.WriteLine(negative);
else Console.WriteLine(positive);
}
}
}
BLM 5: PROGRAM KONTROL FADELER

HERKES N C#
103
kt aada gsterilmitir:
Testing -5: negative
Testing -4: negative
Testing -3: negative
Testing -2: negative
Testing -1: negative
Testing 0: positive
Testing 1: positive
Testing 2: positive
Testing 3: positive
Testing 4: positive
Testing 5: positive
Bu rnekte, i sfrdan kkse ifin hedefi gereklenir. Aksi halde, elsein hedefi
gereklenir. Her ikisinin ayn anda gereklenmesi asla sz konusu olamaz.
Kmelenmi ifler
Kmelenmi if (nested if), bir baka if veya elsein hedefi olan bir if ifadesidir.
Kmelenmi ifler, programlamada ok yaygn olarak kullanlr. C#taki kmelenmi iflerle
ilgili hatrlamanz gereken balca konu, bir else ifadesinin her zaman kendisiyle ayn blokta
yer alan ve bir else ile ilikilendirilmemi en yakn if ifadesine ait olduudur. te bir rnek:
if (i == 10) {
if (j < 20) a = b;
if (k > 100) c = d;
else a = c; // bu else, if (k > 100)'a aittir
}
else a = d; // bu else, if (i == 10)'a aittir
Aklamalarn da gsterdii gibi, en son else, if(j<20) ile ilikili deildir (elsei
olmayan en yakn if bu olmasna ramen), nk ayn blokta deildir. Daha dorusu, en son
else, if(i==10) ile ilikilidir. teki else ise if(k>l00)e aittir, nk ayn blok iindeki
en yakn if budur.
Aadaki programda bir i ie if ifadesi gsteriliyor. nceki pozitif/negatif programnda
sfr, pozitif olarak belirtilmektedir. Ancak, baz uygulamalarda sfr, iaretsiz olarak dikkate
alnr. Sz konusu programn aada yer alan versiyonunda sfr ne pozitif ne de negatif olarak
ele alnmaktadr.
/* Bir degerin pozitif, negatif veya sifir olup olmadigini
belirler. */

using System;

class PosNegZero {
public static void Main() {
int i;

for(i = -5; i <= 5; i++) {

HERKES N C#
KISIM I C# DL

104
Console.Write(Testing + i + : );

if(i < 0) Console.WriteLine(negative);
else if(i == 0) Console.WriteLine(no sign);
else Console.WriteLine(positive);
}
}
}
te kt:
Testing -5: negative
Testing -4: negative
Testing -3: negative
Testing -2: negative
Testing -1: negative
Testing 0; no sign
Testing 1: positive
Testing 2; positive
Testing 3: positive
Testing 4; positive
Testing 5: positive
if-else-if Merdiveni
Kmelenmi ife dayanan ok yaygn bir programlama zellii if-else-if
merdivenidir. Bu, u ekilde grnr;
if (koul)
ifade;
else if (koul)
ifade;
else if (koul)
ifade;
.
.
.
else
ifade;
Koul deyimleri yukardan aaya doru gereklenir. Doru bir koul ile karlar
karlamaz, bu koulla ilikili ifade gereklenir ve merdivenin geri kalan ksm dikkate
alnmaz. Koullarn hibiri doru deilse, bu durumda en son else ifadesi gereklenecektir. En
son else genellikle, varsaylan koul olarak davranr Yani, dier koul testlerinin tm
baarsz olursa, en son else ifadesi gereklenir. Eer en son else ifadesi mevcut deilse ve
dier koullarn tm yanl ise, bu durumda hibir ilem gerekletirilmez.
Aadaki program if-else-if merdivenini gsteriyor. Program, belirli bir deer iin
(lden farkl) en kk tek basamakl arpan buluyor.
// En kucuk tek basamakl carpani bulur.

using System;
BLM 5: PROGRAM KONTROL FADELER

HERKES N C#
105

class Ladder {
public static void Main() {
int num;

for(num = 2; num < 12; num++) {
if((num % 2) == 0)
Console.WriteLine(Smallest factor of + num +
is 2.);
else if((num % 3) == 0)
Console.WriteLine(Smallest factor of + num +
is 3.);
else if((num % 5) == 0)
Console.WriteLine(Smallest factor of + num +
is 5.);
else if((num % 7) == 0)
ConsoLe.WriteLine(Smallest factor of + num +
is 7. );
else
Console.WriteLine(num + " is not divisible by
2, 3, 5, or 7.);
}
}
}
Program, aadaki kty retmektedir:
Smallest factor of 2 is 2.
Smallest factor of 3 is 3.
Smallest factor of 4 is 2.
Smallest factor of 5 is 5.
Smallest factor of 6 is 2.
Smallest factor of 7 is 7.
Smallest factor of 8 is 2.
Smallest factor of 9 is 3.
Smallest factor of 10 is 2.
11 is not divisible by 2, 3, 5, or 7.
Grdnz gibi, varsaylan else, yalnzca nceki if ifadelerinden hibiri baarl
olmad takdirde gereklenir.
switch fadesi
C#n seme ifadelerinden ikincisi switchdir. switch, ok yollu dallanma salar.
Bylece switch, programn birka alternatif arasndan seim yapmasn mmkn klar. Bir
dizi kmelenmi if ifadeleri de ok yollu testler gerekletirebilir olsa da, birok durum iin
switch ok daha verimli bir yntemdir. switch u ekilde alr: Bir deyimin deeri,
sabitlerden oluan bir listede pe pee test edilir. Deyimin deeri sabitlerden biriyle elenince,
bu elemeyle ilikili ifade sekans gereklenir. switch ifadesinin genel olarak formu yledir:
switch(deyim) {
case sabit1:

HERKES N C#
KISIM I C# DL

106
ifade sekans
break;
case sabit2:
ifade sekans
break;
case sabit3:
ifade sekans
break;
.
.
.
default:
ifade sekans
break;
}
switch deyimi bir tamsay tipinde, rnein, char, byte, short veya int, ya da string
tipinde (bu kitapta daha sonra ele alnmaktadr) olmaldr. Bylece sz gelii, kayan noktal de-
yimlere izin verilmemektedir. Sk sk switchi kontrol eden deyim tek bir deikenden
ibarettir. case sabitleri deyim ile uyumlu tipte lileraller olmaldr. Ayn switch iinde
herhangi iki case sabiti ayn deerlere sahip olamaz.
default ifade sekans, case sabitlerinden hibiri deyim ile elenmediinde altrlr.
default istee baldr; default mevcut deilse, elemelerin tm baarsz olduunda
hibir ilem yaplmaz. Bir eleme bulunduunda, bu case ile ilikili ifadeler breake
rastlayana kadar altrlr.
Aadaki program switchi gstermektedir:
// switch'i tanitir.

using System;

class SwitchDemo {
public static void Main() {
int i;

for(i=0; i<10; i++)
switch(i) {
case 0:
Console.WriteLine(i is zero);
break;
case 1:
Console.WriteLine(i is one);
break;
case 2:
Console.WriteLine(i is two);
break;
case 3:
Console.WriteLine(i is three);
break;
case 4:
Console.WriteLine(i is four);
BLM 5: PROGRAM KONTROL FADELER

HERKES N C#
107
break;
default:
Console.WriteLine(i is five or more);
break;
}
}
}
Bu programn rettii kt aadaki gibidir:
i is zero
i is one
i is two
i is three
i is four
i is five or more
i is five or more
i is five or more
i is five or more
i is five or more
Grdnz gibi, dngnn her tekrarnda i ile eleen case sabiti ile ilikili ifadeler
gereklenir. Dierlerinin hibiri dikkate alnmaz. i, be veya daha byk olursa case
sabitlerinden hibiri elenmez; bu nedenle, default ifadesi gereklenir.
nceki rnekte switch, bir int deiken ile kontrol ediliyordu. nceden akland gibi,
switchi char da dahil olmak zere herhangi bir tamsay tipi ile kontrol edebilirsiniz. te,
char deyimi ve char case sabitleri kullanan bir rnek:
// switchi kontrol etmek icin bir char kullanir.

using System;

class SwitchDemo2 {
public static void Main() {
char ch;

for(ch = A; ch <= E; ch++)
switch(ch) {
case A:
Console.writeLine(ch is A);
break;
case B:
Console.writeLine(ch is B);
break;
case C:
Console.WriteLine(ch is C");
break;
case D:
Console.WriteLine(ch is D);
break;
case E:
Console.WriteLine(ch is E);
break;

HERKES N C#
KISIM I C# DL

108
}
}
}
Bu programn kts aada gsterilmitir:
ch is A
ch is B
ch is C
ch is D
ch is E
Dikkat ederseniz, bu rnekte default ifadesi yer almyor. defaultun istee bal
olduunu hatrnzdan karmayn, Gerekmiyorsa, default koda dahil edilmeyebilir.
C#ta bir case ile ilikili ifade sekansnn bir sonraki case iinde devam etmesi hataldr.
Buna bir sonraki seenee kaymama (no fall-through) kural denir. case ifadelerinin break
ifadesi ile sona ermesinin nedeni budur. (Bir sonraki seenee kayma durumunu dier
yntemlerle de, rnein bu blmde daha sonra ele alnacak bir konu olan gotolarla da
nleyebilirsiniz; ancak, break ak farkla en yaygn olarak kullanlan bir yntemdir.) Bir
casein ifade sekans iinde breakle karlanca break ifadesi, program aknn switch
ifadesinin btnn terk etmesine ve switchin dnda kalan bir sonraki ifadeden devam
etmesine neden olur. default ifadesi de ayrca bir sonraki seenee kaymamal ve genellikle
break ile sona ermelidir.
Bir sonraki seenee kaymama kural C#; C, C++ ve Javadan ayran hususlardan
biridir. Bu dillerde bir case, peinden gelen case zerinden devam edebilir (yani, bir sonraki
seenee kayabilir fall-through). C#ta caseler iin bir sonraki seenee kaymama
kural gelitirilmesinin iki nedeni vardr. ncelikle, bu sayede derleyicinin case ifadelerini,
belki de optimizasyon amal olarak, serbeste sralamasna imkan verilir. Eer bir case,
kendisinden sonra gelen case iinde devam ediyor olsayd, bu tr bir yeniden dzenleme
mmkn olmayacakt. kincisi, her casein aka sona ermesini gerekli klmak programclarn
kazara bir casein kendisinden sonra gelen case iinde devam etmesine imkan vermelerine de
engel olur.
Bir case sekansnn bir dieri iinde devam etmesine imkan veremiyor olmanza ramen,
aadaki rnekte gsterildii gibi iki veya daha fazla case ifadesinin ayn kod sekansn
iermesini salayabilirsiniz:
// Bos caseler bir sonraki case icinde devam edebilir.

using System;

class EmptyCasesCanFall {
public static void Main() {
int i;

for(i = 1; i < 5; i++)
switch(i) {
BLM 5: PROGRAM KONTROL FADELER

HERKES N C#
109
case 1:
case 2:
case 3: Console.WriteLine(i is 1, 2 or 3);
break;
case 4: Console.WriteLine(i is 4);
break;
}
}
}
kt aada gsterilmitir:
i is 1, 2 or 3
i is 1, 2 or 3
i is 1, 2 or 3
i is 4
Bu rnekte, eer i 1, 2 veya 3 deerine sahipse, ilk WriteLine() ifadesi altrlr. i, 4
ise ikinci WriteLine() ifadesi altrlr, caselerin st ste ylmas bir sonraki seenee
kaymama kuraln inemez, nk case ifadelerinin tm ayn ifade sekansn
kullanmaktadr.
Birka case ifadesinin ortak bir kodu paylat durumda case ifadelerini st ste ymak
ska kullanlan bir tekniktir. Bu teknik, kod sekansnn gereksiz yere tekrarlanmasn nler.
Kmelenmi switch fadeleri
Bir switchi dtaki bir switchin ifade sekansnn bir paras olarak kullanmak
mmkndr. Buna kmelenmi switch (nested switch) denir. teki ve dtaki switchlerin
case sabitleri ortak deerler ierebilir; bu durumda hibir karklk ortaya kmayacaktr.
rnein, aadaki kod paralar tamamen kabul edilebilir:
switch(ch1) {
case A: Console.WriteLine(This A is part of outer switch);
switch(ch2) {
case A:
Console.WriteLine(This A is part of inner switch);
break;
case B: // ...
} // icteki switch'in sonu
break;
case B: // ...
for Dngs
Blm 2den beri for dngsnn basit bir formunu kullanmaktasnz. Bu blmde for
dngs ayrntl alarak incelenmektedir. for dngsnn ne kadar gl ve esnek olduuna
aracaksnz. Gelin simdi, forun en alldk formlarndan balayarak, temel kavramlar
tekrarlayarak balayalm.

HERKES N C#
KISIM I C# DL

110
Tek bir ifadeyi tekrarlamak iin kullanlan for dngsnn genel formu su ekildedir:
for(balang; koul; iterasyon) ifade;
Tekrarlanan bir blok iin genel form u ekildedir:
for(balang; koul; iterasyon)
{
ifade sekans
}
balang genellikle, dng kontrol deikenine ilk deerini veren bir atama ifadesidir.
Dng kontrol deikeni, dngy kontrol eden bir saya gibi davranr. koul, dngnn
tekrarlanp tekrarlanmayacan belirleyen bool tipinde bir deyimdir. iterasyon deyimi,
dngnn her tekrarlannda dng kontrol deikeninin ne lde deitirileceini tanmlar.
Dngnn bu ana blmnn noktal virgl ile birbirinden ayrldna dikkat edin. for
dngs, koul testi baarl olduu srece almaya devam edecektir. Koul yanl olduu
andan itibaren dngden kacaktr ve program almasna foru takip eden ifadeden
balayarak devam edecektir,
for dngs pozitif veya negatif biimde ilerleyebilir; dng, dng kontrol deikenini
herhangi bir lde deitirebilir. rnein, aadaki program 100 ile -100 arasndaki saylar
5er 5er azaltarak yazdrr:
// Negatif olarak tekrarlayan dongu.

using System;

class DecrFor {
public static void Main() {
int x;

for(x = 100; x > -100; x -= 5)
Console.WriteLine(x);
}
}
for dngleriyle ilgili nemli bir husus, koul deyiminin her zaman dngnn en banda
test edildiidir. Bu, dngye balarken deyimin deeri yanl ise dngnn iindeki kod hi
altrlmayabilir, demektir. te bir rnek:
for(count = 10; count < 5; count++)
x += count; // bu ifade calistirilmayacaktir
Bu dng asla almayacaktr, nk dngye balarken dng kontrol deikeni olan
count, 5ten byktr. Bu, koul deyiminin (count < 5) balangta yanl olmasna neden
olur; bylece, dngnn bir kez bile iterasyonu sz konusu olmaz.
for dngs en ok, iterasyonlarn bilinen sayda yaplaca durumlarda kullanldr.
rnein, aadaki program 2 ile 20 arasndaki asal saylan bulmak iin iki for dngs
kullanmaktadr. Eer say asal deilse, saynn en byk arpan ekranda gsterilmektedir:
BLM 5: PROGRAM KONTROL FADELER

HERKES N C#
111
/*
Bir sayinin asal olup olmadigini belirler.
Sayi asal degilse, sayinin en buyuk carpanini gosterir.
*/

using System;

class FindPrimes {
public static void Main() {
int num;
int i;
int factor;
bool isprime;

for(num = 2; num < 20; num++) {
isprime = true;
factor = 0;

// num tam olarak bolunebilir mi?
for(i = 2; i <= num/2; i++) {
if((num % i) == 0) {
// num tam olarak bolunebilir - asal degil
isprime = false;
factor = i;
}
}

if(isprime)
Console.WriteLine(num + is prime.);
else
Console.WriteLine(Largest factor of + num + is
+ factor);
}
}
}
Programn kts aada gsterilmitir:
2 is prime.
3 is prime.
Largest factor of 4 is 2
5 is prime.
Largest factor of 6 is 3
7 is prime.
Largest factor of 8 is 4
Largest factor of 9 is 3
Largest factor of 10 is 5
11 is prime.
Largest factor of 12 is 6
13 is prime.
Largest factor of 14 is 7
Largest factor of 15 is 5
Largest factor of 16 is 8
17 is prime,
Largest factor of 18 is 9

HERKES N C#
KISIM I C# DL

112
19 is prime.
for Dngs zerinde Baz Varyasyonlar
for, C# dilindeki en ok ynl ifadelerden biridir, nk ok eitli varyasyonlara imkan
verir. Bu varyasyonlar burada incelenmektedir.
Birden Fazla Dng Kontrol Deikeni Kullanmak
for dngs, dngy kontrol etmek amacyla iki veya daha fazla deiken kullanmanza
imkan verir. Birden fazla dng kontrol deikeni kullanrken her deiken iin balang ve
artrma ifadeleri virgl ile birbirinden ayrlr. rnein:
// for ifadesi iinde virgul kullanir.

using System;

class Comma {
public static void Main() {
int i, j;

for(i = 0; j = 10; i < j; i++, j--)
Console.WriteLine(i and j: + i + + j);
}
}
Programn kts aada gsterilmitir:
i and j: 0 10
i and j: 1 9
i and j: 2 8
i and j: 3 7
i and j: 4 6
Burada virgller, iki balang ifadesini ve iki iterasyon deyimini ayrmaktadr.
Dng baladnda i ve jnin her ikisine de ilk deer atanr. Dngnn her tekrarlannda i
bir artrlr, j bir azaltlr. Birden fazla dng kontrol deikeninden yararlanmak, genellikle
kullanl bir yntemdir. Bu sayede belirli algoritmalar kolaylatrlabilir. Herhangi bir sayda
balang ve iterasyon ifadelerine sahip olabilirsiniz; fakat, pratikte ikiden fazlas for
dngsn hantallatrr.
te, bir for ifadesi iinde ok sayda dng kontrol deikeninin pratik kullanmna bir
rnek. Bu program, bir saynn (bu rnekte 100n) en byk ve en kk arpann bulmak
amacyla tek bir for dngs iinde iki dng kontrol deikeni kullanmaktadr. Dngy
sonlandran koula zellikle dikkat edin. Bu, her iki dng deikenine de dayanmaktadr.
/*
Bir sayinin en buyuk ve en kucuk carpanini bulmak icin for
ifadesi icinde virgul kullanir.
*/

BLM 5: PROGRAM KONTROL FADELER

HERKES N C#
113
using System;

class Comma {
public static void Main() {
int i, j;
int smallest, largest;
int num;

num = 100;

smallest = largest = 1;

for(i = 2, j = num/2; (i <= num/2) & (j >= 2); i++, j--) {

if((smallest == 1) & ((num % i) == 0))
smallest = i;

if((largest == 1) & ((num % j) == 0))
largest = j;

}

Console.WriteLine(Largest factor: + largest);
Console.WriteLine(Smallest factor: + smallest);
}
}
Programn kts yledir:
Largest factor: 50
Smallest factor: 2
ki dng kontrol deikeninin kullanlmas sayesinde tek bir for dngs, bir saynn
hem en kk hem de en byk arpann bulabilir. En kk deeri aramak iin i kontrol
deikeni kullanlmaktadr. iye ncelikle 2 deeri atanr ve inin deeri, numn yarsn aana
kadar i artrlr. j kontrol deikeni en byk arpan bulmak iin kullanlr. jnin deeri
balangta numn yarsna eit olacak ekilde ayarlanr ve 2den kk olana kadar azaltlr.
Dng, i ve jnin her ikisi de son deerine ulaana kadar tekrarlamay srdrr. Dng sona
erdiinde, her iki arpan da bulunmu olacaktr.
Koul Deyimi
Bir for dngsn kontrol eden koul deyimi, bir bool sonu reten herhangi bir geerli
deyim olabilir. Koul deyimi, dng kontrol deikenini iermek zorunda deildir. rnein, bir
sonraki programda for dngs, done deeri ile kontrol edilmektedir.
// Dongu kosulu herhangi bir bool deyim olabilir.

using System;

class forDemo {
public static void Main() {

HERKES N C#
KISIM I C# DL

114
int i, j;
bool done = false;

for(i = 0, j = 100; !done; i++, j--) {

if(i * i >= j) done = true;

Console.WriteLine(i, j: + i + + j);
}
}
}
kt aada gsterilmitir:
i, j: 0 100
i, j: 1 99
i, j: 2 98
i, j: 3 97
i, j: 4 96
i, j: 5 95
i, j: 6 94
i, j: 7 93
i, j: 8 92
i, j: 9 91
i, j: 10 90
Bu rnekte, for dngs bool deikeni olan done doru olana kadar tekrarlanr. Bu
deiken, dng iinde inin karesi jden byk veya jye eit olduunda doru deerine
ular.
Eksik Paralar
Baz enteresan for dngs varyasyonlar, dng tanmndaki baz paralar bo brakarak
elde edilebilir. C#ta for dngsnn balang, koul ve iterasyon paralarndan herhangi
birinin veya bu paralarn tmnn bo braklmas mmkndr. rnein, aadaki program
ele aln:
// for'un bazi parcalar bos olabilir.

using System;

class Empty {
public static void Main() {
int i;

for(i = 0; i < 10; ) {
Console.WriteLine(Pass # + i);
i++; // dongu kontrol degiskenini artir
}
}
}
BLM 5: PROGRAM KONTROL FADELER

HERKES N C#
115
Bu rnekte, forun iterasyon deyimi bo braklmtr. Bunun yerine, dng kontrol dei-
keni olan i, dng gvdesi iinde artrlmaktadr. Bu, dngnn her tekrarlannda inin 10a
eit olup olmadn grmek iin i test edilir, fakat bundan baka hibir ilem gerekletirilmez
demektir. Elbette, i dng gvdesi iinde artrld iin, dng normal ekilde almakta ve
aadaki kty ekranda gstermektedir:
Pass #0
Pass #1
Pass #2
Pass #3
Pass #4
Pass #5
Pass #6
Pass #7
Pass #8
Pass #9
Bir sonraki rnekte, balang blm de fordan karlmtr:
// for dongusunden biraz daha parca cikaralim.

using System;

class Empty2 {
public static void Main() {
int i;

i = O; // baslangici donguden cikart
for(; i < 10; ) {
Console.WriteLine(Pass # + i);
i++; // dongu kontrol degiskenini artir
}
}
}
Bu versiyonda iye dngnn bir paras olarak deil, dng balamadan ilk deer
atanyor. Normalde dng kontrol deikenine forun iinde ilk deer vermeyi tercih
edeceksiniz. Balangc dngnn dna yerletirmek, genellikle ilk deerin for ifadesi iine
katlamayacak kadar karmak bir ilem neticesinde elde edildii durumlarda kullanlr.
Sonsuz Dng
Koul deyimi bo braklan bir for dngs kullanarak sonsuz dng (asla sona ermeyen
dng) hazrlayabilirsiniz. rnein, aadaki program paras birok C# programcsnn
sonsuz dng oluturmak iin kulland bir yntemi gstermektedir:
for(;;) // Kasitli olarak hazirlanan bir sonsuz dongu

// ...
}

HERKES N C#
KISIM I C# DL

116
Bu dng sonsuza kadar alacaktr. Sonsuz dng gerektiren baz programlama grevleri
olmasna ramen, sz gelii, iietim sistemi komut ilemcileri gibi sonsuz dnglerin
birou, aslnda zel sonlandrma artna sahip dnglerden ibarettir. Bu blmn sonlarna
doru bu tr bir dngy nasl durduracanz reneceksiniz. (pucu: Bu ilem, break ifadesi
kullanlarak gerekletirilmektedir.)
Gvdesiz Dngler
C#ta for dngsyle (veya bir baka dng ile) ilikili gvde bo olabilir. Bunun nedeni,
null ifadenin (null statement) sz diziimsel adan geerli olmasdr. Gvdesiz dngler sk sk
ie yarar. rnein, aadaki program 1 ile 5 arasndaki saylarn toplamn bulmak iin
gvdesiz bir dng kullanmaktadr:
// Dongunun govdesi bos olabilir.

using System;

class Empty3 {
public static void Main() {
int i;
int sum = 0;

// 5'e kadar sayilari topla
for(i = 1; i <= 5; sum += i++) ;

Console.WriteLine(Sum is + sum);
}
}
Programn kts aadaki gibidir;
Sum is 15
Dikkat ederseniz, toplama ilemi btnyle for ifadesi iinde ele alnmaktadr ve dng
gvdesine hi gerek yoktur. terasyon deyimine zellikle dikkat edin:
sum += i++;
Bu tr ifadeler gznz korkutmasn. Bunlar, profesyonelce yazlm C# programlarnda
ska kullanlr ve ifadeyi paralara ayrrsanz anlalmas kolaydr. Baka bir deyile, bu ifade,
suma sum art inin deerini ekle, sonra iyi artr, demektedir. Yani bu, aadaki ifade
sekans ile ayndr:
sum = sum + i;
i++;
Dng Kontrol Deikenlerini for Dngs inde Deklare etmek
Genellikle bir for dngsn kontrol eden deikene yalnzca dngnn amalar
dorultusunda ihtiya vardr, geri kalan blmlerde bu deiken kullanlmaz. Byle bir durum
BLM 5: PROGRAM KONTROL FADELER

HERKES N C#
117
sz konusu olduunda deikeni, forun balang blm iinde deklare etmek mmkndr.
rnein, aadaki program 1 ile 5 arasndaki saylarn hem toplamn hem de faktriyelini
hesaplamaktadr. Program, dng kontrol deikeni olan iyi forun iinde deklare
etmektedir:
// Dongu kontrol degiskenini for icinde deklare et.

using Systam;

class ForVar {
public static void Main() {
int sum = 0;
int fact = 1;

// 5e kadar sayilarin faktoriyelini hesapla
for (int i = 1; i <= 5; i++) {
sum += i; // i dongu boyunca taniniyor
fact *= i;
}

// fakat i burada taninmiyor.

Console.WriteLine(Sum is + sum);
Console.WriteLine(Factorial is + fact);
}
}
Bir deikeni bir for dngs iinde deklare ettiiniz zaman hatrnzda tutmanz gereken
bir husus vardr: Bu deikenin kapsam for ifadesi sona erdiinde sonlanr. (Yani, deikenin
kapsam for dngs ile snrldr.) for dngs dnda, deikenin varl sona erecektir. Bu
nedenle, nceki rnekte i, for dngs dndan eriilememektedir. Dng kontrol
deikenini programn geri kalan blmlerinde kullanmanz gerekiyorsa, deikeni for
dngs iinde deklare etmeniz mmkn olmayacaktr.
Dier konulara gemeden nce, for dngs zerinde kendi rneklerinizle deneyim
kazanmak isteyebilirsiniz. Bunun etkileyici bir ifade olduunu siz de kefedeceksiniz.
while Dngs
C#ta mevcut bir baka dng ise whiledr. while dngs genel olarak u ekildedir:
While (koul) ifade;
Burada ifade, tek bir ifade de olabilir, bir ifade blou da olabilir; koul ise dngy kontra
eden koulu tanmlar ve geerli herhangi bir Boolean deyim olabilir. fade, koul doru iken
gereklenir. Koul yanl deerini alrsa, program kontrol hemen dngy takip eden satra
geer.
te, bir tamsaynn basamak saysn hesaplamak iin while dngs kullanan basit bir
rnek.

HERKES N C#
KISIM I C# DL

118
// Bir tamsayinin basamak uzunlugunu hesaplar.

using System;

class WhileDemo {
public static void Main() {
int num;
int mag;

num = 435679;
mag = 0;

Console.WriteLine(Number: + num);

while(num > 0) {
mag++;
num = num / 10;
};

Console.WriteLine(Magnitude: + mag);
}
}
kt aada gsterilmitir:
Number: 435679
Magnitude: 6
while dngs u ekilde alr: numn deeri test edilir. Eer num, sfrdan bykse
mag sayac bir artrlr ve num, 10a blnr. numn deer 10dan byk olduu srece dng
tekrarlamaya devam eder. num, sfr olduunda dng sona erer ve mag, orijinal deerin
basamak saysn ierir.
for dngsnde olduu gibi, whileda da koul deyimi dngnn en banda kontrol
edilir. Bu, dng kodunun hi altrlmama ihtimali olduu anlamna gelir. Bu sayede,
dngden nce ayr bir test yapma gereklilii de ortadan kalkm olur. Aadaki program,
while dngsnn bu zelliini gz nnde canlandryor. Program, 2nin 0dan 9a kadar
olan tamsay kuvvetlerini hesaplamaktadr:
// 2'nin tamsayi kuvvetlerini hesaplar.

using System;

class Power {
public static void Main() {
int e;
int result;

for(int i=0; i < 10; i++) {
result = 1;
e = i;

while(e > 0) {
BLM 5: PROGRAM KONTROL FADELER

HERKES N C#
119
result *= 2;
e--;
}
Console.WriteLine(2 to the + i + power is +
result):
}
}
}
Programn kts aada gsterilmitir:
2 to the 0 power is 1
2 to the 1 power is 2
2 to the 2 power is 4
2 to the 3 power is 8
2 to the 4 pouer is 16
2 to the 5 power is 32
2 to the 6 power is 64
2 to the 7 power is 128
2 to the 8 power is 256
2 to the 9 power is 512
Dikkat ederseniz, while dngs, yalnzca e, 0dan byk olduunda almaktadr. By-
lece, e, sfr iken, for dngsnn ilk tekrarnda olduu gibi, while dngs atlanr.
do-while Dngs
nc C# dngs ise do-whiledr. Koulun dngnn en banda test edildii for ve
while, dnglerinden farkl olarak do-while dngs, koulu dngnn sonunda kontrol
eder. Bu, do-while dngsnn her zaman en az bir kez altrlaca anlamna gelir. do-
while dngsnn genel formu u ekildedir:
do {
ifadeler;
} while(koul);
Sadece tek bir ifade mevcut olduunda kme parantezleri gerekli olmasa da, do-while
dngsnn okunabilirligini artrmak amacyla kme parantezleri ounlukla kullanlmaktadr;
bylece, while ile doabilecek karklk da nlenmi olur. do-while dngs, koul ifadesi
doru olduu srece tekrarlamay srdrr.
Aadaki program, bir tamsaynn basamaklarn ters srada gstermek iin do-while
dngs kullanmaktadr:
// Bir tamsayinin basamaklarini ters sirada gosterir.

using System;

class DoWhileDemo {
public static void Main() {
int num;
int nextdigit;

HERKES N C#
KISIM I C# DL

120

num = 198;

Console.WriteLine(Number: + num);

Console.Write(Number in reverse order: );

do {
nextdigit = num % 10;
Console.Write(nextdigit);
num = num / 10;
} while(num > 0);

Console.WriteLine();
}
}
kt aada gsterilmitir:
Number: 198
Number in reverse order: 891
Dng u ekilde almaktadr. Dngnn her iterasyonunda en sadaki basamak,
tamsaynn 10 ile blnmesinden kalan bulunarak elde edilir. Bu basamak daha sonra ekranda
gsterilir. Sonra, numn deeri 10 ile blnr. Bu bir tamsay blmesi olduu iin blme, en
sadaki basaman saydan karlmasyla sonulanr Bu ilem num, sfr olana kadar
tekrarlanr.
foreach Dngs
foreach dngs bir koleksiyonun elemanlar zerinden tekrarlanr. Koleksiyon, bir grup
nesneden oluur. C#ta birka tip koleksiyon tanmldr. Bunlardan biri da dizidir. foreach
dngs, dizilerin ele alnd Blm 7de incelenmektedir.
Dngden kmak in break Kullanmak
break ifadesini kullanarak bir dngden annda kmaya zorlamak mmkndr. Bu
durumda, dngnn gvdesinde geriye kalan her trl kod ve dngnn koul testi pas
geilmi olur. Bir dngnn iinde bir break ifadesi ile karlalnca dng sona erer ve
program kontrol, dngy takip eden bir sonraki ifadeden devam eder. te basit bir rnek:
// Bir donguden cikmak icin break kullanr.

using System;

class BreakDemo {
public static void Main() {

// bu donguden cikmak icin break kullan
for(int i = -10; i <= 10; i++) {
if(i > 0) break; // i pozitif oldugunda donguye son ver
BLM 5: PROGRAM KONTROL FADELER

HERKES N C#
121
Console.Write(i + );
}
Console.WriteLine(Done);
}
}
Bu program aadaki kty retir;
-10 -9 -8 -7 -6 -5 -4 -3 -2 -1 0 Done
Grdnz gibi, for dngs -10dan 10a kadar alacak ekilde tasarlanm olsa da
break ifadesi dngnn daha erken, yani i pozitif olduunda sona ermesine neden olmaktadr.
break ifadesi, kastl sonsuz dngler de dahil olmak zere C#n herhangi bir dngs ile
kullanlabilir. rnein, nceki programn do-while dngs kullanlarak yeniden kodlanm
ekli yledir:
// do-while dongusunden cikmak icin break kullan.

using System;

class BreakDemo2 {
public static void Main() {
int i;

i = -10;
do {
if(i > 0) break;
Console.Write(i + );
i++;
}while(i <= 10);

Console.WriteLine(Done);
}
}
Aada, break ile ilgili daha pratik bir rnek gryorsunuz. Bu program, bir saynn en
kk arpann bulmaktadr:
// Bir degerin en kucuk carpanini bulur.

using System;

class FindSmallestFactor {
public static void Main() {
int factor = 1;
int num = 1000;

for(int i = 2; i < num/2; i++) {
if((num % i)== 0) {
factor = i;
break; // carpani bulunca donguyu durdur
}
Console.WriteLine(Smallest factor is + factor);

HERKES N C#
KISIM I C# DL

122
}
}
kt aada gsterilmitir:
Smallest factor is 2
arpan bulunur bulunmaz break, for dngsn durdurmaktadr. Bu durumda
break kullanmak, bir kez bir arpan bulunduktan sonra dngnn bir baka deer bulmaya
almasn nlemektedir. Bylece, verimsizlik de nlenmi olur.
break, bir takm kmelenmi dnglerin iinde kullanldnda, sadece en iteki
dngden k salar. rnein,
// Kumelenmis dongulerde break kullanmak.

using System;

class BreakNested {
public static void Main() {

for(int i = 0; i < 3; i++) {
Console.WriteLine(Outer loop count: + i);
Console.Write( Inner loop count: );

int t = 0;

while(t < 100) {
if(t == 10) break; // t, 10 olunca donguyu durdur
Console.Write(t + );
t++;
}
Console.WriteLine();
}
Console.WriteLine(Loops complete.);
}
}
Bu program aadaki kty retir:
Outer loop count: 0
Inner loop count: 0 1 2 3 4 5 6 7 8 9
Outer loop count: 1
Inner loop count: 0 1 2 3 4 5 6 7 8 9
Outer loop count: 2
Inner loop count: 0 1 2 3 4 5 6 7 8 9
Loops complete.
Grdnz gibi, iteki dngdeki break ifadesi yalnzca o dngnn sona ermesine
neden olur. Dtaki dng bu durumdan etkilenmez.
break hakknda hatrnzda tutmanz gereken dier iki husus ise yledir: ncelikle, bir
dng iinde birden fazla break ifadesi yer alabilir, fakat dikkatli olmalsnz. Ar sayda
break ifadesi kodunuzun yapsn bozma eilimindedir. kincisi, bir switch ifadesini
BLM 5: PROGRAM KONTROL FADELER

HERKES N C#
123
sonlandran break sadece switch ifadesini etkiler; breaki ieren dngler, sz konusu
breakden etkilenmez.
continue fadesini Kullanmak
Bir dngnn normal kontrol yapsn pas geerek, dngy erken iterasyona zorlamak
mmkndr. Bu, continue kullanlarak gerekletirilir. continue ifadesi, dngy bir
sonraki tekrarn gerekletirmeye zorlar, arada yer alan kod dikkate alnmaz. Yani continue,
esasen breakin tamamlaycsdr. rnein aadaki program, 0 ile 100 arasndaki ift
saylar yazdrmay kolaylatrmak iin continue ifadesini kullanmaktadr.





















HERKES N C#
KISIM I C# DL

124



























BLM 5: PROGRAM KONTROL FADELER

HERKES N C#
125








kural inenmi olmaz; break ifadesine de gerek yoktur. nceden akland gibi, bir
switchin iine atlamak iin goto kullanmak mmkn deildir. Aadaki satrn bandaki
aklama simgelerini kaldrrsanz program derlenmeyecektir:
// goto casel; // Hata! switch'in icine atlayamazsin.
Akas, gotoyu switch ile birlikte kullanmak baz zel durumlarda kullanl olabilir,
ama genel olarak nerilen bir stil deildir.
gotonun dzgn kullanmlarndan biri, derin biimde kmelenmi bir rutinden kmak
iindir. te basit bir rnek:
// goto'yu tanitir.

using System;

class Use_goto {
public static void Main() {
int i = 0, j = 0, k = 0;

for(i = 0; i < 10; i++) {
for(j = 0; j < 10; j++) {
for(k = 0; k < 10; k++} {
Console.WriteLine(i, j, k: + i + + j +
+ k);
f(k == 3) goto stop;
}
}
}

stop:
Console.WriteLine(Stopped! i, j, k: + i + , + j +
+ k);
}
}
Programn kts aada gsterilmitir:

HERKES N C#
KISIM I C# DL

126
i, j, k: 0 0 0
i, j, k: 0 0 1
i, j, k: 0 0 2
i, j, k: 0 0 3
Stopped! i, j, k: 0, 0 3
gotoyu kaldrmak, adet if ve break ifadesi kullanmay mecbur klar. Bu rnekte
goto, kodu basitletirmektedir. Bu, goto kullanmn gstermek amacyla kullanlmak zere
uydurulmu bir rnek olmakla birlikte, gotonun avantajl olabilecei durumlar muhtemelen
siz kendiniz de hayal edebilirsiniz.





A L T I N C I B L M

SINIFLARA, NESNELERE
VE METOTLARA GR




















HERKES N C#
KISIM I C# DL

128
Bu blmde snflar tantlyor. Snf, C#n zdr, nk snf, nesnenin doasn
tanmlar. Snf, btn bir C# dilinin rerine ina edildii bir temeldir. yle ki, snf, C#ta nesne
ynelimli programlamann esaslarn oluturur. Snf iinde veriler ve bu veriler zerinde ilem
yapan kod tanmlanr. Kod, rnetotlar iinde yer alr. Snf, nesne ve metotlar C#n belli bal
zellikleri olduu iin, bunlar bu blmde tanllmaktadr. Bu zellikleri esasl kavram olmak
daha sofistike programlar yazmanza ve sonraki blmlerde ele alnacak olan byk neme
sahip belirlj C# elerini de daha iyi anlamanza imkan verecektir.
Snflarn Temel zellikleri
Tm C# faaliyetleri bir snf iinde meydana geldii iin, aslnda bu kitabn bandan beri
snflar kullanmaktasnz. Elbette, imdiye kadar yalnzca son derece basit snflar kullandnz;
snflarn sahip olduu zelliklerinin byk ounluundan yararlanm deilsiniz. Snflarn u
ana dek tantlan kstl zellie sahip olanlardan ok daha gl olduklarna daha sonra ahit
olacaksnz.
Gelin, temel zellikleri tekrar ederek balayalm. Snf, bir nesnenin eklini tanmlayan bir
ablondur. Snf, hem verileri hem de bu veriler zerinde ilem yapacak kodu belirtir. C#ta
nesneleri tanmlamak iin bir snf spesifikasyonu kullanlmaktadr. Nesneler bir snfn
rnekleridir. Yani, snf esasen nesnelerin ne ekilde ina edileceini belirten birtakm
planlardan ibarettir. Bu noktada bir hususa aklk kazandrmamz gerekiyor: Snf, mantksal
bir soyutlamadr. Bir snfa ait bir nesne oluturulana kadar sz konusu snf bellekte fiziksel
olarak temsil edilmez.
Bir dier husus: Bir snf oluturan metot ve deikenlerin sz konusu snfn yeleri
olduklarn hatrnzdan karmayn.
Snfn Genel Biimi
Bir snf tanmladnzda bu snfn ierdii verileri ve bu verilerin zerinde ilem yapacak
kodu da deklare etmi olursunuz. ok basit snflarn yalnzca veri ya da yalnzca kod
iermeleri mmkn olsa da, gerek dnyaya ait snflarn pek ou her ikisini de ierir.
Genel olarak, veriler snf tarafndan tanmlanm rnek deikenlerde, kod ise metotlarda
saklanr. Ancak anlatma balarken, C#ta birka spesifik veri ve kod yesinin tanml olduunu
aklamak nemlidir. rnek deikenler, statik deikenler, sabitler, metotlar, yaplandrclar,
yok ediciler, indeksleyiciler, olaylar, operatrler ve zellikler bu kapsamda yer alr. imdilik,
snf ile ilgili anlatmmz snfn balca eleriyle snrl tutacaz: rnek deikenler ve
metotlar. Bu blmn ilerideki sayfalarnda yaplandrc ve yok ediciler ele alnacaktr. Dier
ye tipleri daha sonraki blmlerde anlatlacaktr.
Snf class anahtar kelimesi kullanlarak oluturulur. Tek bir rnek deiken ve metot
ieren bir class tanmnn genel biimi aadaki gibidir:


BLM 6: SINIFLARA, NESNELERE VE METOTLARA GR

HERKES N C#
129
class snfismi {
// rnek deikenleri deklare et

eriim tip deiken1;
eriim tip deiken2;
// ...
eriim tip deikenN;

// metotlar deklare et

eriim dn-tipi metot1(parametreler) {
// metodun gvdesi
}
eriim dn-tipi metot2(parametreler) {
// metodun gvdesi
}
// ...
eriim dn-tipi metotN(parametreler) {
// metodun gvdesi
}
}
Her deiken ve metodun ncesinde eriim szcnn yer aldna dikkat edin. Burada
eriim, sz konusu yenin ne ekilde eriileceini belirten bir eriim belirleyicisidir; rnein,
public gibi. Blm 2de bahsedildii gibi, snf yeleri snfa zel (private) ya da daha
eriilebilir ak olabilir. Eriim belirleyicisi, ne tr bir eriime izin verildiini belirler. Eriim
belirleyicisi istee baldr. Eriim belirleyicisi mevcut deilse, bu durumda ilgili ye snfa
zel (private) olur. private eriimli yeler yalnzca kendi snflarnn dier yeleri
tarafndan kullanlabilirler. Bu blmdeki rneklerde tm yeler public olarak belirtilecektir.
Yani, bu yeler tm dier kodlar tarafndan - hatta, snfn dnda kalan kodlar tarafndan dahi
- kullanlabilirler. Eriim belirleyicilerine Blm 8de tekrar dneceiz.
Aslnda bu durumu zorlayan bir sz dizimi kural mevcut olmamasna ramen, iyi tasarlan-
m bir snfn iinde sadece ve sadece tek bir mantksal btn (varlk) tanmlanmaldr. rne-
in, isim ve telefon numaralarn saklayan bir snf, normal olarak, borsa bilgilerini, ortalama
ya younluunu, gnein hareketlerini ya da dier ilgisiz bilgileri de ayn anda
saklamayacaktr. Buradaki husus udur; yi tasarlanm bir snf, mantksal olarak balantl
bilgileri bir araya getirip, gruplar. lgisiz bilgileri ayn snfn iine yerletirmek, kodunuzun
yapsnn ok abuk bozulmasna neden olur.
u ana kadar kullanmakta olduumuz snflarn, yalnzca tek bir metodu vard: Main().
Yaknda, dierlerini de nasl oluturacanz greceksiniz. Ancak, snfn genel yapsnda
Main() metodunun belirtilmemi olmasna dikkat edin, Main() metodu yalnzca, sz konusu
snf, programnzn balang noktas olduu taktirde gerekli olur.
Snf Tanmlamak
Snflar gz nnde canlandrmak iin binalar, rnein evler, dkkanlar, ofisler vs,
hakknda bilgileri bir araya getiren bir snf gelitireceiz. Bu snfa Building ismini verelim.

HERKES N C#
KISIM I C# DL

130
Bu snf, bir bina hakknda tr bilgi ierecek; Kat says, toplam alan ve oturanlarn
(sakinlerin) says.
Buildingin ilk versiyonu aada gsterilmitir, Bunda rnek deiken
tanmlanmaktadr: floors, area ve occupants. Buildingin hi bir metot iermediine
dikkat edin. Yani, Building imdilik sadece veri ieren bir snftr. (Sonraki blmlerde buna
baka metotlar da eklenecektir.)
class Building {
public int floors; // katlarin sayisi
public int area; // toplam bina alani, fit kare olarak
public int occupants; // oturanlarin sayisi
}
Buildingde tanmlanan rnek deikenler, rnek deikenlerin genel olarak nasl
deklare edildiini gsteriyor. Bir rnek deikeni deklare etmenin genel biimi aadaki
gibidir:
eriim tip deiken-ismi;
Burada eriim, eriimi; tip, deikenin tipini ve deiken-ismi de deikenin ismini belirtir.
Bylece, eriim belirleyicisi bir tarafa, bir rnek deikeni tpk yerel deikenleri deklare eder
gibi deklare edersiniz. Buildingde, deikenlerden nce public eriim belirleyicisi
gelmektedir. Daha nce akland gibi bu, deikenlerin Buildingin dndaki kod
tarafndan eriilmelerine imkan verir.
Snf tanm, yen bir veri tipi oluturur. Bu rnekte, yeni veri tipi Building olarak
adlandrlmtr. Building tipinde nesneler deklare ederken bu ismi kullanacaksnz. Snf
deklarasyonunun yalnzca tipi tarif eden bir ifade olduunu, gerekten bir nesne
oluturmadn hatrnzdan karmayn. Bu nedenle, yukardaki kod Building tipinde
herhangi bir nesnenin hayat bulmasna neden olmaz.
Gerekten bir Building nesnesi oluturmak iin aadaki gibi bir ifade kullanacaksnz:
Building house = new Building(); // Building tipinde bir nesne olusturur
Bu ifade gereklendikten sonra house, Buildingin bir rnei olacaktr. Bylece,
fiziksel gereklik kazanacaktr. u an iin bu ifadenin ayrntlarn dert etmeyin.
Bir snfa ait bir rnei her oluturduunuzda, sz konusu snf tarafndan tanmlanan her
rnek-deikenin kendi kopyasn ieren bir nesne oluturmu olursunuz. Yani, her Building
nesnesi floors, area ve occupants rnek deikenlerinin kendi kopyalarn ierecektir. Bu
deikenlere erimek iin nokta (.) operatrn kullanacaksnz. Nokta operatr, bir nesnenin
ismini bir yenin ismi ile balar. Nokta operatrnn genel biimi u ekildedir:
nesne.ye
Yani nesne, sol tarafta belirtilir ve ye, sa tarafa yerletirilir. rnein, houseun floors
deikenine 2 deerini atamak iin aadaki ifadeyi kullann:
BLM 6: SINIFLARA, NESNELERE VE METOTLARA GR

HERKES N C#
131
house.floors = 2;
Genel olarak, hem rnek deikenlere hem de metotlara erimek iin nokta operatrn
kullanabilirsiniz.
te, Building snfn kullanan tamamlanm bir program:
// Building sinifini kullanan bir program.

using System;

class Building {
public int floors; // kat sayisi
public int area; // toplam bina alani, fit kare olarak
public int occupants; // oturanlarin sayisi
}

// Bu, Building tipinde bir nesne deklare eder.
class BuildingDemo {
public static void Main() {
Building house = new Building(); // bir Building nesnesi olustur
int areaPP; // kisi basina dsen alan

// house icindeki alanlara deger ata
house.occupants = 4;
house.area = 2500;
house.floors = 2;

// kisi basina dsen alani hesapla
areaPP = house.area / house.occupants;

Console.WriteLine(house has:\n + house.floors +
floors\n. + house.occupants\n
occupants\n + house.area +
total area\n + areaPP +
area per person);
}
}
Bu program iki snftan olumaktadr: Building ve BuildingDemo. BuildingDemo
iindeki Main() metodu, Building snfnn house adnda bir rneini oluturur. Sonra
Main() iindeki kod, house ile ilikili rnek deikenlere deerler atayarak ve bu deerleri
kullanarak bu deikenlere eriir. Building ve BuildingDemonun iki ayr snf olduunu
anlamak nemlidir. Bu snflarn arasndaki tek iliki, bir snfn dierinin rneini
oluturmasdr. Ayr birer snf olmalarna ramen BuildingDemonun iindeki kod
Buildingin yelerine eriebilir, nk bu yeler public olarak deklare edilmitir. Eer bu
yelerle public eriim belirleyicisi kullanlmam olsayd, sz konusu yelerin eriimi
Building snf ile kstl kalm olacakt ve BuildingDemo bunlar kullanmayacakt.
Diyelim ki, yukardaki UseBuilding.cs dosyasn aryorsunuz. Bu program
derlemek UseBuilding.exe isminde bir dosya oluturur. Building ve BuildingDemo

HERKES N C#
KISIM I C# DL

132
snflarnn her ikisi de bu altrlabilir dosyann birer parasdr. Program aadaki kty
ekranda gsterir:
house has:
2 floors
4 occupants
2500 total area
625 area per person
Aslnda, Building ve BuildingDemo snflarnn ayn kaynak dosyas iinde
bulunmalar art deildir. Her snf, rnein Building.cs ve BuildingDemo.cs olarak
adlandrlan, kendi dosyasna yerletirebilirsiniz. C# derleyicisine her iki dosyay derleyip
balamas gerektiini sylemeniz yeterlidir. Sz gelii, program eer imdi anlatlan ekilde
iki paraya ayrmsanz, program derlemek iin u komut satrn kullanabilirsiniz.
csc Building.cs BuildingDemo.cs
Eer Visual Studio IDEyi kullanyorsanz, her iki dosyay da projenize eklemeniz ve
yeniden kurmanz gerekecektir.
Daha fazla ilerlemeden, gelin, temel prensibi tekrarlayalm: Her nesne, kendi snf
tarafndan tanmlanan rnek deikenlerin kendi kopyalarna sahiptir. Yani, bir nesnenin
iindeki deikenlerin ierii, bir baka nesne iindeki deikenlerin ieriinden farkl olabilir.
Her iki nesne arasnda, ayn tipte nesne olmalar haricinde hi bir ba yoktur. rnein, iki
Building nesneniz varsa, her nesne floors, area ve occupantsn kendi kopyalarn ierir
ve bunlarn ierikleri her iki nesne arasnda farkllk gsterebilir. Aadaki program bu gerei
ortaya koymaktadr:
//8u program iki Building nesnesi olusturur.
using System;

class Building {
public int floors; // kat sayisi
public int area; // toplam bina alani, fit kare olarak
public int occupants; // oturanlarn sayisi
}

// Bu sinif, Building tipinde iki nesne deklare eder.
class BuildingDemo {
public static void Main() {
Building house = new Building();
Building office = new Building();

int areaPP; // Kisi basina dusen alan

// house icindeki alanlara deger ata
house.occupants = 4;
house.area = 2500;
house.floors = 2;

// office icindeki alanlara deger ata
office.occupants = 25;
BLM 6: SINIFLARA, NESNELERE VE METOTLARA GR

HERKES N C#
133
office.area = 4200;
office.floors = 3;

// ev icinde kisi basina dusen alani hesapla
areaPP = house.area / house.occupants;

Console.WriteLine(house has:\n + house.floors +
floors\n + house.occupants +
occupants\n + house.area +
total area\n + areaPP +
area per person);

Console.WriteLine();

// ofis icinde kisi basina dusen alani hesapla
areaPP = office.area / office.occupants;

Console.WriteLine(office has:\n + office.floors +
floors\n + office.occupants +
occupants\n + office.area +
total area\n + areaPP +
area per person);
}
}
Bu programla elde edilen kt aada gsterilmitir:
house has:
2 floors
4 occupants
2500 total area
625 area per person
office has:
3 floors
25 occupants
4200 total area
168 area per person
Grdnz gibi, houseun verileri officein ierdii verilerden tamamen ayrdr. ekil
6.1de bu durum gsterilmektedir.

house



office


EKL 6.1: Bir nesnenin rnek deikenleri, dier nesneninkilerden ayrdr.
floors 2
area 2500
occupants 4
floors 3
area 4200
occupants 25

HERKES N C#
KISIM I C# DL

134
Nesneler Nasl Oluturulur?
nceki programlarda Building tipinde bir nesne deklare etmek iin aadaki satr
kullanlmt;
Building house = new Building{);
Bu deklarasyon iki ilevi gerekletirir; ncelikle, house adnda Building snf tipinde
bir deiken deklare eder. Bu deiken bir nesne tanmlamaz. Bilakis bu, bir nesneyle ilikili
olabilecek bir deikenden ibarettir. kincisi, sz konusu deklarasyon, nesnenin asl, fiziksel
kopyasn oluturur ve house deikenine bu nesnenin bir referansn atar. Bu ilem new
operatr kullanlarak gerekletirilir. Bylece, bu satr gereklendikten sonra house,
Building tipinde bir nesneyle ilikilendirilmi olur.
new operatr, bir nesne iin bellekte dinamik olarak (yani, alma esnasnda) yer ayrr
ve buna bir referans dndrr. Bu referans, nesne iin new ile ayrlan bellek alannn adresidir.
Bu referans daha sonra, bir deiken iinde saklanr. Yani, C#ta tm snf nesneleri iin bellek
alan dinamik olarak ayrlmaldr.
nceki ifadedeki birletirilmi iki adm, her adm avn ayr gstermek iin u ekilde yeni
den yazlabilir:
Building house; // nesneyi gosteren bir referans deklare et
house = new Building (); /* bir Building nesnesi icin
bellek tahsis et */
lk satr, Building tipinde bir nesneye bir referans olarak house deikenini deklare
etmektedir. Bylece, house bir nesneyle ilikili bir deikendir, fakat kendisi bir nesne
deildir. Bu aamada, house, null deerini iermektedir. null, deiken bir nesneyle ilikili
deildir, anlamn tar. Bir sonraki satr, yeni bir Building nesnesi oluturur ve bunu
gsteren bir referans housea atar. Artk, house bir nesne ile balanmtr.
Snf nesnelerinin referans yoluyla eriilmeleri, snflarn neden referans tipleri olarak
adlandrldklarn da aklamaktadr. Deer tipleri ve referans tipleri arasndaki en temel fark,
her tipin deikenlerinin sahip olduklar anlamlardan kaynaklanmaktadr. Bir deer tipindeki
bir deiken iin, deikenin kendisi ilgili deeri tar. rnein,
int x;
x = 10;
x, 10 deerini tar nk x, bir deer tipi olan int tipinde bir deikendir. Ancak, u du-
rumda
Building house = new Building();
houseun kendisi nesneyi iermez. Bunun yerine, nesneyi gsteren bir referans ierir.

BLM 6: SINIFLARA, NESNELERE VE METOTLARA GR

HERKES N C#
135
Referans Deikenleri ve Atama
Bir atama ileminde referans deikenleri, bir deer tipinin, rnein int tipinin,
deikenlerinden daha farkl davranrlar. Bir deer tipi deikenini bir dierine atarken durum
apak ortadadr. Sol taraftaki deiken, sa taraftaki deikenin deerinin bir kopyasn alr.
Bir nesne referans deikenini bir dierine atarken ise, durum biraz daha karmaktr, nk
referans deikeninin ilikili olduu nesneyi deitiriyorsunuz. Aradaki bu farkn etkisi
beklenmeyen baz sonular dourabilir. rnein, aadaki kod parasn ele aln:
Building house1 = new Building();
Building house2 = house1;
lk bakta, house1 ve house2nin farkl nesnelerle ilikili olduu kolaylkla
dnlebilir; fakat bu sz konusu deildir, Bunun yerine, house1 ve house2nin her ikisi de
ayn nesneyle ilikilendirilecektir. house1i house2ye atamak, house1in ilikilendirilmi
olduu nesne ile house2yi de ilikilendirmekten ibarettir. rnein, aadaki atama
gereklendikten sonra
housel.area = 2600;
u WriteLine() ifadelerinin her ikisi de
Console.WriteLine(house1.area);
Console.writeLine(house2.area);
ayn deeri gstermektedirler: 2600.
house1 ve house2nin her ikisi de ayn nesne ile ilikili olsa da, baka hibir ekilde
ilikili deillerdir. rnein house2ye sonradan bir baka deer atamak yalnzca house2nin
ilikili olduu nesneyi deitirir. rnein,
Building house1 = new Building();
Building house2 = house1;
Building house3 = new Building();

house2 = house3; /* artik, house2 ve house3 ayni nesneyle
iliskilidir. */
Bu ifade sekans altrldktan sonra house2, house3n ilikili olduu nesneyle ilikili
hale gelir. house1in ilikili olduu nesne deiiklie uramaz.
Metotlar
nceden akland gibi, rnek deikenler ve metotlar snflar oluturan iki ana
bileendir. imdiye kadar, Building snf veri ieriyor ama hi metot iermiyordu. Sadece
veri ieren snflar da tamamen geerli olmasna ramen, snflarn birou metot ierecektir.
Metotlar, snf tarafndan tanmlanan verileri maniple eden ve bir ok durumda sz konusu

HERKES N C#
KISIM I C# DL

136
verilere eriim salayan alt rutinlerdir. zellikle, programnzn dier blmleri snfla, snfn
metotlar yoluyla etkileeceklerdir.
Bir metot, bir veya daha fazla ifade ierir. yi yazlm bir C# kodunda her metot yalnzca
tek bir grev grr. Her metodun bir ismi vardr ve metodu armak iin bu isim kullanlr.
Genel olarak, bir metoda istediiniz ismi verebilirsiniz. Ancak, Main() isminin programnz
almaya balatan metoda ayrlm olduunu unutmayn. Ayrca, C# anahtar kelimelerini
metot isimleri olarak kullanmayn.
Metotlar metin iinde belirtirken elinizdeki kitapta, C# hakknda yazarken ortak hale
gelmi bir konvansiyon kullanlmaktadr ve kullanlmaya devam edilecektir. Metot isminden
sonra parantezler yer alacaktr. rnein, bir metodun ismi getval ise, bu metodun ismi bir
cmle iinde kullanlrken getval() olarak yazlacaktr. Bu notasyon, elinizdeki kitaptaki
deiken isimlerini metot isimlerinden ayrt etmenize yardmc olacaktr.
Metodun genel biimi u ekildedir:
eriim dn-tipi isim (parametre-listesi) {
// metodun gvdesi
}
Burada eriim, programn dier blmlerinin bu metodu nasl aracan belirleyen bir
eriim niteleyicisidir. nceden akland gibi, eriim niteleyicisi istee baldr. Eer eriim
niteleyicisi mevcut deilse metot, tanml olduu snfa zeldir (private). imdilik, tm
metotlar public olarak deklare edeceiz, bylece bu metotlar programn iindeki dier kodlar
tarafndan da arlabilecekler. dn-tipi, metodun dndrd veri tipini belirtir. Bu, kendi
oluturduunuz snf tipleri de dahil olmak zere herhangi geerli tipte olabilir. Eer metot bir
deer dndrmyorsa, dn deeri void olmaldr. Metodun ismi, isimile belirtilir. Bu, mev-
cut kapsam iinde dier eler tarafndan zaten kullanlmakta olanlardan baka, geerli her-
hangi bir tanmlayc olabilir. parametre-listesi, virgl ile ayrlm tip ve tanmlayc iftlerin-
den oluan bir listedir. Parametreler, esas olarak, metot arldnda metoda aktarlan
argmanlarn deerini alan deikenlerdir. Metodun hi parametresi yoksa parametre listesi de
bo olacaktr.
Building Snfna Bir Metot Eklemek
Az nce akland gibi, bir snfn metotlar tipik olarak bu snfn verilerini maniple
eder ve bu verilere eriim salarlar. Bunu hatrda tutarak, nceki rneklerde Main()in toplam
alan oturanlarn saysna blerek kii bana den alan hesapladn hatrlayn. Bu teknik
olarak doru olsa da, bu hesaplamay gerekletirmek iin en iyi yntem deildir. Kii bana
den alan hesab en iyi Building snfnn kendisi tarafndan gerekletirilebilir. Bu sonuca
gtren neden kolaylkla anlalabilir: Bir binada kii bana den alan, Building snf
tarafndan paketlenmi area ve occupants alanlarnn deerlerine baldr. Bylece,
Building snfnn bu hesaplamay kendi bana gerekletirmesi mmkndr. stelik, bu
hesaplamay Buildingin iine ekleyerek, Buildingi kullanan programlarn her birinin bu
hesab yapmak zorunda olmalarn da nlemi olursunuz. Bu, kodun gereksiz yere
BLM 6: SINIFLARA, NESNELERE VE METOTLARA GR

HERKES N C#
137
kopyalanmasna da engel olur. Son olarak, Buildingin iine kii bana den alan
hesaplayan bir metot eklemek suretiyle, bir bina ile dorudan ilikili nicelikleri Building
iine zapt ederek Building snfnn nesne ynelimli yapsn da gelitirmi oluyorsunuz.
Buildinge bir metot eklemek iin sz konusu metodu Buildingin deklarasyonu iinde
belirtin. rnein, Buildingin aadaki versiyonu, bir binada kii bana den alan gsteren
areaPerPerson() isimli bir metot iermektedir;
// Building'e bir metot ekle.

using System;

class Building {
public int floors; // kat sayisi
public int area; // toplam bina alani, fit kare olarak
public int occupants; // oturanlarin sayisi

// Kisi basina dusen alani goster.
public void areaPerPerson() {
Console.WriteLine( + area / occupants +
area per person);
}
}

// areaPerPerson() metodunu kullan.
class BuildingDemo {
public static void Main() {
Building house = new Building();
Building office = new Building();

// house icindeki alanlara deger ata
house.occupants = 4;
house.area = 2500;
house.floors = 2;

// office icindeki alanlara deger ata
office.occupants = 25;
office,area = 4200;
office.floors = 3;

Console.WriteLine(house has:\n +
house.floors + floors\n +
house.occupants + occupants\n +
house.area + total area);
house.areaPerPerson();

Console.WriteLine();

Console.WriteLine(office has:\n +
office.floors + floors\n +
office.occupants + occupants\n +
office.area + total area);
office.areaPerPerson();

HERKES N C#
KISIM I C# DL

138
}
}
Bu program, nceki ile ayn olan aadaki kty retir:
house has:
2 floors
4 occupants
2500 total area
625 area per person

office has:
3 floors
25 occupants
4200 total area
168 area per person
Gelin, imdi areaPerPerson() metodundan balayarak bu programn temel elerine
gz atalm. areaPerPerson()un ilk satr udur:
public void areaPerPerson() {
Bu satr, areaPerPerson() adnda, parametresiz bir metot deklare etmektedir. Bu metot
public olarak belirtilmitir; bylece, programn dier blmlerinin tm tarafndan
kullanlabilir. Bu metodun dn tipi voiddir. Bu sayede, areaPerPerson() kendisini
aran program parasna bir deer dndrmez. Satr, metodun al kme parantezi ile sona
ermektedir.
areaPerPerson()un gvdesi sadece u ifadeden olumaktadr:
Console.WriteLine( + area / occupants + area per person);
Bu ifade, alan oturanlarn saysna blerek bir binada kii bana den alan gstermekte-
dir. Building tipindeki her nesne area ve occupantsn kendi kopyalarna sahip olduklar
iin, areaPerPerson() arld zaman, hesaplarda metodu aran nesneye ait deiken
kopyalar kullanlmaktadr.
areaPerPerson() metodu, kapan kme parantezine rastlaynca sona erer. Bu, program
kontrolnn tekrar metodu aran koda geri dnmesine neden olur.
imdi, Main()in iindeki u kod satrna yakndan bir bakn:
house.areaPerPerson();
Bu ifade, house zerindeki areaPerPerson() metodunu arr. Yani, nesnenin
isminin ardndan nokta operatrn kullanarak areaPerPerson()u house nesnesine bal
olarak armaktadr. Bir metot arld zaman, program kontrol metoda aktarlr. Metot
sona erdiinde ise, kontrol tekrar metodu aran koda geri dner ve program, ary takip
eden kod satr ile devam eder.
BLM 6: SINIFLARA, NESNELERE VE METOTLARA GR

HERKES N C#
139
Bu rnekte, house.areaPerPerson() ars, house tarafndan tanmlanan binada kii
bana den alan gstermektedir. Benzer ekilde, office.areaPerPerson() ars ise
office tarafndan tanmlanan, binadaki kii bana den alan gsterir. areaPerPerson(),
her arlnda belirtilen nesne iin kii bana den alan gsterir.
areaPerPerson() metodu iinde ok dikkat edilmesi gerekli olan bir ey vardr: area
ve occupants rnek deikenleri dorudan kullanlrlar; isimleri nnde nesne ismi veya
nokta operatr kullanlmaz. Bir metot kendi snf tarafndan tanmlanm bir rnek deiken
kullandnda, bunu dorudan gerekletirir; nesneye aka referansta bulunmaz veya nokta
operatrn kullanmaz. Bunun zerinde biraz dnrseniz mantkl olduunu grrsnz. Bir
metot her zaman kendi snfnn belirli bir nesnesine bal olarak arlr. Bu tr bir ar sz
konusu olduu andan itibaren artk bu nesne bilinir. Bylece, bir metot iinde nesneyi ikinci
kez belirtmeye gerek yoktur. Bu, areaPerPerson() iindeki area ve occupantsn,
areaPerPerson()u aran nesne iindeki bu deikenlerin kopyalaryla dolayl olarak
ilikili olduklar anlamna gelir.
Metottan Dn
Genel olarak, bir metodun dnmesine neden olan iki koul sz konusudur. lki, nceki
rnekteki areaPerPerson() metodundan da grlecei gibi, metodun kapan kme
parantezi ile karlanca sz konusu olur. kinci ise return ifadesi altrldnda
gereklenir, returnn iki ekli vardr: biri void metotlarnda (bir deer dndrmeyen
metotlar) kullanlan ekli, biri de deer dndrmek iin kullanlan ekli. Burada ilk ekil
incelenmektedir. Bir sonraki blmde nasl deer dndrld aklanmaktadr.
Bir void metotla, aadaki gibi bir return kullanarak metodun annda dnmesine neden
olabilirsiniz:
return ;
Bu ifade altrldnda program kontrol, metodun geri kalan kodunu atlayarak metodu
aran koda dner, rnein, u metodu ele aln:
public void myMeth() {
int i;

for( i = 0; i < 10; i++) {
if(i == 5) return; // 5'te dur
Console.WriteLine();
}
}
Burada, for dngs yalnzca 0dan 5e kadar dnecektir, nk i, 5e eit olur olmaz
metot dner.
Bir metot iinde, zellikle iki veya daha fazla dn yolu sz konusu olduunda, birden
fazla return ifadesinin bulunmasna izin verilebilir. rnein,

HERKES N C#
KISIM I C# DL

140
public void myMeth() {
// ...
if(done) return;
// ...
if(error) return;
}
Bu rnekte, metodun ii bittiinde (done) veya bir hata (error) ortaya ktnda metot
dner. Ancak, siz yine de dikkatli olun. Bir metot iinde ok sayda k noktas olmas
kodunuzun yapsn bozabilir; bu nedenle, bunlar sk sk kullanmaktan kann.
Tekrar sylersek, bir void metot, iki yntemden biri kullanlarak dnebilir- metodun kapa-
n kme parantezine ulaldnda veya bir return ifadesi gereklendiinde.
Bir Deer Dndrmek
void tipinde metotlar ender olmasa da, metotlarn ou bir deer dndrecektir. Aslnda,
bir deer dndrme becerisi bir metodun en yararl zelliklerinden biridir. Blm 3te kare kk
elde etmek iin Math.Sqrt() fonksiyonunu kullandmzda, dn deerine bir rnek
grmtnz.
Dn deerleri, programlamada ok eitli amalarda kullanlabilir. Baz durumlarda,
Math.Sqrt() rneinde olduu gibi, dn deeri baz hesaplamalardan elde edilen sonucu
iermektedir. Dier durumlarda dn deeri, yalnzca baar ve baarszl gstermekten
ibaret olabilir. Geri kalan durumlarda ise, dn deeri bir durum kodunu ierebilir. Ama ne
olursa olsun, metot dn deerlerini kullanmak C# programlamann nemli bir parasdr.
Metotlar, kendilerini aran rutine, aadaki ekilde return kullanarak bir deer
dndrrler:
return deer;
Burada deer, dndrlen deerdir.
areaPerPerson()un uygulann gelitirmek iin bir dn deeri kullanabilirsiniz.
Kii bana den alan gstermek yerine, areaPerPerson()un bu deeri dndrmesini
salamak daha iyi bir yaklamdr. Bu deeri dier hesaplamalarda da kullanlabilecek olmanz,
bu yaklamn salad avantajlar arasndadr. Aadaki rnekte areaPerPerson() metodu,
kii bana den alan gstermek yerine, bu deeri dndrecek ekilde deitirilmektedir:
// areaPerPerson()dan bir deger dondurmek.

using System;

class Building {
public int floors; // kat sayisi
public int area; // binanin toplam alani, fit kare olarak
public int occupants; // oturanlarin sayisi

// Kisi basina dusen alani dondur.
BLM 6: SINIFLARA, NESNELERE VE METOTLARA GR

HERKES N C#
141
public int areaPerPerson() {
return area / occupants;
}
}

// areaPerPerson()'dan donen degeri kullan.
class BuildingDemo {
public static void Main() {
Buildine house = new Building();
Building office = new Building();
int areaPP; // kisi basina dsen alan

// house icindeki alanlara deger ata
house.occupants = 4;
house.area = 2500;
house.floors = 2;

// office icindeki alanlara deger ata
office.occupants = 25;
office.area = 4200;
office.floors = 3;

// ev icin kisi basina dusen alan elde et
areaPP = house.areaPerPerson();

Console.WriteLine(house has:\n +
house.floors + floors\n +
house.occupants + occupants\n +
house.area + total area\n +
areaPP + area per person);

Console.WriteLine();

// ofis icin kisi basina dusen alani elde et
areaPP = office.areaPerPerson();

Console.WriteLine(office has:\n +
office.floors + floors\n +
office.occupants + occupants\n +
office.area + total area\n +
areaPP + area per person);
}
}
kt, nceden gsterilen ktyla ayndr.
Programda dikkat ederseniz, areaPerPerson() arld zaman, atama ifadesinin sa
tarafna yerletirilmektedir. Solda, areaPerPerson()un dndrecei deeri alacak olan
deiken yer alr. Bylece, aadaki ifade altktan sonra, house nesnesinin kii bana
den alan areaPP iinde saklanr.
areaPP = house.areaPerPerson();

HERKES N C#
KISIM I C# DL

142
areaPerPerson()un artk int tipinde bir deere sahip olduuna dikkat edin. Bu,
kendisini aran koda bir tamsay deer dndrecei anlamna gelir. Bir metodun dn deeri
nemlidir, nk metot tarafndan dndrlen deer, metot tarafndan belirtilen deerle uyumlu
olmaldr. Yani, double tipinde bir deer dndren bir metot istiyorsanz, bu durumda sz
konusu metodun dn tipi double tipinde olmaldr.
nceki program doru olmasna ramen, olabildiince verimli bir biimde yazlmamtr.
Spesifik olarak, areaPP deikenine hi gerek yoktur. areaPerPerson()a yaplan ar
dorudan WriteLine() ifadesinde kullanlabilir. u ekilde:
Console.WriteLine(house has:\n +
house.floors + floors\n +
house.occupants + occupants\n +
house.area + total area\n +
house.areaPerPerson() + area per person);
Bu rnekte, WriteLine() altrldnda house.areaPerRerson() otomatik olarak
arlr ve bundan dnen deer, WriteLine()a aktarlr. stelik, bir Building nesnesi iin
kii bana den alan ne zaman gerekli olarsa, her seferinde areePerPerson()a arda
bulunabilirsiniz. rnein, u ifade iki binann kii bana den alanlarn karlatrmaktadr:
if(bl.areaPerPerson() > b2.areaPerPerson())
Console.WriteLine(b1 has more space for each person);
Parametre Kullanmak
Bir metot arld zaman, metoda bir veya iki deer aktarmak mmkndr. nceden
akland gibi, bir metoda aktarlan deere argman denir. Metot iinde, argman kabul eden
deikene parametre denir. Parametreler, metot isminin peinden gelen parantezler iinde
deklare edilirler. Parametreleri deklare etmek iin kullanlan sz dizimi, deikenler iin
kullanlan ile ayndr. Bir parametre kendi metodunun kapsam iindedir ve argman kabul
etmek gibi zel grevi bir tarafa, tpk dier yerel deikenler gibi davranr.
te, parametre kullanan basit bir rnek. ChkNum snf iinde isPrime() metodu,
kendisine aktarlan deer asal ise true dndrmektedir. Aksi halde, false dndrr. Bu
nedenle, isPrime(), bool dn tipine sahiptir.
// Parametre kullanan basit bir ornek.

using System;

class ChkNum {
// x, asal ise true dondur.
public bool isPrime(int x) {
for(int i=2; i < x/2 + 1; i++)
if((x % i) == 0) return false;

return true;
}
}
BLM 6: SINIFLARA, NESNELERE VE METOTLARA GR

HERKES N C#
143

class ParmDemo {
public static void Main() {
ChkNum ob = new ChkNum();

for(int i=1; i < 10; i++)
if(ob.isPrime(i)) Console.WriteLine(i + is prime.);
else Console.WriteLine(i + is not prime.);

}
}
Programn kts ite yledir:
1 is prime.
2 is prime.
3 is prime.
4 is not prime.
5 is prime.
6 is not prime.
7 is prime.
8 is not prime.
9 is not prime.
Bu programda isPrime() dokuz kez arlmaktadr ve fonksiyona her seferinde farkl bir
deer aktarlmaktadr. Gelin, imdi bu ileme daha yakndan gz atalm. ncelikle,
isPrime()n nasl arldna dikkat edin. Argman, parantez iinde belirtilmektedir.
isPrime() ilk kez arldnda, fonksiyona 1 deeri aktarlmaktadr. Yani, isPrime()
gereklenmeye baladnda x parametresi 1 deerini alr. kinci arda argman, 2dir ve x, 2
deerine sahip olur nc arda argman, 3tr ve bu, xin kabul ettii deerdir vs.
Buradaki husus udur: isPrime() arldnda argman olarak aktarlan deer, fonksiyonun
x parametresi tarafndan kabul edilen deerdir.
Bir metodun birden fazla parametresi olabilir. Sadece, her parametreyi bir sonrakinden
virglle ayrarak deklare edin. rnein, burada ChkNum snf, lcd() adnda bir metot
eklenerek geniletilmitir. lcd(), kendisine aktarlan iki deerin en kk ortak blenini
dndrr:
// iki arguman alan bir metot ekleyin.

using System;

class ChkNum {
// x asal ise true dondur.
public bool isPrime(int x) {
for(int i=2; i < x/2 + 1; i++)
if(x % i) == 0) return false;

return true;
}
// En kucuk ortak boleni dondur.
public int lcd(int a, int b) {

HERKES N C#
KISIM I C# DL

144
int max;

if(isPrime(a) | isPrime(b) return 1;

max = a < b ? a : b;

for(int i=2; i < max/2 + 1; i++)
if(((a%i) == 0) & ((b%i) == 0)) return i;

return 1;
}
}

class ParmDemo {
public static void Main() {
ChkNum ob = new ChkNum();
int a, b;

for(int i=1; i < 10; i++)
if(ob.isPrime(i)) Console.WriteLine(i + is prime.);
else Console.WriteLine(i + is not prime.);

a = 7;
b = 8;
Console.WriteLine(Least common denominator for +
a + and + b + is +
ob.lcd(a, b));

a = 100;
b = 8;
Console.WriteLine(Least common denominator for +
a + and + b + is +
ob.lcd(a, b));

a = 100;
b = 75;
Console.WriteLine(Least common denominator for +
a + and + b + is +
ob.lcd(a, b));
}
}
lcd() arldnda argmanlarn da virgl ile ayrldna dikkat edin. Programdan elde
edilen kt aada gsterilmitir;
1 is prime.
2 is prime.
3 is prime.
4 is not prime.
5 is prime.
6 is not prime.
7 is prime.
8 is not prime.
9 is not prime.
Least common denominator for 7 and 8 is 1
BLM 6: SINIFLARA, NESNELERE VE METOTLARA GR

HERKES N C#
145
Least common denominator for 100 and 8 is 2
Least common denominator for 100 and 75 is 5
Birden fazla parametre kullanldnda her parametre kendi tipini belirtir. Parametrelerin
tipleri birbirinden farkl olabilir. rnein, u ifade tamamen geerlidir:
int myMeth(int a, double b, float c) {
// ...
Buildinge Parametreli Bir Metot Eklemek
Building snfna yeni bir zellik katmak iin parametreli bir metot kullanabilirsiniz: Bu
zellik; bir bina sakinlerinin belirli bir minimal alan kapladklarn varsayarak, bina sakinlerinin
maksimum saysn hesaplama becerisi olabilir. Bu yeni metot maxOccupant() olarak
adlandrlr ve aada gsterildii gibidir:
/* Bina sakinlerinin her biri en azindan belirli bir minimum alan
kaplamak zorundaysa, bina sakinlerinin maksimum sayisini
dondur. */
public int maxOccupant(int minArea) {
return area / minArea;
}
maxOccupant() arldnda, minArea parametresi her bina sakini iin gerekli olan
minimum alan alr. Metot, binann toplam alann bu deere bler ve sonucu dndrr.
maxOccupant() da ieren btn Building snfnn tamam aada gsterilmitir:
/*
Bir binada oturan kisilerin maksimum sayisini hesaplayan
parametreli bir metot ekleyin.
Her bina sakininin belirli bir minimum alana gereksinim
duydugunu varsayin.
*/

using System;

class Building {
public int floors; // kat sayisi
public int area; // toplam bina alani, fit kare olarak
public int occupants; // oturanlarin sayisi
// Kisi basina dusen alani dondur.
public int areaPerPerson() {
return area / occupants;
}

/* Bina sakinlerinin her biri en azindan belirli bir minimum
alan kaplamak zorundaysa, bina sakinlerinin maksimum
sayisini dondur. */
public int maxOccupant(int minArea) {
return area / minArea;
}
}

HERKES N C#
KISIM I C# DL

146

// maxOccupant() metodunu kullan.
class BuildingDemo {
public static void Main() {
Building house = new Building();
Building office = new Building();

// house icindeki alanlara deger ata
house.occupants = 4;
house.area = 2500;
house.floors = 2;

// office icindeki alanlara deger ata
office.occupants = 25;
office.area = 4200;
office.floors = 3;

Console.WriteLine(Maximum occupants for house if each has +
300 + square feet: +
house.maxOccupant(300));

Console.WriteLine(Maximum occupants for office if each has
+ 300 + square feet: +
office.maxOccupant (300));
}
}
Programn kts aadaki gibidir;
Maximum occupants for house if each has 300 square feet: 8
Maximum occupants for office if each has 300 square feet: 14
Eriilemeyen Kodlar nlemek
Metotlar hazrlarken, kodun baz paralarnn her ne koulda olursa olsun altrlamaz
olmasna neden olabilecek durumlar nlemelisiniz. Buna eriilemeyen kod (unreachable code)
denir ve bu tr bir kod C#ta hatal olarak kabul edilir. Eriilemeyen kod ieren bir metot
gelitirmiseniz, derleyici bu durumda bir uyar mesaj verecektir. rnein:
public void m() {
char a, b;

// ...

if (a == b) {
Console.WriteLine(equal);
return;
}
else {
Console.WriteLine(not equal);
return;
}
Console.WriteLine(this is unreachable);
}
BLM 6: SINIFLARA, NESNELERE VE METOTLARA GR

HERKES N C#
147
Burada, m() metodu daima son WriteLine() ifadesinden nce dnecektir. Bu metodu
derlemeye alrsanz bir uyar mesaj ile karlarsnz. Genel olarak, eriilmez kodlar sizin
tarafnzdan yaplm bir hata nedeniyle ortaya kar; bu nedenle, erilemeyen kodlarla ilgili
uyarlar ciddiye almanz tavsiye edilir.
Yaplandrclar
nceki rneklerde her Building nesnesinin rnek deikenlerinin, aadaki gibi bir
ifade sekans kullanlarak, ayarlanmalar gerekiyordu;
house.occupants = 4;
house.area = 2500;
house.floors = 2;
Bu tr bir yntem, profesyonelce yazlm C# programlarnda asla kullanlmaz. Bu
durumun hataya ak olmas bir yana (alanlardan birine deer vermeyi unutabilirsiniz), bunu
ok daha iyi gerekletirebilecek bir yntem de mevcuttur.
Yaplandrc (constructor), bir nesne oluturulduu anda bu nesneyi ilk kullanma hazrlar.
Yaplandrc kendi snf ile ayn isme sahiptir ve sz dizimsel olarak metoda benzer. Ancak,
yaplandrclarn ak bir dn tipi yoktur. Yaplandrclarn genel yaps aada
gsterilmitir:
eriim snf-ismi() {
// yaplandrc kodu
}
Genellikle, bir snf tarafndan tanmlanan rnek deikenlere ilk deer atarken veya bir
nesnenin eksiksiz oluturulmas iin gerekli dier balang prosedrlerini gerekletirirken
yaplandrclar kullanacaksnz. Ayrca, eriim genellikle publictir, nk yaplandrclar
normal olarak kendi snflar dndan arlrlar.
Siz tanmlayn ya da tanmlamayn, tm snflarn yaplandrclar vardr, nk C#
otomatik olarak, tm ye deikenlere sfr (deer tipleri iin) veya null (referans tipleri iin)
ilk deerini atayan bir varsaylan yaplandrc salar. Yine de, kendi yaplandrcnz
tanmladnz andan itibaren varsaylan yaplandrc bir daha kullanlmaz.
te size, bir yaplandrc kullanan basit bir rnek:
// Basit bir yapilandirici.

using System;

class MyClass {
public int x;

public MyClass() {
x = 10;
}
}

HERKES N C#
KISIM I C# DL

148

class ConsDemo {
public static void Main() {
MyClass t1 = new MyClass();
MyClass t2 = new MyClass();

Console.WriteLine(t1.x + + t2.x);
}
}
Bu rnekte MyClass iin yaplandrc udur:
public MyClass() {
x = 10;
}
Dikkat ederseniz, yaplandrc public olarak belirtilmitir. Bunun nedeni,
yaplandrcnn kendi snf dnda kalan kod tarafndan arlacak olmasdr. Bu yaplandrc
MyClassn x rnek deikenine 10 deerini atar. Yeni bir nesne oluturulaca zaman sz
konusu yaplandrc new kullanlarak arlr. rnein, aadaki satrda
MyClass t1 = new MyClass();
MyClass() yaplatdrcs t1 nesnesi zerinde arlyor ve t1.xe 10 deeri atanm
oluyor. Ayn durum t2 iin de geerlidir. Yaplandrc kullanmndan sonra t2.x, 10 deerine
sahip olur. Bylece, programn kts yle olur:
10 10
Parametreli Yaplandrclar
nceki rnekte parametresiz yaplandrc kullanlmt. Bu, birok durum iin uygun olsa
da, daha ok, bir veya daha fazla parametre kabul eden yaplandrclara ihtiyacnz
olacak. Parametreler tpk metotlara eklendii ekliyle yaplandrclara eklenir: Parametreleri,
yaplandrcnn isminin ardndan gelen parantezler iinde deklare etmeniz yeterlidir. rnein,
burada MyClassa parametreli bir yaplandrc verilmitir:
// Parametreli yapilandirici.

using System;

class MyClass {
public int x;

public MyClass(int i) {
x = i;
}
}

class ParmConsDemo {
public static void Main() {
MyClass t1 = new MyClass(10);
BLM 6: SINIFLARA, NESNELERE VE METOTLARA GR

HERKES N C#
149
MyClass t2 = new MyClass(88);

Console.WriteLine(t1.x + + t2.x);
}
}
Bu programn kts aadaki gibidir:
10 38
Programn bu versiyonunda MyClass() yaplandrcs, i adnda bir parametre tanmlyor.
i, x rnek deikenine ilk deer atamak iin kullanlyor. Bylece, aadaki satr
gereklendiinde l0 deeri iye aktarlr ve bu, daha sonra xe atanr;
MyClass t1 = new MyClass(10);
Building Snfna Bir Yaplandrc Eklemek
Bir nesne oluturulurken floors, area ve occupants alanlarna otomatik olarak ilk
deer atayan bir yaplandrcy Building snfna ekleyerek Building snfn
gelitirebiliriz. Building nesnelerinin nasl oluturulduuna zellikle dikkat edin.
// Building'e bir yapilandirici ekler.

using System;

class Building {
public int floors; // kat sayisi
public int area; // toplam bina alani, fit kare olarak
public int occupants; // oturanlarn sayisi

public Building(int f, int a, int o) {
floors = f;
area = a;
occupants = o;
}

// Kisi basina dusen alani dondur.
public int areaPerPerson() {
return area / occupants;
}

/* Bina sakinlerinin her biri en azindan belirli bir minimum
alan kaplamak zorundaysa, oturanlarin maksimum sayisini
dondur. */
public int maxOccupant(int minArea) {
return area / minArea;
}
}

// Parametreli Building yapilandiricisini kullan.
class BuildingDemo {
public static void Main() {

HERKES N C#
KISIM I C# DL

150
Building house = new Building(2, 2500, 4);
Building office = new Building(3, 4200, 25);

Console.WriteLine(Maximum occupants for house if each has
+ 300 + square feet: +
house.maxOccupant (300));

Console.WriteLine(Maximum occupants for office if each has
+ 300 + square feet: +
office.maxOccupant(300));
}
}
Bu programn kts nceki versiyonunkiyle ayndr.
Hem house, hem de office oluturulduklar anda Building() yaplandrcs ile ilk
kullanma hazrlanrlar. Nesnelerin her birine ilk deerleri, parametrelerde belirtildii ekliyle
kendi yaplandrcs tarafndan atanr. rnein, aadaki satrda
Building house = new Building(2, 2500, 4);
new nesneyi ulutururken 2, 2500 ve 4 deerleri Building() yaplandrcsna aktarlr.
Bylece, housea ait floors, area ve occupants kopyalar srasyla 2, 2500 ve 4
deerlerini ierecektir.
new Operatrne Tekrar Bir Bak
Snflar ve snflarn yaplandrclar hakknda daha fazla bilgi sahibi olduunuza gre
gelin, new operatrn daha yakndan inceleyelim. new operatrnn genel yaps u
ekildedir:
snf-deikeni = new snf-ismi( );
Burada snf-deikeni, oluturulmakta olan snf tipindeki deikendir, snf-
ismi, rneklenmekte olan snfn ismidir. Ardndan parantezlerin geldii snf ismi, snfa ait
yaplandrcy belirtir. Eer bir snf kendi yaplandrcsn tanmlamyorsa new, C# tarafndan
salanan varsaylan yaplandrcy kullanacaktr. Bylece new, herhangi bir snf tipinde
nesneleri oluturmak iin kullanlabilir.
Bellek sonlu olduu iin bellein yetersiz olduu durumlarda newun bir nesne iin
bellekte yer ayramamas mmkndr. Eer byle bir durum sz konusu ise, programn
almas esnasnda bir kural d durum ortaya kacaktr. (Bunun ve dier kural dts
durumlarn nasl kontrol altna alndn Blm 13'te reneceksiniz.) Elinizdeki kitaptaki
rnek programlarda bellein tkenmesinden endie etmenize gerek olmayacak, fakat sizin
yazacanz gerek dnyaya ait programlarda bu ihtimali gz nnde bulundurmanz
gerekecektir.

BLM 6: SINIFLARA, NESNELERE VE METOTLARA GR

HERKES N C#
151
new'u Deer Tipleriyle Birlikte Kullanmak
Bu aamada, newu int veya float gibi deer tiplerindeki deikenlerle neden
kullanmanz gerekmediini merak ediyor olabilirsiniz. C#ta bir deer tipindeki deiken kendi
deerini ierir. Program derlendiinde bu deeri tutacak bellek alan, derleyici tarafndan
otomatik olarak ayrlr. Bylece, new kullanarak bu bellek alann aka ayrmaya gerek
yoktur. Bunun kart olarak bir referans deikeni, bir nesneyi gsteren bir referans ierir. Bu
nesneyi tutacak olan bellek alan, programn almas srasnda dinamik olarak ayrlr.
Temel tiplerin - rnein int veya char - referans tipi olmamas, programnzn
performansn byk lde artrr. Bir referans tipi kullanld zaman, bir dolayllk katman
sz konusu olur ki bu, nesne eriimlerinin her birine deer tiplerinde olmayan ekstra bir yk
ekler.
in ilginci, aada gsterildii gibi, newun deer tipleriyle kullanmna izin verilmi
olmasdr:
int i = new int();
Bu ifade, int tipi iin varsaylan yaplandrcy arr ve iye sfr ilk deerini atar.
rnein:
// new'u bir deger tipiyle birlikte kullanmak.

using System;

class newValue {
public static void Main() {
int i = new int(); // i'ye sifir ilk degerini ata

Console.WriteLine(The value of i is: + i);
}
}
Bu programn kts yledir:
The value of i is: 0
ktnn da dorulad gibi, iye sfr ilk deeri atanmaktadr. unu hatrnzdan
karmayn: new kullanlmam olsayd iye ilk deer atanmam olacakt ve iye aka bir
deer vermeden iyi WriteLine() ifadesinde kullanmaya almak hatal olacakt.
Genel olarak, newu bir deer tipi iin armak sz konusu tip iin varsaylan
yaplandrcy armak demektir. Akas, programclarn ou newu deer tipleriyle
birlikte kullanmazlar.



HERKES N C#
KISIM I C# DL

152
Anlamsz Verilerin Toplanmas ve Yok ediciler
Grdnz gibi nesnelere new operatr kullanlarak serbest bellek havuzundan dinamik
olarak bellek alan ayrlr. Elbette, bellek sonsuz deildir ve serbest bellek tkenebilir. Yani,
istenilen nesneyi oluturmak iin yeterli serbest bellek alan olmamas durumunda, new
ileminin baarszlkta sonulanmas mmkndr. Bu nedenle, herhangi bir dinamik bellek
alan ayrma tekniinin en temel bileenlerinden biri, kullanlmayan nesnelerin igal ettii
serbest bellek alann geri kazanmak ve bu bellek alann daha sonraki ayrma ilemleri iin
hazr tutmaktr. Birok programlama dilinde, nceden ayrlm bellek alannn serbest
braklmas, elle kontrol edilir. rnein, C++ta ayrlm bellek alann serbest brakmak, iin
delete operatrn kullanrsnz. Ancak, C# farkl ve daha problemsiz bir yntem
kullanmaktadr: Anlamsz verilerin toplanmas (garbage collection).
C#n anlamsz verileri toplama sistemi, nesnelere ayrlan bellek alann otomatik olarak
geri alr ve bu ilemi programclarn mdahale etmesine gerek kalmadan; perde arkasnda
gerekletirir. Sistem u ekilde alr: Bir nesneye hibir referans sz konusu deilse, bu nes-
neye artk ihtiya duyulmayaca varsaylr ve bu nesnenin igal ettii bellek alan serbest
braklr. Bu geri kazanlan bellek alan, daha sonraki ayrma ilemlerinde kullanlabilir.
Anlamsz verileri toplama ilemi, programnzn almas srasnda sadece ara sra
meydana gelir. Daha fazla kullanlmayacak bir veya daha fazla nesne her mevcut olduunda
gereklemez. Anlamsz verileri toplama ilemi zaman ald iin, C# alma zaman (runtime)
sistemi sadece ihtiya olduunda veya dier uygun zamanlarda bunu gerekletirir. Bu nedenle,
anlamsz verileri toplama ileminin ne zaman gerekletirileceini kesin olarak bilemezsiniz.
Yok Ediciler
Bir nesnenin anlamsz veri toplaycs tarafndan tamamen yok edilmesinden hemen nce
arlmak zere bir metot tanmlamak mmkndr. Bu metoda yok edici (destructor) denir ve
bir nesnenin kesinlikle sonlandrldn garanti etmek iin kullanlabilir. rnein, bu nesnenin
sahip olduu ak bir dosyann kapatldndan emin olmak iin bir yok edici kullanabilirsiniz.
Yok ediciler, genel olarak aadaki bir yapya sahiptir:
-snf-ismi() {
// yok edici kodu
}
Burada snf-ismi, snfn ismidir. Yani, bir yok edici tpk bir yaplandrc gibidir. Tek
fark, en bata tilda karakteri (-) iermesidir, Dn tipinin olmadna dikkat edin.
Bir snfa bir yok edici eklemek iin, bunu bir ye olarak snfa dahil etmeniz yeterlidir.
Yok edici, kendi snfnn bir nesnesi geri dntrlmek zere olduunda arlacaktr. Nesne
yok edilmeden nce gerekletirilmesi gereken ilemleri yok edici iinde belirtirsiniz.
Yok edicinin anlamsz verileri toplama ileminden hemen nce arldn kavramak
nemlidir. rnein, nesne kapsam dna ktnda yok edici arlmaz. (Bu, nesnenin kapsam
BLM 6: SINIFLARA, NESNELERE VE METOTLARA GR

HERKES N C#
153
dna kmas durumunda arlan C++n yok edicilerinden farkldr.) Bu, yok edicilerin ne
zaman altrlacan tam olarak bilemeyeceiniz anlamna gelir. Yine de, program sona
ermeden nce yok edicilerin tm arlacaktr.
Aadaki program bir yok ediciyi gstermektedir. Program, ok sayda nesne oluturarak
ve yok ederek almaktadr. Bu sre zarfnda, bir aamada anlamsz veri toplaycs etkin
klnacaktr ve bu nesneler iin yok ediciler arlacaktr.
// Bir yok ediciyi gosterir.

using System;

class Destruct {
public int x;

public Destruct(int i) {
x = i;
}

// nesne geri donusturulurken cagrilir
-Destruct() {
Console.WiteLine(Destructing + x);
}

// hemen yok edilmek uzere bir nesne uretir
public void generator(int i) {
Destruct o = new Destruct(i);
}
}

class DestructDemo {
public static void Main() {
int count;

Destruct ob = new Destruct(0);

/* Simdi, cok sayida nesne uretin. Bir asamada, anlamsiz
veri toplama islemi meydana gelecektir.
Dikkat: Anlamsiz veri toplamayi zorlamak icin, uretilen
nesne sayisini artirmaniz gerekebilir. */

for(count = 1; count * 100000; count++)
ob.generator(count);

Console.WriteLine(Done);
}
}
Programn almas yledir: Yaplandrc, x rnek deikenine ilk deer olarak bilinen
bir deer atar. Bu rnekte x, nesnenin kimlik bilgisi olarak kullanlmaktadr. Yok edici, nesne
geri dntrlrken xin deerini gsterir, generator() zellikle enteresandr. Bu metot, bir
Destruct nesnesini oluturur ve hemen ardndan da yok eder. DestructDemo snf, ob

HERKES N C#
KISIM I C# DL

154
adnda ilk Destruct nesnesini oluturur. Sonra obu kullanarak ve generator() ob
zerinde ararak, 100.000 nesne retir. Bu ilemin net etkisi 100.000 nesne retip, yok
etmektir. Bu srecin ortalarnda, eitli aamalarda anlamsz verileri toplama ilemi yer
alacaktr. Bu ilemin tam olarak ne zaman ve ne kadar sklkla gerekletirilecei, birka
faktre baldr: Balangtaki serbest bellek alan miktar, iletim sistemi vs. Ancak, bir
aamada yok edici tarafndan retilen uyar mesajlarn grmeye balayacaksnz. Program sona
ermeden nce (yani, Done mesajndan nce) bu mesajlar grmemiseniz, for dngs
iindeki countu ykselterek retilmekte olar nesne saysn artrmay deneyin.
Yok edicilerin belirsiz biimde arlmalarndan tr bu fonksiyonlar, programnzda
belirli bir aamada meydan gelmesi gereken ileri gerekletirmek iin kullanlmamaldr.
Dier bir husus ise udur: Anlamsz verilerin toplanmas talebinde bulunmak mmkndr.
Bu durum, Ksm IIde C#n snf ktphanesi ele alnrken anlatlacaktr. Ancak, anlamsz
verilerin toplanmas ilemini elle balatmak, birok durum iin tavsiye edilmez, nk bu,
verimsizliklere yol aabilir Aynca, aka anlamsz verilerin toplanmas talebinde bulunmu
olsanz bile, anlamsz veri toplaycsnn alma eklinden dolay, belirli bir nesnenin ne zaman
geri dntrleceini tam olarak bilmenizin bir yolu yoktur.
this Anahtar Kelimesi
Bu blme son vermeden nce thisi tantmak gereklidir. Bir metot arld zaman, bu
metoda, kendisini aran nesnenin bir referans olan dolayl bir argman otomatik olarak
aktarlr. Bu referans this olarak adlandrlr. thisi anlamak iin ncelikle bir program ele
alalm. Bu program, bir dikdrtgenin enini ve boyunu ieren Rect adnda bir snf oluturur.
Rect snf ayrca dikdrtgenin alan dndren area() adnda bir de metot iermektedir.
using System;

class Rect {
public int width;
public int height;

public Rect(int w, int h) {
width = w;
height = h;
}

public int area() {
return width * height;
}
}

class UseRect {
public static void Main() {
Rect r1 = new Rect(4, 5);
Rect r2 = new Rect(7, 9);

Console.WriteLine(Area of r1: + r1.area());
BLM 6: SINIFLARA, NESNELERE VE METOTLARA GR

HERKES N C#
155

Console.WriteLine(Area of r2: + r2.area());
}
}
Bildiiniz gibi, bir metot iinde snfn dier yeleri, herhangi bir nesne veya snf
niteleyicisi olmakszn dorudan eriilebilirler. Bylece, area() iindeki u ifade,
return width * height;
width ve heightn area()y aran nesne ile ilikili kopyalarnn birbiriyle
arplaca ve sonucun dndrlecei anlamna gelir. Ancak, ayn ifade u ekilde de yeniden
yazlabilir:
return this.width * this.height;
Burada this, area()nn zerinde arld nesneyle ilikilidir. Yani this.width, sz
konusu nesnenin width kopyasna ve this.height ise nesnenin height kopyasna karlk
gelir. rnein, area(), x adnda bir nesne zerinde arlm olsayd, nceki ifadede geen
this, x ile ilikili olmu olacakt. this kullanmadan ifadeyi yazmak ise gerekten ksadr.
this referans kullanlarak yazlm btn bir Rect snf u ekildedir:
using System;

class Rect {
public int width;
public int height;

public Rect(int w, int h) {
this.width = w;
this.height = h;
}

public int area() {
return this.width * this.height;
}
}

class UseRect {
public static void Main() {
Rect r1 = new Rect(4, 5);
Rect r2 = new Rect(7, 9);

Console.WriteLine(Area of r1: + r1.area());

Console.WriteLine(Area of r2: + r2.area());
}
}
Aslnda, hibir C# programcs thisi az nce gsterildii ekliyle kullanmaz, nk bu
ekilde hibir ey kazanlmaz, stelik standart form daha kolaydr. Yine de, bunun baz nemli
kullanmlar da vardr. rnein, C# sz dizimi bir parametrenin ya da yerel deikenin bir r-

HERKES N C#
KISIM I C# DL

156
nek deikenle ayn isimde olmasna izin vermektedir. Byle bir durum sz konusu olduunda
yerel isim rnek deikeni gizler. Gizlenmi rnek deikene this kullanarak eriim
salayabilirsiniz. rnein, tavsiye edilmeyen bir stil olmasna ramen aadaki kod, Rect()
yaplandrcsn yazmak iin sz dizimsel adan geerii bir yntemdir;
public Rect (int width, int height) {
this.width = width;
this.height = height;
}
Bu versiyonda, parametrelerin isimleri rnek deikenlerin isimleriyle ayndr, yani onlar
gizlemektedir; this, rnek deikenleri ortaya karmak iin kullanlmtr.




Y E D N C B L M

DZLER VE KARAKTER
KATARLARI




















7

HERKES N C#
KISIM I C# DL

158
Bu blmde C#n veri tipleri konusuna geri dnlyor. Diziler ve string tipi bu
blmde ele alnmaktadr. foreach dngs de ayrca incelenmektedir.
Diziler
Dizi (array), ortak bir isim ile anlan ayn tipteki deikenler topluluudur. Tek boyutlu
diziler ok daha yaygn olmasna ramen C#ta diziler bir veya daha fazla boyutlu olabilir.
Diziler ok eitli amalarda kullanr, nk diziler, ilgili deikenleri bir araya getirip,
gruplamak iin uygun bir yntem sunmaktadr. rnein, bir ay iin gnlk en yksek scaklk
kaytlarn, hisse senedi fiyatlarnn listesini veya programlama kitaplarndan oluan
koleksiyonunuzu tutmak iin bir dizi kullanabilirsiniz.
Dizinin salad balca avantaj, verileri, kolaylkla maniple edilecek ekilde organize
etmesidir. rnein, seilmi bir grup hissenin kar payn tutan bir diziye sahipseniz dizi
zerinden ilerleyerek ortalama gelirinizi kolaylkla hesaplarsnz. Ayrca diziler, verileri
kolaylkla sralanabilecek ekilde dzenlerler.
C#taki diziler tpk dier programlama dillerindeki diziler gibi kullanlabiliyor olsalar da
zel bir nitelie sahiptirler; C#taki diziler, nesne olarak uygulanrlar. Dizilerin anlatmnn
nesneler tantlana kadar ertelenmesinin bir nedeni budur. Dizileri nesne olarak uygulayarak
baz nemli avantajlar kazanlr. Kullanlmayan diilerin anlamsz veri kapsamnda toplanmas
bu sayede elde edilen avantajlarn en nemlilerinden biridir,
Tek Boyutlu Diziler
Tek boyutlu bir dizi, ilgili deikenlerin bir listesidir. Programlamada bu tr listeler
yaygndr. rnein, bir a zerindeki aktif kullanclarn hesap numaralarn saklamak iin tek
boyutlu bir dizi kullanabilirsiniz. Bir beyzbol takmnn mevcut vuru ortalamalarn ise bir
baka dizide saklayabilirsiniz.
Tek boyutlu bir dizi deklare etmek iin u genel yapy kullanacaksnz:
tip[] dizi-ismi = new tip[byklk];
Burada tip, dizinin temel tipini deklare etmektedir. Temel tip, diziyi oluturan her bir
elemann veri tipini belirler. tipin peinden keli parantez geldiine dikkat edin. Keli
parantezler, tek boyutlu bir dizinin deklare edilmekte olduuna iaret ederler. Dizinin tutaca
eleman says byklk ile belirtilir. Diziler, nesne olarak gereklendikleri iin bir dizi
oluturmak iki aamal bir sretir. lk aamada dizi referans deikenini deklare edersiniz.
kinci aamada dizi deikenine bir bellek referansn atayarak dizi iin bellekten yer
ayrrsnz. Bylece, C#ta dizilere new operatr kullanlarak dinamik olarak bellek alan
ayrlr.

NOT
C veya C++ biliyorsanz, dizilerin deklare edili ekline zellikle dikkat edin.
zellikle, keli parantezler dizi ismini deil, tip ismini takip etmektedir.
BLM 7: DZLER VE KARAKTER KATARLARI

HERKES N C#
159
te bir rnek. Aadaki ifade 10 elemanl bir int dizi tanmlyor ve bunu sample adnda
bir dizi referans deikenine balyor.
int[] sample = new int[10];
Bu deklarasyon tpk bir nesne deklarasyonu gibi alr. sample deikeni, new ile tahsis
edilen bellek alanna bir referans ierir. Bu bellek alam, int tipinde 10 eleman tutabilecek b-
yklktedir.
Nesnelerde olduu gibi, yukardaki deklarasyonu da ikiye blmek mmkndr. rnein:
int[] sample;
sample = new int[10];
Bu durumda, sample oluturulduunda herhangi bir fiziksel nesneyle ilikili deildir.
Ancak ikinci ifade gereklendikten sonra sample bir diziye balanr.
Bir dizinin iindeki elemanlara tek tek dizi indeksi yardmyla eriilir. Dizi indeksi (array
index), bir elemann dizi iindeki konumunu ifade eder. C#ta dizilerin tm, ilk eleman
indeksi olarak sfr deerine sahiptir. samplen 10 eleman olduu iin sample 0 ile 9
arasndaki indeks deerlerini ierir. Bir diziyi indekslemek iin istediiniz elemann numarasn
keli parantez iinde belirtin. Bylece, samplen ilk eleman sample[0], son eleman ise
sample[9] olur rnein, aadaki program samplea 0 ile 9 arasndaki saylar ykler:
// Tek boyutlu bir diziyi tanitir.

using System;

class ArrayDemo {
public static void Main() {
int[] sample = new int[10];
int i;

for(i = 0; i < 10; i = i+1)
sample[i] = i;

for(i = 0; i < 10; i = i+1)
Console.WriteLine(sample[ + i + ]: + sample[i]);
}
}
Programn kts aada gsterilmitir:
sample[0]: 0
sample[l]: 1
sample[2]: 2
sample[3]: 3
sample[4]: 4
sample[5]: 5
sample[6]: 6
sample[7]: 7
sample[8]: 8

HERKES N C#
KISIM I C# DL

160
sample[9]: 9
Kavramsal olarak, sample dizisi aadaki gibi grnr:
Diziler programlamada ska kullanlr, nk birbiriyle ilikili ok sayda deikenle
kolaylkla ilgilenmenize imkan verirler. rnein, aadaki program, for dngs yardmyla
dizi elemanlar zerinde ilerleyerek, nums dizisinde saklanan birtakm deerlerin ortalamasn
bulur:

0 1 2 3 4 5 6 7 8 9

s
a
m
p
l
e
[
0
]

s
a
m
p
l
e
[
1
]

s
a
m
p
l
e
[
2
]

s
a
m
p
l
e
[
3
]

s
a
m
p
l
e
[
4
]

s
a
m
p
l
e
[
5
]

s
a
m
p
l
e
[
6
]

s
a
m
p
l
e
[
7
]

s
a
m
p
l
e
[
8
]

s
a
m
p
l
e
[
9
]


// Bir takim degerlerin ortalamasini hesaplar.

using System;

class Average {
public static void Main() {
int[] nums = new int[10];
int avg = 0;

nums[0] = 99;
nums[1] = 10;
nums[2] = 100;
nums[3] = 18;
nums[4] = 78;
nums[5] = 23;
nums[6] = 63;
nums[7] = 9;
nums[8] = 87;
nums[9] = 49;

for(int i=0; i < 10; i++)
avg = avg + nums[i];

avg = avg / 10;

Console.WriteLine(Average: + avg);
}
}
Programdan elde edilen kt aada gsterilmitir:
Average: 53


BLM 7: DZLER VE KARAKTER KATARLARI

HERKES N C#
161
Diziyi lk Kullanma Hazrlamak
nceki programda, on ayr atama ifadesi kullanlarak nums dizisine elle deer atanmt.
Bu tamamen geerli olmasna ramen bunu gerekletirmenin daha kolay bir yolu da vardr.
Diziler tanmlanrken, ilk kullanma hazrlanabilir. Tek boyutlu bir diziyi ilk kullanma
hazrlamann genel yaps u ekildedir:
tip[ ] dizi-ismi = { deer1, deer2, deer3, ..., deerN };
Burada, ilk deerler deer1 ile deerNye kadar yer alan deerlerle belirtilir. Bu deerler
soldan saa doru indeks srasna gre srayla atanr. C#, belirttiiniz ilk deerleri tutabilecek
byklkte bir diziye, otomatik olarak bellek alan ayrr. new operatrn kullanmaya gerek
yoktur. rnein, Average programn ite daha iyi yazmann bir yolu yledir:
// Bir takim degerlerin ortalamasini hesaplar.

using System;

class Average {
public static void Main() {
int[] nums = { 99, 10, 100, 18, 78, 23,
63, 9, 87, 49 };
int avg = 0;

for(int i = 0; i < 10; i++)
avg = avg + nums[i];

avg = avg / 10;

Console.WriteLine(Average: + avg);
}
}
lgin bir konu, gerekli olmamasna ramen bir diziyi ilk kullanma hazrlarken new
operatrn kullanabilmenizdir. rnein, yukardaki programda nums ilk kullanma
hazrlamak iin bu, uygun fakat gereksiz bir yoldur:
int[] nums = new int[] { 99, 10, 100, 18, 78, 23,
63, 9, 87, 49 };
Burada gereksiz olmasna ramen, diziyi new ile ilk kullanma hazrlamak, nceden
mevcut bir dizi referans deikenine yeni bir dizi atayacanz zaman ie yarar rnein:
int[] nums;
nums = new int[] { 99, 10, 100, 18, 78, 23,
63, 9, 37, 49 };
Bu durumda, nums ilk ifadede deklare edilir ve ikincisinde ilk deerlerini alr.

HERKES N C#
KISIM I C# DL

162
Son bir husus: Bir diziyi ilk kullanma hazrlarken dizi bykln aka belirtmeye izin
verilir, fakat byklk, atanacak deer says ile uyumaldr. rnein, nums ilk kullanma
hazrlamann bir baka yolu yledir;
int[] nums = new int[10] { 99, 10, 100, 18, 78, 23,
63, 9, 87, 49 );
Bu deklarasyonda, numsn bykl aka 10 olarak belirtilmitir.
Snrlar Zorlanr
C#ta dizi snrlarna sk skya uymak gereklidir. Dizinin st snrn atnzda yada alt
snrnn altna dtnzde alma zaman hatas meydana gelir. Bunu kendi kendinize
dorulamak isterseniz, dizinin st snrn kasti olarak aan aadaki program deneyin:

// Dizinin ust sinirinin asilmasini gosterir.

using System;

class ArrayErr {
public static void Main() {
int[] sample = new int[10];
int i;

// bir dizi am olutur

for(i = 0; i < 100; i = i+1)
sample[i] = i;
}
}
i, 10a ular ulamaz IndexOutOfRangeException (indeksin menzil dna ktn
belirten bir kural d durum) meydana gelir ve program sona erer.
ok Boyutlu Diziler
Programlamada en yaygn olarak tek boyutlu diziler kullanyor olmasna ramen, ok
boyutlu diziler de kesinlikle ender olarak kullanlmaz. ok boyutlu bir dizi (multidimensional
array), iki veya daha fazla boyutu olan dizidir ve dizinin her elemanna iki veya daha fazla
indeks kombinasyonu ile eriilir.
ki Boyutlu Diziler
ok boyutlu dizinin en basit ekli iki boyutlu dizidir. ki boyutlu dizide herhangi bir
spesifik elemann konumu iki indeks ile belirtilir. ki boyutlu bir diziyi bilgi ieren bir tablo
olarak dnrseniz, indekslerden biri satr, dieri de stunu gsterir,
BLM 7: DZLER VE KARAKTER KATARLARI

HERKES N C#
163
table adnda ve 10x20 boyutunda iki boyutlu bir tamsay dizisi deklare etmek iin u
ekilde yazarsnz:
int[,] table = new int[10, 20];
Deklarasyona zellikle dikkat edin- ki boyutun birbirinden virgl ile ayrldna ok
dikkat edin. Deklarasyonun ilk blmnde, aadaki sz dizimi
[,]
iki boyutlu dizi referans deikeninin oluturulmakta olduuna iaret eder. new
kullanlarak dizi iin gerekten bellek alan ayrldnda, u sz dizimi kullanlr:
int[10, 20]
Bu, 10x20 boyutunda bir dizi oluturur ve boyutlar yine virgl ile ayrlr.
ki boyutlu dizinin bir elemanna erimek iin, her iki indeksi de virgl ile ayrarak
belirtmelisiniz. rnein, table dizisinin 3, 5 konumuna 10 deerini atamak iin yle
yazarsnz:
table[3, 5] = 10;
Aada tamamlanm bir rnek grlyor. Bu rnekte, iki boyutlu bir diziye 1den 12ye
kadar saylar yklenmekte ve dizinin ierii ekranda gsterilmektedir.
// iki boyutlu bir diziyi gosterir.

using System;

class TwoD {
public static void Main() {
int t, i;
int[,] table = new int[3, 4];

for(t = 0; t < 3; ++t) {
for(i = 0; i < 4; ++i) {
table[t, i] = (t * 4) + i + 1;
Console.Write(table[t,i] + );
}
Console.WriteLine();
}
}
}
Bu rnekte table[0,0], 1 deerini; table[0,1], 2 deerini; table[0,3], 3 deerini
alr vs. table[2, 3]n deeri 12 olacaktr. Kavramsal olarak, dizi ekil 7 ldeki gibi
grnecektir.
NOT
C, C++ veya Java biliyorsanz, ok boyutlu dizileri deklare ederken veya bu
dizi elemanlarna eriirken dikkatli olun. Bu dillerde, dizi boyutlarnn ve
indekslerinin her biri kendi keli parantezleri iinde belirtilir. C#ta ise
virgl kullanlarak boyutlar birbirinden ayrlr.

HERKES N C#
KISIM I C# DL

164
veya Daha Fazla Boyutlu Diziler
C#, ikiden fazla boyutlu dizilere imkan vermektedir. ok boyutlu bir dizi deklarasyonunun
genel yaps u ekildedir:
tip[, ...,] isim = new tip[byklk1, byklk2, ..., byklkN];

0 1 2 3 sa indeks
0 1 2 3 4
1 5 6 7 8

2 9 10 11 12



sol indeks table[1, 2]

EKL 7.1: TwoD programyla oluturulan table dizisinin kavramsal grnm
rnein, aadaki deklarasyon 4x10x3 byklnde boyutlu bir tamsay dizisi
oluturur:
int[,,] multidim = new int[4, 10, 3];
multidimin 2,4,1 konumundaki elemanna 100 deerini atamak iin u ifadeyi
kullann:
multidim[2, 4, 1] = 100;
te size, 3x3x3 matris deerlerini tutmak iin boyutlu bir dizi kullnan bir program.
Program, daha sonra, kpn kegenlerinden biri zerindeki deerlerin toplamn bulmaktadr.
// 3x3x3luk matrisin kosegeni zerindeki sayilarin toplamini bulur.

using System;

class ThreeDMatrix {
public static void Main() {
int[,,] m = new int[3, 3, 3];
int sum = 0;
int n = 1;

for(int x = 0; x < 3; x++)
for(int y = 0; y < 3; y++)
for(int z = 0; z < 3; z++)
m[x, y, z] = n++;

sum = m[0,0,0) + m[1,1,1] + m[2,2,2];

Console.WriteLine(Sum of first diagonal: + sum);
BLM 7: DZLER VE KARAKTER KATARLARI

HERKES N C#
165
}
}
kt aadaki gibidir:
Sum of first diagonal: 42
ok Boyutlu Dizileri lk Kullanma Hazrlamak
ok boyutlu bir dizinin ilk kullanma hazrlanmas, her boyutun ilk deer listesini kendi
kme parantezleri iine alarak gerekletirilir. rnein, iki boyutlu bir dizi iin ilk kullanma
hazrlama ileminin genel yaps aada gsterilmitir:
tip[,] dizi_ismi = {
{ deer, deer, deer, ..., deer },
{ deer, deer, deer, ..., deer },
.
.
.
{ deer, deer, deer, ..., deer },
};
Burada deer, atanacak ilk deeri gsterir. bloklarn her biri bir satra karlk gelir.
Her satr iinde, ilk deer dizinin ilk konumunda, ikinci deer ikinci konumda saklanacaktr vs.
lk deer bloklarnn virgl ile ayrldna ve kapan kme parantezinden sonra noktal virgl
geldiine dikkat edin.
rnein, aadaki program sqrs adnda bir diziye 1 ile 10 arasndaki saylar ve bunlarn
karelerini ilk deer olarak atamaktadr:
// Iki boyutlu bir diziyi ilk kullanima hazirla.

using System;

class Squares {
public static void Main() {
int[,] sqrs = {
{ 1, 1 },
{ 2, 4 },
{ 3, 9 },
{ 4, 16 },
{ 5, 25 },
{ 6, 36 },
{ 7, 49 },
{ 8, 64 },
{ 9, 81 },
{ 10, 100 }
};
int i, j;

for(i = 0; i < 10; i++) {
for(j = 0; j < 2; j++)
Console.Write(sqrs[i,j] + );

HERKES N C#
KISIM I C# DL

166
Console.WriteLine();
}
}
}
Programn kts yle olur:
1 1
2 4
3 9
4 16
5 25
6 36
7 49
8 64
9 81
10 100

Dzensiz Diziler
nceki rneklerde, iki boyutlu bir dizi oluturduunuzda C#ta dikdrtgensel dizi olarak
adlandrlan bir dizi oluturmu oluyordunuz. ki boyutlu bir diziyi bir tablo olarak dnrsek,
dikdrtgensel bir dizi, satrlarn her birinin btn bir dizi iin ayn uzunlukta olduu iki boyutlu
bir dizidir. Ancak, C#ta ayrca dzensiz dizi (jagged array) denilen zel tipte iki boyutlu dizi
oluturmanza da imkan verilir. Bir dzensiz dizi, her biri farkl uzunlukta dizilerin oluturduu
bir dizidir. Bylece, satr uzunluklar ayn olmayan tablolar oluturmak iin bir dzensiz dizi
kullanlabilir.
Dzensiz diziler, boyutlarn her biri bir ift keli parantez kullanlarak gsterilecek
ekilde deklare edilir. rnein, iki boyutlu dzensiz bir dizi deklare etmek iin, u genel yapy
kullanacaksnz:
tip[][] dizi-ismi = new tip[byklk][ ];
Burada byklk, dizideki satr saysn gsterir. Satrlarn kendileri iin yer
ayrlmamtr. Bunun yerine, satrlar iin tek tek yer ayrlr. Bu, her satrn uzunluunun farkl
olmasna imkan verir. rnein aadaki kod, jaggedin ilk boyutu iin deklare edilirken
bellekte yer ayrr. Sonra, ikinci boyut iin ayrca yer ayrr.
int[][] jagged = new int[3][];
jagged[0] = new int[4];
jagged[1] = new int[3];
jagged[2] = new int[5];
Bu ifade sekans gereklendikten sonra jagged u ekilde grnr:

BLM 7: DZLER VE KARAKTER KATARLARI

HERKES N C#
167


jagged[0][0] jagged[0][1] jagged[0][2] jagged[0][3]
jagged[1][0] jagged[1][1] jagged[1][2]
jagged[2][0] jagged[2][1] jagged[2][2] jagged[2][3] jagged[2][4]

Dzensiz dizilerin isimlerinin nereden geldii aka grlyor!
Bir dzensiz dizi oluturulduu andan itibaren dizinin elemanlarna, her indeks kendi
keli parantezi iinde belirtilerek eriilebilir rnein, jaggedin 2, 1 konumundaki
elemanna 10 deerini atamak iin u ifadeyi kullanrsnz:
jagged[2][l] = 10;
Bunun bir dikdrtgensel dizinin elemanna erimek iin kullanlan sz diziminden farkl
olduuna dikkat edin.
Aadaki program iki boyutlu dzensiz bir dizi oluturmay gsteriyor:
// Duzensiz dizileri gosterir.

using System;

class Jagged {
public static void Main() {
int[][] jagged = new int[3][];
jagged[0] = new int[4];
jagged[1] = new int[3];
jagged[2] = new int[5];

int i;

// birinci diziye deger yukle
for(i = 0; i < 4; i++)
jagged[0][i] = i;

// ikinci diziye deger yukle
for(i = 0; i < 3; i++)
jagged[1][i] = i;

// ucuncu diziye deger yukle
for(i = 0; i < 5; i++)
jagged[2][i] = i;

// birinci dizideki degerleri goster
for(i = 0; i < 4; i++)
Console.Write(jagged[0][i] + );

Console.WriteLine();


HERKES N C#
KISIM I C# DL

168
// ikinci dizideki degerleri goster
for(i = 0; i < 3; i++)
Console.Write(jagged[1][i] + );

Console.WriteLine();

// ucuncu dizideki degerleri goster
for(i = 0; i < 5; i++)
Console.Write(jagged[2][i] + );

Console.WriteLine();
}
}
kt aadaki gibidir:
0 1 2 3
0 1 2
0 1 2 3 4
Dzensiz diziler, uygulamalarn tmnde kullanlmaz, ama baz durumlarda etkili
olabilirler. rnein ii ok fazla dolu olmayan (yani elemanlarn tm kullanlmayacak olan)
ok byk bir iki boyutlu diziye ihtiya duyuyorsanz, dzensiz dizi mkemmel bir zm
olabilir.
Son bir husus: Dzensiz diziler, dizilerden oluan diziler olduu iin her dizinin ayn cinste
olmas gerekli deildir. Sz gelii, aadaki ifade iki boyutlu dizilerden oluan bir dizi
tanmlar:
int[][,] jagged = new int[3][,];
Bir sonraki ifade, jagged[0]a 4x2lik bir diziyi gsteren bir referans atar:
jagged[0] = new int[4, 2];
Aadaki ifade, jagged[0][1,0]a bir deer atar:
jagged[0][1,0] = i;
Dizi Referanslarn Atamak
Tpk dier nesneler gibi, bir dizi referans deikenini bir dierine atadnzda sadece
deikenin ilikili olduu nesneyi deitiriyorsunuz. Ne dizinin bir kopyasnn karlmasna,
ne de dizinin ieriinin bir baka diziye kopyalanmasna neden olmuyorsunuz rnein,
aadaki program ele aln:
// dizi referans degiskenlerini atamak.

using System;

class AssignARef {
public static void Main() {
int i;
BLM 7: DZLER VE KARAKTER KATARLARI

HERKES N C#
169

int[] nums1 = new int[10l;
int[] nums2 = new int[10];

for(i = 0; i < 10; i++) nums1[i] = i;

for(i = 0; i < 10; i++) nums2[i] = -i;

Console.Write(Here is nums1: );
for(i = 0; i < 10; i++)
Console.Write(nums1[i] + );
Console.WriteLine();

Console.Write(Here is nums2: );
for(i = 0; i < 10; i++)
Console.Write(nums2[i] + );
Console.WriteLine();

nums2 = nums1; // artik nums2, nums1 ile iliskili

Console.Write(Here is nums2 after assignment: );
for(i = 0; i < 10; i++)
Console.Write(nums2[i] + );
Console.WriteLine();

// simdi nums2 uzerinden, nums1 dizisi uzerinde islem yap
nums2[3] = 99;

Console.Write(Here is nums1 after change through nums2: );
for(i = 0; i < 10; i++)
Console.Write(nums1[i] + );
Console.WriteLine();
}
}
Programn kts aada gsterilmitir:
Here is nums1: 0 1 2 3 4 5 6 7 8 9
Here is nums2: 0 -1 -2 -3 -4 -5 -6 -7 -8 -9
Here is nums2 after assignment: 0 1 2 3 4 5 6 7 8 9
Here is nums1 after change through nums2: 0 1 2 99 4 5 6 7 8 9
ktdan grldg gibi, nums2ye nums1in atanmasndan sonra her iki dizi referans
deikenleri de ayn nesneyi gstermekteler.
Length zelliini Kullanmak
C#ta diziler nesne olarak gereklendikleri iin bu durum birtakm avantajlar dourur. Bu
avantajlardan biri Length zelliinden kaynaklanmaktadr. Length, dizinin tutabilecei
eleman saysn ierir. Bylece, her dizi dizinin uzunluunu ieren bir alan da beraberinde
tar. te, bu zellii gsteren bir program:
// Length dizi ozelligini kullan.

HERKES N C#
KISIM I C# DL

170

using System;

class LengthDemo {
public static void Main() {
int[] nums = new int[10];

Console.WriteLine(Length of nums is + nums.Length);

// nums'a ilk deger atamak icin Length'i kullan
for (int i = 0; i < nums.Length; i++)
nums[i] = i * i;

// simdi, nums'i gostermek icin Length'i kullan
Console.Write(Here is nums: );
for(int i = 0; i < nums.Length; i++)
Console.Write(nums[i] + );

Console.WriteLine();
}
}
Bu program ekranda aadaki kty gsterir:
Length of nums is 10
Here is nums: 0 1 4 9 16 25 36 49 64 81
LengthDemonun iinde nums.Lengthin, for dngsnde sz konusu tekrar saysn
kontrol etmek iin dng tarafndan ne ekilde kullanldna dikkat edin. Her dizi kendi
uzunluunu birlikte tad iin, dizinin bykln elle takip etmek yerine bu bilgiyi
kullanabilirsiniz. Lengthin deerinin, gerekte kullanmda olan eleman says ile ilgili
olmadn hatrnzda tutun. Length, dizinin tutabilecei eleman saysn ierir.
ok boyutlu dizilerin uzunluu elde edilirken dizinin tutabilecei toplam eleman says
dndrlr. rnein;
// Uc boyutlu bir dizi uzerinde Length dizi ozelligini kullan.

using System;

class LengthDemo3D {
public static void Main() {
int[,,] nums = new in[{10, 5, 6];

Console.WriteLine(Length of nums is + nums.Length);
}
}
kt aadaki gibidir:
Length of nums is 300
BLM 7: DZLER VE KARAKTER KATARLARI

HERKES N C#
171
ktnn da dorulad gibi, Length, numsn tutabilecei eleman saysn elde eder. Bu
rnekte eleman says 300dr (10x5x6). Belirli bir boyutun uzunluunu elde etmek mmkn
deildir.
Length zelliinin dahil edilmesi belirli tipteki dizi ilemlerinin daha kolay - ve daha
gvenli - gerekletirilmesini salad iin bu sayede birok algoritma sadeletirilmektedir.
Sz gelii, aadaki program, Length zelliini kullanarak bir dizinin elemanlarn arkadan
ne doru bir baka diziye kopyalayp dizinin ieriini ters evirmektedir.
// Diziyi ters cevir.

using System;

class RevCopy {
public static void Main() {
int i,j;
int[] nums1 = new int[10];
int[] nums2 = new int[10];

for(i = 0; i < nums1.Length; i++) nums1[i] = i;

Console.Write(Original contents: );
for(i = 0; i < nums2.Length; i++)
Console.Write(nums1[i] + );

Console.WriteLine();

// nums1'den nums'ye tersten kopyalama
if(nums2.Length >= nums1.Length) /* nums2nin yeterli
uzunlukta oldugundan
emin ol */
for(i=0, j=nums1.Length-1; i < nums1.Length; i++, j--)
nums2[j] = nums1[i];

Console.Write(Reversed contents: );
for(i = 0; i < nums2.Length; i++)
Console.Write(nums2[i] + );

Console.WriteLine();
}
}
kt yle olur:
Original contents: 0 1 2 3 4 5 6 7 8 9
Reversed contents: 9 8 7 6 5 4 3 2 1 0
Bu rnekte Length, iki nemli ilevi gerekletiriyor. Birincisi; Length, hedef dizinin,
kaynak dizinin ieriini tutabilecek byklkte olduunu dorulamak iin kullanlyor. kincisi;
Length, ters kopyalama ilemini gerekletiren for dngs iin sonlanma koulu salyor.
Bu

basit rnekte dizilerin bykl elbette kolaylkla biliniyor, ama ayn yntem daha
zorlayc, ok eitli durumlara uygulanabilir.

HERKES N C#
KISIM I C# DL

172
Dzensiz Dizilerde Length Kullanmak
Lengthin dzensiz dizilerle birlikte kullanlmas zel bir durumdur. Bu durumda, her
dizinin tek tek uzunluunu elde etmek mmkn olur. rnein, drt dml bir a zerinde
CPU etkinliini simle eden aadaki program ele aln:
// Duzensiz dizilerle Length kullanimini gosterir.

using System;

class Jagged {
public static void Main() {
int[][] network_nodes = new int[4][];
network_nodes[0] = new int[3];
network_nodes[1] = new int[7];
network_nodes[2] = new int[2];
network_nodes[3] = new int[5];

int i, j;

// Baz sahte CPU kullanm verileri uyduralim
for(i = 0; i < network_nodes.Length; i++)
for(j = 0; j < network_nodes[i].Length; j++)
network nodes[i][j] = i * j + 70;

Console.WriteLine(Total number of network nodes: +
network_nodes.Length + \n);

for(i = 0; i < network_nodes.Length; i++) {
for(j = 0; j < network_nodes[i].Length; j++) {
Console.Write(CPU usage at node. + i + CPU +
j + ; );
Console.Write(network_nodes[i][j] + % );
Console.WriteLine();
}
Console.WriteLine();
}
}
}
kt aada gsterilmitir:
Total number of network nodes: 4
CPU usage at node 0 CPU 0: 70%
CPU usage at node 0 CPU 1: 70%
CPU usage at node 0 CPU 2: 70%

CPU usage at node 1 CPU 0: 70%
CPU usage at node 1 CPU 1: 71%
CPU usage at node 1 CPU 2; 72%
CPU usage at node 1 CPU 3: 73%
CPU usage at node 1 CPU 4: 74%
CPU usage at node 1 CPU 5: 75%
CPU usage at node 1 CPU 6: 76%
BLM 7: DZLER VE KARAKTER KATARLARI

HERKES N C#
173

CPU usage at node 2 CPU 0; 70%
CPU usage at node 2 CPU 1: 72%

CPU usage at node 3 CPU 0: 70%
CPU usage at node 3 CPU 1: 73%
CPU usage at node 3 CPU 2: 76%
CPU usage at node 3 CPU 3: 79%
CPU usage at node 3 CPU 4: 82%
network_nodes dzensiz dizisi zerinde Lengthin ne ekilde kullanldna zellikle
dikkat edin. Hatrlarsanz, iki boyutlu dzensiz dizi, dizilerden oluan bir dizidir. Bylece,
aadaki ifade kullanldnda, network_nodes iinde saklanan dizilerin says elde edilir;
network_nodes.Length
Bu rnekte bu say 4tr. Dzensiz bir dizi iinde herhangi bir dizinin uzunluunu elde et-
mek iin aadaki gibi bir deyim kullanrsnz:
network_nodes[0].Length
Yukardaki deyim, ilk dizinin uzunluunu elde eder.
foreach Dngs
C#ta foreach olarak adlandrlan bir dngnn tanml olduundan, Blm 5te
bahsedilmiti, fakat bu ifadeyle ilgili aklamalar ileriki konulara braklmt. te bu
aklamalarn zaman artk geldi.
foreach dngs, bir koleksiyonun elemanlar zerinde ilerleyerek tekrarlamak iin
kullanlr. Koleksiyon, bir grup nesneden ibarettir. C#ta birka tip koleksiyon tanmldr.
Bunlardan biri de dizidir. foreachin genel yaps aadaki gibidir:
foreach(tip deiken-ismi in koleksiyon) ifade;
Burada tip deiken-ismi, foreach iterasyon yaparken koleksiyonun
elemanlarndan deer alacak olan iterasyon deikeninin tipini ve ismini belirtir. zerinde
ilerlenecek olan koleksiyon, koleksiyon ile belirtilir. Bu rnekte koleksiyon, bir dizidir. Bu
nedenle tip, dizinin temel tipi ile ayn (veya uyumlu) olmaldr. Hatrlanmas gereken nemli
bir nokta, diziler sz konusu olduu srece iterasyon deikeninin salt okunur olduudur. Yani,
iterasyon deikenine yeni bir deer atayarak dizinin ieriini deitiremezsiniz.
te, foreach kullanlan basit bir rnek. Bu rnekte, bir tamsay dizisi oluturuluyor ve bu
dizi ilk kullanma hazrlanyor. Daha sonra, bu deerler bir yandan toplanrken dier yandan
ekranda gsteriliyor.
// foreach dongusunu kullanir.

using Syatem;


HERKES N C#
KISIM I C# DL

174
class ForeachDemo {
public static void Main() {
int sum = 0;
int[] nums = new int[10];

// numsa bazi degerler ata
for(int i = 0; i < 10; i++)
nums[i] = i;

// degerleri gostermek ve toplamak icin foreach kullan
foreach(int x in nums) {
Console.WriteLine(Value is: + x);
sum += x;
}
Console.WriteLine(Summation: + sum);
}
}
Programn kts aada gsterilmitir:
Value is: 0
Value is: 1
Value is: 2
Value is: 3
Value is: 4
Value is: 5
Value is: 6
Value is: 7
Value is: 8
Value is: 9
Summation: 45
Bu ktdan grld gibi; foreach, bir dizi iinde en dk indeksten en yksek
indekse doru tekrarlar.
foreach dngs, bir dizi iindeki tm elemanlar incelenene kadar iterasyonu srdrme-
sine ramen, foreach dngsn break kullanarak daha erken sona erdirmek mmkndr.
rnein, bu program numsn sadece ilk be elemann toplar:
// foreach ile birlikte break kullan.

using System;

class ForeachDemo {
public static void Main() {
int sum = 0;
int[] nums = new int[10];

// nums'a bazi degerler ver
for(int i = 0; i < 10; i++)
nums[i] = i;

// degerleri toplamak ve gostermek icin foreach kullan
foreach(int x in nums) {
BLM 7: DZLER VE KARAKTER KATARLARI

HERKES N C#
175
Console.WriteLine(Value is: + x);
sum += x;
if(x == 4) break; // 4 elde edilince donguyu durdur
}
Console.WriteLine(Summation of first 5 elements: + sum);
}
}
Elde edilen kt yle olur:
Value is: 0
Value is: 1
Value is: 2
Value is: 3
Value is: 4
Summation of first 5 elements: 10
Grld gibi, foreach dngs beinci eleman elde edilince durur.
foreach, ok boyutlu diziler zerinde de alr. Satr srasna gre ilk satrdan sonuncu
satra kadar ilgili elemanlar dndrr.
// foreach'i iki boyutlu dizi uzerinde kullan.

using System;

class ForeachDemo2 {
public static void Main() {
int sum = 0;
int[,] nums = new int[3,5];

// nums'a bazi degerler ver
for(int i = 0; i < 3; i++)
for(int j = 0; j < 5; j++)
nums[i,j] = (i+1)*(j+1);

// degerleri toplamak ve gostermek icin foreach kullan
foreach(int x in nums) {
Console.WriteLine(Value is: + x);
sum += x;
}
Console.WriteLine(Summation: + sum);
}
}
Bu programn kts aada gsterilmitir:
Value is: 1
Value is: 2
Value is: 3
Value is: 4
Value is: 5
Value is: 2
Value is: 4
Value is: 6

HERKES N C#
KISIM I C# DL

176
Value is: 8
Value is: 10
Value is: 3
Value is: 6
Value is: 9
Value is: 12
Value is: 15
Summation: 90
foreach, bir dizi zerinde, yalnzca, dizinin bandan sonuna, srayla ilerleyebildii iin,
bu dngnn kullanmnn kstl olduunu dnebilirsiniz. Oysa, bu doru deildir. ok
sayda algoritmada tam olarak bu mekanizmaya gerek duyulur. Bu algoritmalardan en yaygn
olan da arama algoritmalardr. rnein, aadaki program bir dizi iinde bir deer aramak
iin foreach dngs kullanmaktadr. Deer bulunursa dng sona erer.
// foreach kullanarak bir diziyi aramak.

using System;

class Search {
public static void Main() {
int[] nums = new int[10];
int val;
bool found = false;

// nums'a bazi degerler ver
for(int i = 0; i < 10; i++)
nums[i] = i;

val = 5;

// numsda bir anahtar deger aramak icin foreach kullan
foreach(int x in nums) {
if(x == val) {
found = true;
break;
}
}

if(found)
Console.WriteLine(Value found!);
}
}
Dier foreach uygulamalar arasnda ortalama hesab, bir kmenin en dk ve en
yksek deerlerini bulmak, ift deerleri aramak gibi uygulamalar yer alr. Elinizdeki kitapta
daha sonra greceiniz gibi foreach, dier tipteki koleksiyonlar zerinde iiem yaparken de
zellikle kullanldr.


BLM 7: DZLER VE KARAKTER KATARLARI

HERKES N C#
177
Karakter Katarlar
Programlamayla ilgili grler gnden gne deise de, C#n en nemli veri tiplerinden
biri stringdir. string, karakter katarlarn tanmlar ve destekler. Dier birok programlama
dilinde string, bir karakter dizisidir. Oysa, C#ta byle bir durum sz konusu deildir. C#ta
string, bir nesnedir. Yani, string bir referans tipidir. C#ta string standart bir veri tipi
olmasna ramen, string ile ilgili aklamalarn snf ve nesneler tantlana kadar beklemesi
gerekliydi.
Aslnda siz, string snfn Blm 2den beri kullanmaktasnz, fakat bunu
bilmiyordunuz. Bir karakter katar literali oluturduunuz zaman aslnda bir string nesnesi
oluturmu oluyorsunuz. rnein, u ifadede
Console.WriteLine(In C#, strings are objects.);
In C#, strings are objects. karakter katar, C# tarafndan otomatik olarak bir
string nesnesi haline getirilir. Yani, nceki programlarda string smfnn kullanm arka
plandayd. Bu bolmde bunlarn aka nasl ele alndn reneceksiniz.
Karakter Katarlarn Oluturmak
Bir string oluturmann en kolay yolu, karakter katar literali kullanmaktr. rnein,
burada str, bir string referans deikenidir. stra, bir karakter katar literalini gsteren bir
referans atanmaktadr:
string str = C# strings are powerful.;
Bu rnekte, stra ilk deer olarak C# strings are powerful karakter sekans
atanmaktadr.
Aynca, bir char dizisinden de bir string oluturabilirsiniz. rnein:
char[] charray = {'t', 'e', 's', 't'};
string str = new string(charray);
Bir kez bir string nesnesi oluturduktan sonra, trnak iinde karakter katarlarna izin
verilen her yerde bunu kullanabilirsiniz. rnein, aadaki rnekte gsterildii gibi, bir
string nesnesini WriteLine()a argman olarak kullanabilirsiniz:
// Karakter katarlarini tanitir.

using System;

class StringDemo {

public static void Main() {

char[] charray = {A, ' ', 's', 't, 'r, 'i', n', 'g, '.' };
string str1 = new string(charray);

HERKES N C#
KISIM I C# DL

178
string str2 = Another string.;

Console.WriteLine(str1);
Console.WriteLine(str2);
}
}
Programn kts aada gsterilmitir:
A string.
Another string.
Karakter Katarlar zerinde lem Yapmak
string snf, karakter katarlar zerinde ilem yapan birka metot ierir. Tablo 7.1de
bunlarn birka gsterilmektedir.
string tipi, karakter katarnn uzunluunu ieren Length zelliine de sahiptir.
Bir karakter katarnn iinde yer alan karakterlerin deerlerini tek tek elde etmek iin
sadece indeks kullanmanz yeterlidir. rnein,
string str = test;
Console.WriteLine(str[0]);
Bu rnekte, testin ilk karakteri olan t ekranda gsterilir. Tpk diziler gibi,
karakter katar indeksleri de sfrdan balar. Ancak nemli bir husus, indeks kullanarak bir
karakter katar iindeki bir karaktere yeni bir deer atayamyor olmanzdr. ndeks yalnzca
karakterleri elde etmek iin kullanlabilir.
ki karakter katarnn eit olup olmadn test etmek iin == operatrn kullanabilirsiniz.
Normal olarak, == operatr, nesne referanslarna uygulandnda her iki referansn da ayn
nesneyle balantl olup olmadn belirler. Ancak bu durum, string tipindeki nesneler iin
farkldr. == operatr iki string referansna uygulandnda, string ieriklerinin kendileri
eitlik asndan karlatrlr. Ayn durum != operatr iin de geerlidir; string nesneleri
karlatrldnda stringlerin ierikleri karlatrlr. Ancak, dier ilikisel operatrler, sz
gelii <, > ya da =, tpk dier nesne tiplerinde olduu gibi referanslar karlatrrlar.

TABLO 7.1: En Yaygn Karakter Katar Dzenleyici Metotlar


Metot Anlam
static string Copy(string str) strn bir kopyasn dndrr.
int CompareTo(string str)
Metodu aran karakter katar strdan kkse sfrdan
kk bir deer dndrr; strdan bykse, sfrdan
byk bir deer dndrr; karakter katarlar eitse, sfr
dndrr.
BLM 7: DZLER VE KARAKTER KATARLARI

HERKES N C#
179
int IndexOf(string str)
Metodu aran karakter katar iinde str ile belirtilen
alt karakter katarn arar. lk elemenin indeksini
dndrr. Eleme olmamas durumunda -1 dndrr.
int LastIndexOf(string str)
Metodu aran karakter katar iinde str ile belirtilen
alt karakter katarn arar. Son elemenin indeksini
dndrr. Eleme olmamas durumunda -1 dndrr.
string ToLower() Metodu aran karakter katarnn kk harfli
versiyonunu dndrr.
string ToUpper() Metodu aran karakter katarnn byk harfli
versiyonunu dndrr.
Aada, birka string ilemini gsteren bir program gryorsunuz:
// Bazi string islemleri.

using System;

class StrOps {
public static void Main() {
string str1 =
When it comes to .Net programming, C# is #1.;
string str2 = string.Copy(str1);
string str3 = C# strings are powerful.;
string strUp, strLow;
int result, idx;

Console.WriteLine(str1: + str1);

Console.WriteLine(Length of str1: + str1.Length);

// str1'in buyuk ve kucuk harfli versiyonlarini olustur
strLow = str1.ToLower();
strUp = str1.ToUpper();
Console.WriteLine(Lowercase version of str1:\n +

strLow);
Console.WriteLine(Uppercase version of str1:\n +
strUp);

Console.WriteLine();

//str1i her seferinde bir karakter goruntulenecek sekilde goster
Console.WriteLine(Display str1, one char at a time.);
for(int i=0; i < str1.Length; i++)
Console.Write(str1[i]);
Console.WriteLine(\n);

// karakter katarlarini karsilastir
if(str1 == str2)
Console.WriteLine(str1 == str2);
else
Console.WriteLine(str1 != str2);

HERKES N C#
KISIM I C# DL

180

if(str1 == str3)
Console.WriteLine(strl == str3);
else
Console.WriteLine(str1 != str3);

result = str1.CompareTo(str3);
if(result == 0)
Console.WriteLine(str1 and str3 are equal);
else if(result < 0)
Console.WriteLine(str1 is less than str3);
else
Console.WriteLine(str1 is greater than str3);

Console.WriteLine();

// yeni karakter katarini str2ye ata
str2 = One Two Three One;

// karakter katarini ara
idx = str2.IndexOf(One);
Console.WriteLine(Index of first occurrence of One: + idx);
idx = str2.LastIndexOf(One);
Console.WriteLine(Index of last occurrence of One: + idx);
}
}
Bu program aadaki kty retir:
strl: When it comes to .NET programming, C# is #1.
Length of str1: 44
Lowercase version of str1:
when it comes to .net programming, c# is #1.
Uppercase version of str1:
WHEN IT COMES TO .NET PROGRAMMING, C# IS #1.

Display str1, one char at a time.
When it comes to .NET programming, C# is #1.

str1 == str2
str1 != str3
str1 is greater than str3

Index of first occurrence of One: 0
Index of last occurrence of One: 14

+ operatrn kullanarak iki karakter katarn bititirebilirsiniz (pepee ekleyebilirsiniz).
rnein, u ifade str4e OneTwoThree karakter katarn atar.
string str1 = One;
string str2 = Two;
string str3 = Three;
string str4 = str1 + str2 + str3;
BLM 7: DZLER VE KARAKTER KATARLARI

HERKES N C#
181
Bir dier husus: string anahtar kelimesi, .NET Framework snf ktphanesi tarafndan
tanmlanan System.String iin kullanlan bir takma isimdir (alias) (yani, dorudan
System.String ile elenir). Bylece, string tarafndan tanmlanan alanlar ve metotlar,
burada gsterilen rneklerden ok daha fazlasn ieren System.String snfna aittir.
System.String, Ksm IIde ayrntlaryla incelenmektedir.
Karakter Katar Dizileri
Tpk dier veri tipleri gibi, karakter katarlar da diziler iine toplanabilir. rnein:
// Karakter katari dizilerini gosterir.

using System;

class StringArrays {
public static void Main() {
string[] str = { This, is, a, test. };

Console.WriteLine(Original array: );
for(int i=0; i < str.Length; i++)
Console.Write(str[i] + );
Console.WriteLine(\n);

// karakter katarini degistir
str[1] = was;
str[3] = test, too!;

Console.WriteLine(Modified array: );
for(int i=0; i < str.Length; i++)
Console.Write(str[i] + );
}
}
Bu programn kts yle olur:
Original array:
This is a test.

Modified array:
This was a test, too!
te ok daha ilgin bir rnek. Aadaki program, kelimeleri kullanarak bir tamsayy
ekranda gsterir. rnein, 19 deeri - ngilizce one nine olarak gsterilir.
// Bir tamsayinin basamaklarini kelimelerle gosterir.

using System;

class ConvertDigitsToWords {
public static void Main() {
int num;
int nextdigit;
int numdigits;

HERKES N C#
KISIM I C# DL

182
int[] n = new int[20];

string[] digits = { zero, one, two, three, four,
five, six, seven, eight,
nine };

num = 1908;

Console.WriteLine(Number: + num);

Console.Write(Number in words: );

nextdigit = 0;
numdigits = 0;

/*n'nin icinde saklanan basamaklari al. Bu basamaklar ters
sirada saklanmistir. */
do {
nextdigit = num % 10;
n[numdigits] = nextdigit;
numdigits++;
num = num / 10;
} while(num > 0);
numdigits--;

// kelimeleri goster
for( ; numdigits >= 0; numdigits--)
Console.Write(digits[n[numdigits]] + );

Console.WriteLine();
}
}
kt aadaki gibidir:
Number: 1908
Number in words: one nine zero eight
Programda digits adndaki string dizisi, basamaklarn sfrdan dokuza kadar kelime
olarak karlklarn srasyla tutar. Program, bir tamsayy u ekilde kelimelere dntrr: En
sadaki basamaktan balayarak tamsaynn basamaklarnn her birini elde eder ve bunlar n
adndaki bir int dizisinde ters srada saklar. Sonra program, bu dizi zerinde arkadan ne
doru ilerler. Bu ilem srasnda ndeki her tamsay deer digits iin indeks olarak kullanlr
ve karlk gelen karakter katar ekranda gsterilir.
Karakter Katarlar Deimez
te sizi artabilecek bir konu: Bir string nesnesinin ierii kesindir, deitirilemez.
Yani, bir kez oluturduktan sonra karakter katarn meydana getiren karakter sekansn
deitiremezsiniz. Bu kstlama, karakter katarlarnn C#ta daha verimli gereklenmesine
imkan verir. Bu ciddi bir dezavantaj gibi grnse bile, aslnda deildir. nceden mevcut bir
karakter katarnn deitirilmi bir versiyonuna ihtiyacnz varsa, istenilen karakter katarn
BLM 7: DZLER VE KARAKTER KATARLARI

HERKES N C#
183
ieren yeni bir karakter katar oluturmanz yeterlidir. Kullanlmayan karakter katar nesneleri,
anlamsz veri kapsamnda otomatik olarak toplanaca iin, kullanlmayan karakter katarlarna
ne olaca konusunda endie etmenize gerek yoktur.
Ancak, bir konuya aklk getirmek gerekiyor: string referans deikenleri, balantl
olduklar nesneleri elbette deitirebilirler. Oluturulduktan sonra deitirilemeyecek olan,
belirli bir string nesnesinin ieriidir.
Deitirilemez karakter katarlarnn neden bir engel olmadn tam olarak anlamak iin bir
baka string metodu kullanacaz: Substring().Substring() metodu, kendisini aran
karakter katarnn belirli bir parasn ieren yeni bir karakter katar dndrr. Alt karakter
katarn ieren yeni bir string retildii iin orijinal karakter katar deiiklie uramaz ve
deimezlik kural halen geerli kalr. Kullanmakta olacamz Substring()in yaps
aada gsterilmitir:
string Substring(int balang, int uzunluk)
Burada balang, alt karakter katarnn balang indeksini; uzunluk ise uzunluunu
belirtir.
Substring()i ve karakter katarlarnn deimezlii prensibini gsteren bir program:
// Substring()i kullanir.

using System;

class SubStr {
public static void Main() {
string orgstr = C# makes strings easy.;

// bir alt karakter katari olustur
string substr = orgstr.Substring(5, 12);

Console.WriteLine(orgstr: + orgstr);
Console.WriteLine(substr: + substr);
}
}
Programn kts u ekildedir:
orgstr: C# makes strings easy.
substr: kes strings
Grdnz gibi, orijinal karakter katar orgstr deimeden kalr ve substr, alt
karakter katarn ierir.
Bir husus daha: string nesnelerinin deitirilemez oluu, genellikle bir kstlama ya da
engel olmamasna karn, bir karakter katarn deitirebilmenin avantajl olduu durumlar da
sz konusu olabilir. Buna imkan vermek iin C#, System.Text isim uzaynda yer alan

HERKES N C#
KISIM I C# DL

184
StringBuilder adnda bir snf sunmaktadr. Bu snf ile deitirilebilen string nesneleri
oluturulur. Ancak, ou kez StringBuilder yerine stringi kullanmay tercih edeceksiniz.
Karakter Katarlar switch fadelerinde Kullanlabilir
Bir switch ifadesini kontrol etmek iin bir string kullanlabilir. string, switchte
kullanlabilen ve int tipinde olmayan tek tiptir. Karakter katarlarnn switch ifadelerinde
kullanlabilmesi gerei, baz durumlarn olduka kolay ele alnmasn mmkn klmaktadr.
rnein, aadaki program one, two ve three kelimelerinin rakam karlklarn
ekranda gsterir:
// Bir switch ifadesini bir string kontrol edebilir.

using System;

class StringSwitch {
public static void Main() {
string[] strs = { one, two, three, two, one };

foreach(string s in strs) {
switch(s) {
case one:
Console.Write(1);
break;
case two:
Console.Write(2);
break;
case three:
Console.Write(3);
break;
}
}
Console.WriteLine();
}
}
kt aadaki gibidir:
12321




S E K Z N C B L M

METOTLAR VE SINIFLARA
DAHA YAKINDAN BR
BAKI


















8

HERKES N C#
KISIM I C# DL

186
Bu blmde snf ve metotlar incelenmeye devam ediyoruz. Bir snfn yelerine eriimin
nasl kontrol edilebilecei incelenerek blme balanyor. Sonra nesnelerin aktarlmas ve
dndrlmesi, metotlarn ar yklenmesi (overloading), Main()in eitli ekilleri, yinelenme
(recursion) ve static anahtar kelimesinin kullanm ele alnyor.
Snf yelerine Eriimi Kontrol Etmek
Verilerin paketlenmesi (encapsulation) zelliini destekleme kapsamnda snflar balca
iki avantnj salamaktadr. ncelikle; snflar, verileri kodlarla balar. Snflarn bu zeliinden
Blm 6dan beri yararlanmaktasnz. kincisi; snflar, yelere eriimi kontrol altnda tutmak
iin eitli yntemler salarlar. Burada incelenen ite bu ikinci zelliktir.
C#n yaklam bir para daha sofistike olsa da, aslnda snf yeleri iki temel tipte
toplanr: public (ak) ve private (zel). public ye, kendi snfnn dnda tanmlanm
kodlar tarafndan serbeste eriilebilir. u aamaya kadar kullanmakta olduumuz snf yeleri
bu tiptendir. private ye ise, yalnzca kendi snf iinde tanmlanm metotlar tarafndan
eriilebilir. Eriim, private yelerin kullanm sayesinde kontrol edilir.
Bir snfn yelerine eriimi kstlamak nesne ynelimli programlamann en temel paras-
dr, nk bu, bir nesnenin yanl kullanmn nlemeye yardmc olur. iyi tanmlanm
birtakm metotlar yoluyla yalnzca private verilere eriim imkan vererek sz konusu verilere
uygunsuz deerlerin atanmasn nleyebilirsiniz -deer aral kontrol yaparak, rnein. Snfn
dnda kalan kodun private bir verinin deerini dorudan ayarlamas mmkn deildir.
Ayrca, bir nesnenin iindeki verilerin nasl ve ne zaman kullanldn da tam olarak kontrol
edebilirsiniz. Bylece, doru olarak uygulandnda bir snf, rahatlkla kullanlabilecek, fakat
dahili almas kurcalamaya ak olmayan bir "kara kutu" oluturur.
C#ta Eriim Belirleyicileri
ye eriim kontrol, drt adet eriim belirleyicisinin kullanm sayesinde elde edilir:
public, private, protected ve internal. Bu blmde public ve private ile
ilgileneceiz. protected niteleyicisi yalnzca kaltm sz konusu olduunda uygulanr ve
Blm 9da anlatlacaktr. internal niteleyicisi, daha ok assembly kullanmna uygulanr.
Assembly de C#ta genel bir tanmla bir program anlamna gelir. internal niteleyicisi Blm
l6da incelenmektedir.
Bir snfn bir yesi public belirleyicisi ile nitelendiinde bu ye, programnzdaki
herhangi bir kod tarafndan eriilebilir. Dier snflarn iinde tanmlanan metotlar da bu
kapsamda yer alr.
Bir snfn bir yesi private olarak belirtilmise bu ye, yalnzca kendi snfnn dier
yeleri tarafndan eriilebilir. Bylece, dier snflardaki metotlar bir baka snfn private
verilerine eriemezler. Blm 6da akland gibi, eer hi eriim belirleyicisi
kullanlmamsa snf yesi kendi snfna zeldir. (Yani; private varsaylan deerdir.)
BLM 8: METOTLAR VE SINIFLARA DAHA YAKINDAN BR BAKI

HERKES N C#
187
Bylece, private snf yeleri olutururken private belirleyicisini kullanmak istee
baldr.
Eriim belirleyicisi, yenin geri kalan tip spesifikasyonundan nce gelir. Yani, yenin
deklarasyon ifadesi, eriim belirleyicisi ile balamaldr. te birka rnek:
public string errMsg;
private double bal;
private bool isError(byte status) { // ...
public ve private arasndaki fark anlamak iin aadaki program ele aln:
// public ve private erisim.

using System;

class MyClass {
private int alpha; // private erisim acikca belirtiliyor
int beta; // varsayilan eriim sekli: private
public int gamma; // public erisim

/* alpha ve betaya erismek icin gerekli metotlar. Bir sinifin
bir uyesinin, ayni sinifin private uyesine erismesinde
problem yoktur.
*/
public void setAlpha(int a) {
alpna = a;
}

public int getAlpha() {
return alpha;,
}

public void setBeta(int a) {
beta = a;
}
public int getBeta() {
return beta;
}
}

class AccessDemo {
public static void Main() {
MyClass ob = new MyClass();

/* alpha ve beta'ya erisim yalnizca metotlar yardimiyla
mmkndr. */
ob.setAlpha(-99);
ob.setBeta(19);
Console.WriteLine(ob.alpha is + ob.getAlpha());
Console.WriteLine(ob.beta is + ob.getBeta());

// alpha veya beta'ya bu sekilde erisemezsiniz:
// ob.alpha = 10; // Yanlis! alpha private'tir!

HERKES N C#
KISIM I C# DL

188
// ob.beta = 9; // Yanlis! beta private'tir!

// gamma'ya dogrudan erisim olabilir cunku gamma publictir
ob.gamma = 99;
}
}
Grdnz gibi, MyClass snf iinde alpha, private olarak belirtilmektedir;
betann varsaylan deeri privatetr ve gamma ise public olarak belirtilmitir. alpha ve
beta private olduklar iin kendi snflar dndaki kod tarafndan eriilemezler, Bundan
dolay, AccessDemo snf iinde bu iki deikenin ikisi de dorudan kullanlamaz. Her ikisi
de, public olan metotlar - sz gelii setAlpha() ya da getAlpna() - yardmyla
kullanlabilir. rnein, aadaki satrn bandaki aklama simgesini kaldrmak isteseydiniz,
eriim kuralnn ignenmesinden tr bu program derleyemeyecektiniz.
// ob.alpha = 10; // Yanlis! alpha private'tir!
MyClass dnda yer alan kodun alphaya eriimine izin verilmemesine ramen,
setAlpha() ve getAlpha() metotlarndan da grld gibi MyClass iindeki metotlar
alphaya serbete eriebilirler. Bu durumun ayns beta iin de geerlidir.
Temel husus udur: Bir private ye kendi snfnn dier yeleri tarafndan serbeste
kullanlabilir, fakat kendi snfnn dnda yer alan kod tarafndan eriilemez.
Public ve Private Eriimi Uygulamak
public ve private eriimi dzgn olarak kullanmak, baarl nesne ynelimli
programlamann temel bileenidir. Kat kurallar olmasa da, klavuz alnabilecek baz genel
prensipler unlardr;
1. Bir snfn yalnzca bu snf iinde kullanlan yeleri private olmaldr.

2. Belirli bir deer aralnda olmas gereken rnek veriler private olmaldr; bu
verilere eriim, deer aral kontrol yapabilen public metotlar yardmyla
salanmaldr.

3. Eer bir ye zerinde yaplan deiikliin etkisi yenin kendisini ayorsa (yani,
nesnenin dier taraflarn da etkiliyorsa), sz konusu ye private olmal ve bu
yeye eriim kontrol altnda tutulmaldr.

4. Yanl kullanldklarnda bir nesneye zarar verebilen yeler private olmaldr. Bu
yelere eriim, yanl kullanm nleyen public metotlar yardmyla
gerekletirilmelidir.

5. private verilerin deerlerini alan ve ayarlayan (deitiren) metotlar public
olmaldr.

6. public rnek deikenlere, bu deikenlerin private olmalarn gerektiren bir
neden yoksa, izin verilir.
BLM 8: METOTLAR VE SINIFLARA DAHA YAKINDAN BR BAKI

HERKES N C#
189
Yukardaki kurallarn ele almad nanslar elbette mevcuttur; stelik, zel durumlar bir
veya daha fazla kuraln inenmesine neden olabilir. Fakat, genel olarak, bu kurallara
uyarsanz, kolaylkla yanl kullanlmayacak esnek nesneler oluturacaksnz demektir.
Eriimi Kontrol Altna Almak: Bir rnek alma
Eriim kontrolnn nasl ve niin gerekli olduunu daha iyi anlamak iin bir rnek
incelemek yararldr. Nesne ynelimli programlamann mkemmel rneklerinden biri, bir
yn gerekleyen bir snftr. Muhtemelen biliyorsunuzdur; yn, ilk giren son kar
mantna dayanan bir listeyi gerekleyen veri yapsdr. Ynn ismi, bir masa zerindeki
tabak ynna benzerliinden gelmektedir. Masaya konan ilk tabak, en son kullanlacak
olandr.
Yn, nesne ynelimli programlamann klasik rneklerindendir, nk bilgi iin gerekli
depolamay, bilgiye erimek iin gerekli metotlarla birletirir. Bu nedenle yn; ilk giren, son
kar kullanmn mecbur klan bir veri motorudur (data engine). Bu tr bir birleme, yn iin
depolama salayan yeleri private olan ve public metotlarla eriim salanan bir snf iin
mkemmel bir seenektir. Bir snfn iinde yer alan verileri d dnyadan gizleyerek yn
kullanan kodun elemanlara kural tanmadan (metotlar kullanmadan) erimesi engellenir.
Yn ile ilgili iki temel ilem tanmldr: ekleme (push) ve karma (pop). Ekleme, bir
deeri ynn en stne yerletirir. karma, ynn en stnden bir deer alr. Yani karma,
tketicidir; bir kez bir deer yndan alndktan sonra, artk yndan karlmtr, bu deere
tekrar eriilemez.
Aada gsterilen rnek, bir yn gerekleyen Stack adnda bir snf tanmlamaktadr.
Ynn temelini oluturan depolama, zel bir dizi tarafndan salanmaktadr. Ekleme ve
karma ilemleri Stack snfnn public metotlar sayesinde mmkndr. Yani, public
metotlar ilk giren son kar mekanizmasn zorunlu klar. Burada gsterildii gibi, Stack snf
karakterleri saklar, ama ayn mekanizma, herhangi bir veri tipini saklamak amacyla da
kullanlabilir:
// Karakterlerden olusan bir yigin sinifi.

using System;

class Stack {
// bu uyeler private'tir
char[] stck; // yigini tutar
int tos; // yiginin tepesinin indeksi

// buyuklugu bilinen bos bir Stack olustur
public Stack(int size) {
stck = new char[size]; // yigin iin bellek alani ayir
tos = 0;
}

// Karakterleri yigina ekle.

HERKES N C#
KISIM I C# DL

190
public void push(char ch) {
if(tos == stck.Length) {
Console.WriteLine( -- Stack is full.);
return;
}

stck[tos] = ch;
tos++;
}

// Yigindan bir karakter cikar.
public char pop() {
if(tos == 0) {
Console.writeLine( -- Stack is empty.);
return (char) 0;
}

tos--;
return stck[tos];
}

// Yigin doluysa true dondur.
public bool full() {
return tos == stck.Lengtn;
}

// Yigin bossa true dondur.
public bool empty() {
return tos == 0;
}

// Yiginin toplam kapasitesini dondur.
public int capacity() {
return stck.Length;
}

// Su an yiginda olan nesnelerin sayisini dondur.
public int getNum() {
return tos;
}
}
Gelin, imdi bu snf daha yakndan inceleyelim. Stack snf, u iki rnek deikeni
deklare ederek balamaktadr:
// bu uyeler private'tir
char[] stok; // yigini tutar
int tos; // yiginin tepesinin indeksi
stck dizisi, ynn temelini oluturan depolamay salar. Bu rnekte yn, karakterleri
tutar. Dizi iin bellek alan ayrlmadna dikkat edin. Asl dizi iin bellek alan ayrma ilemi,
Stack yaplandrcs tarafndan ele alnr. tos isimli ye, ynn en stnn (tepesinin)
indeksini tutar.
BLM 8: METOTLAR VE SINIFLARA DAHA YAKINDAN BR BAKI

HERKES N C#
191
tos ve stck yelerinin her ikisi de privatetir. Bu; ilk giren son kar mekanizmasn
zorunlu klmaktadr. stcke public eriime izin verilseydi, yndaki elemanlar geliigzel
bir srada eriilebilirlerdi. Ayrca; tos, ynn en stteki elemannn indeksini tuttuu iin,
ynn bozulmasn nlemek amacyla, Stack snf dndaki kodun tos zerinde deiiklik
yapmas da nlenmelidir. Stacki kullananlar iin, ksaca bahsedilen eitli public metotlar
yardmyla, stck ve tosa eriim dolayl olarak mmkndr.
Programda daha sonra yn yaplandrcs gsterilmektedir:
// buyuklugu bilinen bos bir Stack olustur
public Stack(int size) {
stck = new char[size]; // yigin icin bellek alani ayir
tos = 0;
}
stenilen yn bykl yaplandrcya aktarlr. Yaplandrc, temel tekil edecek dizi
iin bellek alan ayrr ve tosa sfr deerini verir. Bylece, tosun iindeki sfr deeri,
ynn bo olduuna iaret eder.
Ak push() metodu, yna bir eleman yerletirir. Bu metot aada gsterilmitir;
// Karakterleri yigina ekle.
public void push(char ch) {
if(tos == stck.Length) {
Console.WriteLine( -- Stack is full.);
return;
}

stck[tos] = ch;
tos++;
}
Yna yerletirilecek olan eleman ch zerinden aktarlr. Sz konusu eleman yna
eklenmeden nce yn oluturan dizide hala yer olup olmad kontrol edilir Bunun iin
tosun stckn uzunluunu amadndan emn olmak gerekir. Hala yer varsa sz konusu
eleman, stck iinde tosun belirttii indekste saklanr ve tos bir artrlr. Bylece, tos her
zaman stck iindeki bir sonraki bo elemann indeksini ierir.
Yndan bir eleman karmak iin pop() ak metodunu arn. pop() aada
gsterilmitir:
// Yigindan bir karakter cikar.
public char pop () {
if(tos == 0) {
Console.WriteLine( -- Stack is empty.);
return (char) 0;
}

tos--;
return stck[tos];
}

HERKES N C#
KISIM I C# DL

192
Burada tosun deeri kontrol edilmektedir. tosun deeri sfr ise yn botur. Aksi
halde, tos bir azaltlr ve o indekste bulunan eleman dndrlr.
Bir yn uygulamak iin gerekli olan metotlar yalnzca push() ve pop()tan ibaret olsa
da, dier baz metotlar da olduka kullanldr. Stack snfnda drt metot daha tanmldr.
Bunlar full(), empty(), capacity() ve getNum()dr. Bu metotlar ynn durumuyla
ilgili bilgi sunarlar. Aada gsterilmilerdir:
// Yigin doluysa true dondur.
public bool full() {
return tos == stck.Length;
}

// Yigin bossa true dondur.
public bool empty() {
return tos == 0;
}

// Yiginin toplam kapasitesini dondur.
public int capacity() {
return stck.Length;
}

// Su an yiginda olan nesnelerin sayisini dondur.
public int getNum() {
return tos;
}
full() metodu, yn dolu iken true, aksi halde false dndrr. empty() metodu,
yn bo olduunda true, aksi halde false dndrr. Ynn toplam kapasitesini (yani,
ynn tutabilecei toplam eleman saysn) elde etmek iin capacity()yi arn. Ynda
u an iin mevcut olan elemanlarn saysn elde etmek iin getNum() arn. Bu metotlar
kullanldr, nk bu metotlarn salad bilgi tosa eriim gerektirir; tos ise privatetr.
Bunlar ayrca, public metotlarn private yelere nasl gvenli eriim salayabileceinin
birer rneidir.
Aadaki program, yn gstermektedir:
// Stack sinifini gsterir.

using System;

class StackDemo {
public static void Main() {
Stack stk1 = new Stack(10);
Stack stk2 = new Stack(10);
Stack stk3 = new Stack(10);
char ch;
int i;

// stk1 icine birkac karakter yerlestir.
Console.WriteLine(Push A through Z onto stk1.);
BLM 8: METOTLAR VE SINIFLARA DAHA YAKINDAN BR BAKI

HERKES N C#
193
for(i = 0; !stk1.full(); i++)
stk1.push((char) (A + i));

if(stk1.full()) Console.WriteLine(stk1 is full.);

// stk1in icerigini goster.
Console.Write(Contents of stk1: );
while( !stk1.empty() ) {
ch = stk1.pop();
Console.Write(ch);
}

Console.WriteLine();

if(stk1.empty()) Console.WriteLine(stk1 is empty.\n);

// stk1e biraz daha karakter yerlestir
Console.WriteLine(Again push A through Z onto stk1.);
for(i = 0; !stk1.full(); i++)
stk1.push((char) (A + i));

/* Simdi, stk1den al ve alinan elemani stk2ye koy.
Bu islem, stk2nin elemanlari
tek sirada tutmasna neden olur. */
Console.WriteLine(Now, pop chars from stk1 and push +
them onto stk2.);
while( !stk1.empty() ) {
ch = stk1.pop();
stk2.push(ch);
}

Console.Write(Contents of stk2: );
while( !stk2.empty() ) {
ch = stk2.pop();
Console.Write(ch);
}

Console.WriteLine(\n);

// yigina 5 karakter yerlestir
Console.WriteLine(Put 5 characters on stk3.);
for(i = 0; i < 5; i++)
stk3.push((char) (A + 1));

Console.WriteLine(Capacity of stk3: + stk3.capacity());
Console.WriteLine(Number of objects in stk3: +
stk3.getNum());
}
}
Programn kts aada gsterilmitir.
Push A through Z onto stk1.
Stk1 is full.


HERKES N C#
KISIM I C# DL

194
Contents ot stk1: JIHGFEDCBA
Stk1 is empty.

Again push A through Z onto stk1.
Now, pop chars from stk1 and push them onto stk2.
Contents of stk2: ABCDEFGHIJ

Put 5 characters on stk3.
Capacity of stk3: 10
Number of objects in stk3: 5
Metotlara Nesne Aktarmak
Bu noktaya kadar, elinizdeki kitaptaki rneklerde deer tipleri, rnein int veya double,
metotlara parametre olarak kullanlmaktayd. Ancak, metotlara nesne aktarmak da hem doru
hem de yaygndr. rnein, aadaki program ele aln:
// Nesneler, metotlara aktarilabilir.

using System;

class MyClass {
int alpha, beta;

public MyClass(int i, int j) {
alpha = i;
beta = j;
}

/* Eger ob, metodu cagiran nesne ile ayni deerleri
iceriyorsa, true dondur. */
public bool sameAs(MyClass ob) {
if((ob.alpha == alpha) & (ob.beta == beta))
return true;
else return false;
}

// obun kopyasini olustur.
public void copy(MyClass ob) {
alpha = ob.alpha;
beta = ob.beta;
}

public void show() {
Console.WriteLine(alpha: {0}, beta: {1}, alpha, beta);
}
}

class PassOb {
public static void Main() {
MyClass ob1 = new MyClass(4, 5);
MyClass ob2 = new MyClass(6, 7);

Console.Write(ob1: );
BLM 8: METOTLAR VE SINIFLARA DAHA YAKINDAN BR BAKI

HERKES N C#
195
ob1.show();

Console.Write(ob2: );
ob2.show();

if(ob1.sameAs(ob2))
Console.WriteLine(ob1 and ob2 have the same values.);
else
Console.WriteLine(ob1 and ob2 have different values.);

Console.WriteLine();

// simdi ob1, ob2nin kopyasi olsun
ob1.copy(ob2);

Console.Write(ob1 after copy: );
Ob1.show();

if(ob1.sameAs(ob2))
Console.WriteLine(ob1 and ob2 have the same values.);
else
Console.WriteLine(ob1 and ob2 have different values.);
}
}
Bu program aadaki kly retir:
ob1: alpha: 4, beta: 5
ob2: alpha: 6, beta: 7
ob1 and ob2 have different values.

ob1 after copy: alpha: 6, beta: 7
ob1 and ob2 have the same values.
sameAs() ve copy() metotlarnn her biri argman olarak bir nesne alrlar. sameAs()
metodu, metodu aran nesnenin iindeki alpha ve beta deerlerini, argman olarak obun
iinde aktarlan nesnenin alpha ve beta deerleriyle karlatrr. Metot ancak bu rnek
deikenler iin her iki nesne de ayn deerleri ieriyorsa true dndrr. copy() metodu, ob
iinde aktarlan nesnenin alpha ve beta deerlerini, metodu aran nesnenin alpha ve beta
deerlerine atar. Her iki durumda da, ob parametresinin tip olarak MyClass snfn belirttiine
dikkat edin. Bu rnekte de grld gibi; nesne tipleri, sz dizimsel olarak, deer tipleriyle
ayn ekilde metotlara aktarlmaktadr.
Argmanlar Nasl Aktarlr?
nceki rnekte de gsterildii zere, bir metoda bir nesne aktarmak problemsiz bir itir.
Yine de, o rnekte gsterilmeyen baz nanslar da sz konusudur. Belirli durumlarda nesne
aktarmann etkileri, nesne olmayan argmanlarn aktarmnda yaanlan deneyimlerden farkl
olacaktr. Neden byle olduunu anlamak iin gelin, bir argmann bir alt rutine aktarlabilmesi
iin kullanlabilecek iki yntemi yeniden gzden geirelim.

HERKES N C#
KISIM I C# DL

196
lk yntem, deer olarak ardr. Bu yntem, argmann deerini alt rutinin tanml
parametresine kopyalar. Bu sayede, alt rutinin parametresi zerinde yaplan deiikliklerin
arda kullanlan argman zerinde hibir etkisi yoktur. Argman aktarmak iin ikinci yntem
ise referans olarak ardr. Bu yntemde argman gsteren bir referans (argmann deeri
deil) parametreye aktarlr. Alt rutinin iinde bu referans, arda belirtilen asl argmana eri-
mek iin kullanlr. Bunun anlam udur: Parametre zerinde yaplacak deiiklikler, alt rutini
armak iin kullanlan argman etkileyecektir. C#ta her iki yntemin de kullanlabileceini
daha sonra greceksiniz.
int veya double gibi bir deer tipini bir metoda aktarrken bu deer tipi, deer olarak
aktarlr. Bylece, argman kabul eden parametre zerinde meydana gelen deiikliklerin me-
tot dnda hibir etkisi yoktur. rnein, aadaki program ele aln:
// Basit tipler deger olarak aktarilir.

using System;

class Test {
/* Bu metot, cagrida kullanilan argumanlar uzerinde degisiklik
yapmaz. */
public void noChange(int i, int j) {
i = i + j;
i = -j;
}
}

class CallByValue {
public static void Main() {
Test ob = new Test();

int a = 15, b = 20;

Console.WriteLine(a and b before call: + a + + b);

ob.noChange(a, b);

Console.WriteLine(a and b after call: + a + + b);
}
}
Bu programn kts aadaki gibidir:
a and b before call: 15 20
a and b after call: 15 20
Grdnz gibi, noChange() iinde meydana gelen ilemlerin, arda kullanlan a ve b
deerleri zerinde hi etkisi yoktur.
Bir nesne referansn bir metoda aktardnzda bu durum biraz daha karmaktr. Teknik
olarak, nesne referansnn kendisi deer olarak aktarlr. Bylece, referansn bir kopyas
oluturulur; parametre zerindeki deiiklikler argman etkilemeyecektir. (rnein,
parametreyi yeni bir nesneyle ilikilendirmek argmann ilgili olduu nesneyi
BLM 8: METOTLAR VE SINIFLARA DAHA YAKINDAN BR BAKI

HERKES N C#
197
deitirmeyecektir.) Ancak - ki bu, byk bir ancaktr - parametrenin ilikili olduu nesne
zerinde yaplan deiiklikler argmann ilgili olduu nesneyi etkileyecektir. imdi, neden
byle olduunu grelim.
Hatrlarsanz, snf tipinde bir deiken olutururken aslnda bir nesneye bir referans
oluturmu oluyorsunuz. Bylece, bu referans bir metoda aktardnzda, bunu alan parametre,
argmann ilikili olduu nesneyle ilikilendirilecektir. Bu gerekten de nesnelerin metotlara
referans olarak ar kullanlarak aktarld anlamn tar. Metodun iindeki nesneye
yaplan deiiklikler argman olarak kullanlan nesneyi kesinlikle etkiler. rnein, aadaki
program ele aln:
// Nesneler referans olarak aktarilir.

using System;

class Test {
public int a, b;

public Test(int i, int j) {
a = i;
b = j;
}

/* Bir nesne aktar. Simdi, cagrida kullanilan nesnenin
icindeki ob.a ve ob.b degisecek. */
public void change(Test ob) {
ob.a = ob.a + ob.b;
ob.b = -ob.b;
}
}

class CallByRef {
public static void Main() {
Test ob = new Test(15, 20);

Console.WriteLine(ob.a and ob.b before call: +
ob.a + + ob.b};

ob.change(ob);

Console.WriteLine(ob.a and ob.b after call: +
ob.a + + ob.b);
}
}
Bu program aadaki kty retir:
ob.a and ob.b before call: 15 20
ob.a and ob.b after call: 35 -20
Grdnz gibi, bu rnekte change()in iindeki faaliyetler argman olarak kullanlan
nesneyi etkilemitir.

HERKES N C#
KISIM I C# DL

198
Tekrar edecek olursak: Bir nesne referans bir metoda aktarldnda, referansn kendisi
deer olarak ar kullanlarak aktarlr. Bylece, sz konusu referansn bir kopyas
oluturulur. Ancak, aktarlmakta olan deer bir nesneyle ilikili olduu iin sz konusu deerin
kopyas hala karlk gelen argmann balantl olduu nesneyle ilikili olacaktr.
ref ve out Parametrelerini Kullanmak
Az nce akland gibi, int veya char gibi deer tipleri, metotlara deer olarak aktarlr.
Bunun anlam udur: Bir deer tipini alan parametre zerine yaplan deiiklikler arda
kullanlan asl argman etkilemeyecektir. Ancak, bu davran deitirebilirsiniz. ref ve out
anahtar kelimelerinin kullanm sayesinde deer tiplerini referans olarak aktarmak mmkndr.
Bu sayede, bir metodun, arda kullanlan argman deitirmesine imkan verilir.
ref ve outun nasl kullanldna gemeden nce, bir deer tipini neden referans olarak
aktarmak isteyebileceinizi anlamanz yararldr. Genel olarak, bunun iki nedeni vardr:
Metodun kendi argmannn ieriini deitirebilmesine imkan vermek ya da metodun birden
fazla deer dndrmesini mmkn klmak. Gelin imdi, bu nedenlerin her birini ayrntlaryla
inceleyelim.
Bir metodun, kendisine aktarlan asl argmanlar zerinde ilem yapabilmesine sk sk ihti-
ya duyacaksnz. Bunun mkemmel bir rnei, iki argman dei-toku yapan swap()
metodudur. Deer tipleri deer olarak aktarldklar iin C#n varsaylan deer olarak ar
parametre aktarma mekanizmas kullanlarak, rnein iki int deerini takas eden bir metot
yazmanz mmkndr. ref niteleyicisi problemi zer.
Bildiiniz gibi, return ifadesi, bir metodun kendisini arana bir deer dndrmesini
mmkn klar. Ancak, bir metot her arlnda yalnzca bir deer dndrebilir. Peki, iki veya
daha fazla bilgi paras dndrmeniz gerekirse ne olacak? rnein, bir kayan noktal sayy
tamsay ve ondalk ksmlarna ayran bir metot gelitirmek istediinizde ne yapacaksnz? Bu-
nun iin iki bilgi parasnn da dndrlmesi gerekir: Tamsay ksm ve ondalk bileen. Bu
metot tek bir dn deeri kullanlarak yazlamaz. out niteleyicisi bu problemi zer.
ref Kullanmak
ref parametre niteleyicisi C#n deer olarak ar yerine, referans olarak ar
oluturmasn salar. ref niteleyicisi, metot deklare edildiinde ve arldnda kullanlr.
Gelin, bir rnekle balayalm. Aadaki program sqr() adnda bir metot kullanmaktadr.
sqr(), bulunduu yere argmannn karesini dndrr. refin kullanmna ve konumuna
dikkat edin.
// Bir deger tipini referans olarak aktarmak icin ref kullanir.

using System;

class RefTest {
/* Bu metot, kendi argumanini degitirir.
BLM 8: METOTLAR VE SINIFLARA DAHA YAKINDAN BR BAKI

HERKES N C#
199
refin kullanimina dikkat edin. */
public void sqr(ref int i) {
i = i * i;
}
}

class RefDemo {
public static void Main() {
RefTest ob = new RefTest();

int a = 10;

Console.WriteLine(a before call: + a);

ob.sqr(ref a); // refin kullanimina dikkat edin

Console.WriteLine(a after call: + a);
}
}
refin metot iindeki btn parametre deklarasyonundan nce geldiine ve metot
arldnda argman isminin nnde yer aldna dikkat edin. Aada gsterilen program
kts da, argman ann deerinin sqr() tarafndan gerekten deitirildiini
dorulamaktadr:
a before call: 10
a after call: 100
ref kullanarak, deer tipindeki iki argmannn deerlerini dei-toku yapan bir metot
yazmak artk mmkndr. rnein, ite size bir program. Bu program, kendisini aran iki
tamsay argmannn deerlerini dei-toku yapan swap() adnda bir metot iermektedir:
// iki degeri takas et.

using System;

class Swap {
// Bu metot simdi argumanlarini degistirir.
public void swap(ref int a, ref int b) {
int t;

t = a;
a = b;
b = t;
}
}

class SwapDemo {
public static void Main() {
Swap ob = new Swap();

int x = 10, y = 20;

Console.WriteLine(x and y before call: + x + + y);

HERKES N C#
KISIM I C# DL

200

ob.swap(ref x, ref y);

Console.WriteLine(x and y after call: + x + + y);
}
}
Bu programn kts aada gsterilmitir:
x and y before call: 10 20
x and y after call: 20 10
ref hakknda anlalmas nemli bir konu da udur: ref olarak aktarlan bir argmana
ardan nce bir deer atanmaldr. Bunun nedeni udur: Bu tr bir argman alan bir metot,
parametrenin geerli bir veriyle ilikili olduunu varsayar. Yani, ref kullanarak, bir argmana
ilk deer atamak iin bir metot kullanmanz mmkn deildir.
out Kullanmak
Kimi zaman bir metoda deer aktarmak yerine metottan bir deer almak iin bir referans
parametresi kullanmak isteyeceksiniz. rnein, referans parametresinde baar/baarszlk
kodunu dndren sz gelii bir a soketi amak gibi baz ilevleri gerekletiren bir metoda
sahip olabilirsiniz. Bu durumda, metoda aktarlacak bilgi yoktur; metottan geri alnmas
gereken bilgi vardr. Bu senaryodaki problem, ref parametresine ardan nce bir deer
atanm olmas gereidir. Sonuta, bir ref parametresi kullanmak srf bu koulu salamak iin
argmana sahte bir deer verilmesini gerekli klacaktr. Neyse ki, C# daha iyi bir alternatif
sunmaktadr: out parametresi.
out parametresi, tek bir farkla ref parametresiyle ayndr: out sadece br metottan
darya bir deer aktarmak iin kullanlabilir. out parametresi olarak kullanlan deikene
metodu armadan nce ilk deer vermek gerekli (veya kullanl) deildir. Metot, sz konusu
deikene bir deer verecektir. Ayrca, metodun iinde, bir out parametresi daima atama
yaplmam olarak kabul edilir; yani out parametresinin ilk deere sahip olmad varsaylr.
Bunun yerine metot, sona ermeden nce sz konusu parametreye bir deer atamaldr. Bylece,
metoda yaplan ardan sonra out parametresi bir deer ierecektir.
te, out parametresi kullanlan bir rnek. Decompose() snf iinde parts() metodu,
kayan noktal bir sayy tamsay ve ondalk ksmlarna aynr. Metodu aran koda bileenlerin
her birinin nasl dndrldne dikkat edin.
// out kullan.

using System;

class Decompose {

/* Kayan noktali bir degeri
tamsayi ve ondalik kisimlarina ayir. */
public int parts(double n, out double frac) {
BLM 8: METOTLAR VE SINIFLARA DAHA YAKINDAN BR BAKI

HERKES N C#
201
int whole;

whole = (int) n;
frac = n - whole; //ondalik kismi frac uzerinden geri aktar
return whole; // tamsayi kismi dondur
}
}

class UseOut {
public static void Main() {
Decompose ob = new Decompose();
int i;
double f;

i = ob.parts(10.125, out f);

Console.WriteLine(Integer portion is + i);
Console.WriteLine(Fractional part is + f);
}
}
Programn kts aadaki gibidir:
Integer portion is 10
Fractional part is 0.125
parts() metodu iki para halinde bilgi dndrr: ncelikle, nnin tamsay ksm
parts()n dn deeri olarak dndrlr. kincisi, nnin ondalk ksm metodu aran
koda, frac isimli out parametresi zerinden geri aktarlr. Bu rnekte de grld gibi, out
kullanlarak bir metodun iki deer dndrmesi mmkndr.
Elbette, yalnzca bir adet out parametresi ile kstlanm deilsiniz. Bir metot, out
parametreleri yardmyla gerekli olduu kadar ok sayda bilgi dndrebilir. te, iki adet out
parametresi kullanan bir rnek. Bu rnekte, isComDenom() metodu iki ilev grmektedir.
ncelikle, iki tamsaynn ortak bir paydas olup olmadn belirler. Eer varsa, true
dndrr; aksi halde, false dndrr. kinci ilevi ise udur: Eer ortak bir payda varsa
isComDenom(), ortak paydalarn en kk ve en byklerini out parametrelerinde dndrr.
// iki out parametresi kullan.

using System;

class Num {
/* x ve ynin ortak bir paydasi olup olmadigini belirler.
Eger varsa, en kucuk ve en buyuk ortak paydalari
out parametrelerinde dondurur. */
public bool isComDenom(int x, int y,
out int least, out int greatest) {
int i;
int max = x < y ? x : y;
bool first = true;


HERKES N C#
KISIM I C# DL

202
least = 1;
greatest = 1;

// en kucuk ve en buyuk ortak paydalari bulur
for(i = 2; i <= max/2 + 1; i++) {
if( ((y%i)==0) & ((x%i)==0) ) {
if(first) {
least = 1;
f0irst = false;
}
greatest = i;
}
}

if(least != 1) return true;
else return false;
}
}

class DemoOut {
public static void Main() {
Num ob = new Num();
int lcd, gcd;

if(ob.isComDenom(231, 105, out lcd, out gcd)) {
Console.WriteLine(Lcd of 231 and 105 is + lcd);
Console.WriteLine(Gcd of 231 and 105 is + gcd);
}
else
Console.WriteLine(No common denominator for 35 and 49.);
if (ob.isComDenom(35, 51, out lcd, out gcd)) {
Console.WriteLine(Lcd of 35 and 51 + lcd);
Console.WriteLine(Gcd of 35 and 51 is + gcd);
}
else
Console.WriteLine(No common denominator for 35 and 51.);
}
}
Main() iinde, isComDenom()a ar yaplmadan nce lcd ve gcdye deer
atanmadna dikkat edin. Parametreler out yerine ref olsayd hatal olurdu. Metot, her iki
tamsaynn ortak bir paydas olup olmamasna bal olarak true veya false dndrr. Eer
ortak bir payda varsa, ortak paydalarn en k ve en by out parametrelerinde
dndrlr. Bu programn kts aadaki gibidir:
Lcd of 231 and 105 is 3
Gcd of 231 and 105 is 21
No common denominator for 35 and 51.
Referans Parametrelerinde ref ve out Kullanmak
ref ve out kullanm yalnzca deer parametreleriyle snrl deildir. Bunlar referans
parametrelerinde de, rnein bir nesne referans aktarld zaman da ayrca kullanlabilir. ref
BLM 8: METOTLAR VE SINIFLARA DAHA YAKINDAN BR BAKI

HERKES N C#
203
veya out bir referans parametresi zerinde deiiklik yapnca, bu durum, referansn kendisinin
referans olarak aktarlmasna neden olur. Bylece metodun, referansn ilikili olduu nesneyi
deitirmesine imkan verilir. Aadaki program ele aln. Bu programda, iki referansn ilikili
olduu nesneleri dei-toku etmek iin ref parametreleri kullanlmaktadr:
// iki referansi takas etmek.

using System;

class RefSwap {
int a, b;

public RefSwap(int i, int j) {
a = i;
b = j;
}

public void show() {
Console.WriteLine(a: {0}, b: {1}, a, b);
}

// Bu metot argumanlarini degistirir.
public void swap(ref RefSwap ob1, ref RefSwap ob2) {
RefSwap t;

t = ob1;
ob1 = ob2;
ob2 = t;
}
}
class RefSwapDemo {
public static void Main() {
RefSwap x = new RefSwap(1, 2);
RefSwap y = new RefSwap(3, 4);

Console.Write(x before call: );
x.show();

Console.Write(y before call: );
y.show();

Console. WriteLine();

// x ve ynin iliskili oldugu nesneleri degis-tokus yap
x.swap(ref x, ref y);

Console.Write(x after call: );
x.show();

Console.Write(y after call: );
y.show();
}
}

HERKES N C#
KISIM I C# DL

204
Bu programn kts aada gsterilmitir:
x before call: a: 1, b: 2
y before call: a: 3, b: 4

x after call: a: 3, b: 4
y after call: a: 1, b: 2
Bu rnekte swap() metodu, swap()n her iki argmannn ilikili olduu nesneleri
dei-toku eder. swap() armadan nce x, 1 ve 2 deerlerini ieren bir nesneyle; y ise 3
ve 4 deerlerini ieren bir nesneyle ilikilidir. swap()a yaplan ardan sonra x, 3 ve 4
deerlerini ieren nesneyle; y ise 1 ve 2 deerlerini ieren nesneyle ilikilendirilir. ref
parametreleri kullanlmam olsayd. swap() iindeki dei-tokuun swap() dnda hi bir
etkisi olmam olacakt. Bunu kantlamak isterseniz, refi swap()tan karabilirsiniz.
Deien Sayda Argman Kullanmak
Bir metot gelitirdiinizde, genellikle bu metoda aktaracanz argmanlarn saysn
nceden bilirsiniz, fakat bu durum her zaman geerli deildir. Bazen rasgele sayda argman
aktarlabilen bir metot gelitirmek isteyebilirsiniz. rnein, bir deerler kmesinin en
kn bulan bir metodu ele aln. Byle bir metoda iki gibi az sayda deer ya da , drt vs
sayda deer aktarlabilir. Her trl durumda, metodun en kk deeri dndrmesini istersiniz.
Bu tr bir metot, normal parametreler kullanlarak oluturulamaz. Bunun yerine, rasgele sayda
parametreye karlk gelen zel tipte bir parametre kullanmalsnz. te bu, params
parametresi kullanlarak gerekletirilir.
params niteleyicisi, sfr sayda veya daha fazla argman alabilen bir dizi parametre
deklare etmek iin kullanlr. Dizideki eleman says, metoda aktarlan argman saysna eit
olacaktr. Programnz daha sonra argmanlar elde etmek iin diziye eriir.
te size bir rnek. Bu rnekte, bir deerler kmesinin en kk deerini dndren
minVal() adnda bir metot oluturmak iin params kullanlmaktadr:
// params'i gosterir.

using System;

class Min {
public int minVal(params int[] nums) {
int m;

if(nums.Length == 0) {
Console.WriteLine(Error: no arguments.);
return 0;
}

m = nums[0];
for(int i = 1; i < nums.Length; i++)
if(nums[i] < m) m = nums[i];
BLM 8: METOTLAR VE SINIFLARA DAHA YAKINDAN BR BAKI

HERKES N C#
205

return m;
}
}

class ParamsDemo {
public static void Main() {
Min ob = new Min();
int min;
int a = 10, b = 20;

// 2 deger ile cagir
min = ob.minVal(a, b);
Console.WriteLine(Minimum is + min);

// 3 deger ile cagir
min = ob.minVal(a, b, -1);
Console.WriteLine(Minimum is + min);

// 5 deger ile cagir
min = ob.minVal(18, 23, 3, 14, 25);
Console.WriteLine(Minimum is + min);

// bir int dizisiyle bile cagrilabilir
int[] args = { 45, 67, 34, 9, 112, 8 };
min = ob.minVal(args);
Console.WriteLine(Minimum is + min);
}
}
Programn kts aada gsterilmitir:
Minimum is 10
Minimum is -1
Minimum is 3
Minimum is 8
minVal()in her arlnda argmanlar, nums dizisi zerinden metoda aktarlr. Dizinin
uzunluu eleman saysna eittir. Bylece, minVal()i herhangi bir sayda deerin en
kn bulmak iin kullanabilirsiniz.
params parametresine herhangi bir sayda argman aktarabilmenize ramen, bunlarn
tm parametre olarak belirtilen dizi tipi ile uyumlu olmaldr. rnein, minVali u ekilde
armak;
min = ob.minVal(1, 2.2);
kurallara uymaz, nk doubledan (2.2) inte otomatik dnm yoktur. Oysa int,
minVal()in iinde yer alan numsn tipidir.
params kullanrken snr koullaryla ilgili dikkatli olmanz gerekir, nk params
parametresi herhangi bir sayda argman kabul edebilir - hatta, sfr sayda bile! rnein,
minVal()i aada gsterildii gibi armak sz dizimsel adan geerlidir:

HERKES N C#
KISIM I C# DL

206
min = ob.minVal(); // argumansiz
min = ob.minVal(3) // 1 argumanli
nums dizisinin elemanna erimeye girimeden nce dizide en az bir eleman olduunu
dorulamak iin minVal() iinde bir kontroln yer almasnn nedeni budur, Eer burada kont-
rol olmasayd, minVal()in argmansz arlmas durumunda, altrma srasnda bir kural
d durum ortaya kard. (Bu kitabn ileriki blmlerinde kural d durumlar ele alndnda,
bu tip hatalar kontrol altna almak iin daha iyi bir yntem reneceksiniz.) stelik,
minVal()in kodu, minVal()i tek bir parametreyle armaya izin verecek ekilde
yazlmtr, Byle bir durumda, tek argman dndrlr.
Bir metot, normal parametrelere ve deiken sayda bir parametreye sahip olabilir.
rnein, aadaki programda showArgs() metodu nce bir string parametresi, sonra da bir
params tamsay dizisi alr:
// Normal parametreyi params parametresiyle birlikte kullanmak.

using System;

class MyClass {
public void showArgs(string msg, params int[] nums) {
Console.Write(msg + : );

foreach(int i in nums)
Console.Write(i + );

Console.WriteLine();
}
}

class ParamsDemo2 {
public static void Main() {
MyClass ob = new MyClass();

ob.showArgs(Here are some integers, 1, 2, 3, 4, 5);
ob.showArgs(Here are two more, 17, 20);
}
}
Bu program aadaki kty ekranda gsterir:
Here are some integers: 1 2 3 4 5
Here are two more: 17 20
Bir metodun hem normal parametreye hem de params parametresine sahip olmas
durumlarnda params parametresi, parametre listesindeki en son eleman olmaldr. stelik, her
koulda parametre listesinde yalnzca bir tane params parametresi olmaldr.


BLM 8: METOTLAR VE SINIFLARA DAHA YAKINDAN BR BAKI

HERKES N C#
207
Nesneleri Dndrmek
Bir metot snf tipleri de dahil olmak zere herhangi tipten verileri dndrebilir. rnein,
Rect snfnn aadaki versiyonu enlarge() adnda bir metot iermektedir. enlarge(),
kendisini aran dikdrtgenle ayn orantya sahip, fakat belirli bir faktr orannda daha byk
bir dikdrtgen oluturmaktadr:
// Bir nesne dondur.

using System;

class Rect {
int width;
int height;

public Rect(int w, int h) {
width = w;
height = h;
}

public int area() {
return width * height;
}

public void show() {
Console.WriteLine(width + + height);
}

/* Metodu cagiran dikdortgenden belirtilen oranda
daha buyuk bir dikdortgen dondur. */
public Rect enlarge(int factor) {
return new Rect(width * factor, height * factor);
}
}

class RetObj {
public static void Main() {
Rect r1 = new Rect(4, 5);

Console.Write(Dimensions of r1: );
r1.show();

Console.WriteLine(Area of r1: + r1.area());

Console.WriteLine();

// r1in iki kati buyuklukte bir dikdortgen olustur
Rect r2 = r1.enlarge(2);

Console.Write(Dimensions of r2: );
r2.show();
Console.WriteLine(Area of r2 + r2.area());
}

HERKES N C#
KISIM I C# DL

208
}
kt aada gsterilmitir:
Dimensions of r1: 4 5
Area of r1: 20

Dimensions of r2: 8 10
Area of r2 80
Bir metot tarafmdan dndrlen bir nesne, artk kendisine herhangi bir referans kalmayana
kadar varln srdrr. Kendisine herhangi bir referans kalmadnda ise o nesne anlamsz
veri toplama ve yok etme srecine (garbage collection) tabi tutulur. Bir baka ifade ile, bir
nesne, srf kendisini oluturan metot sonland diye hemen yok edilmez
Nesne dn tiplerinin bir uygulamas, snf fabrikasdr (class factory). Bir snf fabrikas,
kendi snfndan nesneler kurmaya yarayan bir metottur. Gvenlik nedenleriyle ya da nesne
kuruluu baz d unsurlara bal olduu iin baz durumlarda bir snfn kullanclarna o snfn
yaplandrcsna erime olana vermek istemeyebilirsiniz. Byle durumlarda nesneleri kurmak
iin bir snf fabrikas kullanlr. Aada bunun basit bir rnei yer almaktadr.
// Bir sinif fabrikasi kullanir.

using System;

class MyClass {
int a, b; // private

// MyClass icin bir sinif fabrikasi olusturur.
public MyClass factory (int i, int j) {
MyClass t = new MyClass();

t.a = i;
t.b = j;

return t; // bir nesne dondurur
}

public void show() {
Console.WriteLine(a and b: + a + + b);
}
}

class MakeObjects {
public static void Main() {
MyClass ob = new MyClass();
int i, j;

// Fabrikayi kullanarak nesneler uretir.
for(i=0, j=10; i < 10; i++, j--) {
MyClass anotherOb = ob.factory(i, j); // Nesne olustur
anotherOb.show();
}
BLM 8: METOTLAR VE SINIFLARA DAHA YAKINDAN BR BAKI

HERKES N C#
209

Console.WriteLine();
}
}
Programn kts yledir:
a and b: 0 10
a and b: 1 9
a and b: 2 8
a and b: 3 7
a and b: 4 6
a and b: 5 5
a and b: 6 4
a and b: 7 3
a and b: 8 2
a and b: 9 1
Gelin, imdi bu rnei yakndan inceleyelim. MyClass bir yaplandrc tanmlamad
iin sadece varsaylan yaplandrc mevcuttur. Dolaysyla a ve bnin deerlerini bir
yaplandrc kullanarak atamak olanakl deildir. Ancak snf fabrikas factory(), a ve bnin
deer atand nesneyle oluturabilir. stelik, a ve b private olduu iin, onlara deer
atamann tek yolu factory()yi kullanmaktr.
Main()de bir MyClass nesnesi rneklenmektedir ve ilave 10 nesne oluturmak iin bu
nesnenin fabrika metodu for dngs iinde kullanlmaktadr. Bu ilemin yapld kod satr
udur:
MyClass anotherOb = ob.factory(i, j); // Bir nesne al
Dngnn her admnda, anotherOb adl bir nesne referans oluturulmakta ve buna, fab-
rika tarafndan kurulan nesneye bir referans atanmaktadr. Her admn sonunda anotherOb
kapsam dna kmakta ve onun referansta bulunduu nesne geri dnm ilemine tabi
tutulmaktadr.
Bir Diziyi Dndrmek
C#ta diziler, nesneler olarak uygulandndan bir metot bir dizi de dndrebilir. (Bu,
dizilerin geerli dn tipi olmad C++tan farkl bir durumdur.) rnein, aadaki
programda findfactors() metodu kendisine aktarlan argmanlarn arpanlarn tutan bir
dizi dndrmektedir:
// Bir diziyi geri dondurmek.

using System;

class Factor {
/* numun carpanlarini iceren bir diziyi geri dondurur.
Geri donuste numfactors bulunan carpanlarinin
sayisini ierir. */

HERKES N C#
KISIM I C# DL

210
public int[] findfactors(int num, out int numfactors) {
int[] facts = new int[80]; //80'lik buyukluk keyfi secilmitir
int i, j;

// carpanlari bul ve bunlari facts dizisine koy
for(i=2, j=0; i < num/2 + 1; i++)
if( (num%i) == 0 ) {
facts[j] = i;
}

numfactors = j;
return facts;
}
}

class FindFactors {
public static void Main() {
Factor f = new Factor();
int numfactors;
int[] factors;

factors = f.findfactors(1000, out numfactors);

Console.WriteLine(Factors for 1000 are: );
for(int i = 0; i < numfactors; i++)
Console.Write(factors[i] + );

Console.WriteLine();
}
}
Programn kts aada gsterilmitir,
Factors for 1000 are:
2 4 5 8 10 20 25 40 50 100 125 200 250 500
Factorde findfactors() u ekilde deklare edilmektedir:
public int[] findfactors(int num, out int numfactors) {
int dizisinin dn tipinin nasl belirlendiine dikkat edin. Bu sz dizimi
genelletirilebilir. Bir metot bir dizi geri dndrdnde tip ve boyutlar gerektii ekilde
ayarlayarak dn tipini yukardakine benzer ekilde belirleyebilirsiniz. rnein, aadaki
ifade iki boyutlu bir double dizisi geri dndren someMeth() adl bir metot tanmlamaktadr.
public double[,] someMeth() { // ...
Metotlarn Ar Yklenmesi
Bu blmde, C#n en heyecan verici zelliklerinden biri olan metotlarn ar yklenmesi
konusunu reneceksiniz. C#ta ayn snfn iindeki iki ya da daha fazla metot, parametre
deklarasyonlar farkl olduu srece, ayn ismi paylaabilirler. Byle metotlara ar yklenmi
BLM 8: METOTLAR VE SINIFLARA DAHA YAKINDAN BR BAKI

HERKES N C#
211
metot denir. Bu ileme de metodun ar yklenmesi ad verilir. Metodun ar yklenmesi,
C#n ok biimlilii uygulama yollarndan biridir.
Genelde bir metodu ar yklemek iin onun farkl versiyonlarn deklare etmek yeterlidir.
Gerisini derleyici halleder. Yalnz, nemli bir kstlamaya dikkat etmelisiniz: Ar yklenmi
her bir metodun parametre tipleri ve/veya saylar farkl olmaldr. ki metodun sadece dn
tiplerinin farkl olmas yeterli deildir. Parametrelerinin tip ya da saylar farkl olmaldr.
(Dn tipleri, C#n olas her durumda hangi metodu kullanacana karar verebilmesi iin
yeterli bilgi vermez.) Kukusuz, ar yklenmi metotlarn geri dn tiplerinde de farkllklar
olabilir. Ar yklenmi bir metot arldnda, ardaki argmanlarla ayn parametre
saysna ve parametre tiplerine sahip olan versiyon gereklenir.
te, metot ar yklenmesini gsteren basit bir rnek:
// Metot asiri yuklenmesini gosterir.

using System;

class Overload {
public void ovlDemo() {
Console.WriteLine(No parameters);
}

// ovlDemoyu tek tamsayi parametre icin asiri yukle.
public void ovlDemo(int a) {
Console.WriteLine(One parameter: + a);
}

// ovlDemoyu iki tamsayi parametre icin asiri yukle.
public int ovlDemo(int a, int b) {
Console.WriteLine(Two parameters: + a + + b);
return a + b;
}

// ovlDemoyu iki double parametre icin asiri yukle.
public double ovlDemo(double a, double b) {
Console.WriteLine(Two double parameters: + a + + b);
return a + b;
}
}

class OverloadDemo {
public static void Main() {
Overload ob = new Overload();
int resI;
double resD;

// ovlDemonun tum surumlerini cagir
ob.ovlDemo();
Console.WriteLine();

ob.ovlDemo(2);
Console.WriteLine();

HERKES N C#
KISIM I C# DL

212
resI = ob.ovlDemo(4, 6);
Console.WriteLine(Result of ob.ovlDemo(4, 6): + resI);
Console.WriteLine();

resD = ob.ovlDemo(1.1, 2.32);
Console.WriteLine(Result of ob.ovlDemo(1.1, 2.32): +
resD;
}
}
Programn kts u ekildedir:
No parameters

One parameter: 2

Two parameters: 4 6
Result of ob.ovlDemo(4, 6): 10

Two double parameters: 1.1 2.32
Result of ob.ovlDemo(1.1, 2.32): 3.42
Grdnz gibi, ovlDemo() drt kez ar yklenmitir. lk versiyonun parametresi
yoktur. kincisinde tek bir int parametre vardr. ncsnde iki int parametre,
drdncsnde de iki double parametre yer almaktadr. ovlDemonun ilk iki versiyonunun
void, kalan iki versiyonunun ise bir deer dndrdne dikkat edin. Bu tamamen geerli bir
durumdur, ancak daha nce de akladmz gibi, ar ykleme bir metodun geri dn
tipinden u ya da bu ekilde etkilenmez. Dolaysyla, ovlDemonun u iki versiyonunu
kullanmaya alrsak hata ile karlarz:
// Tek ovlDemo(int)de bir problem yok.

public void ovlDemo(int a) {
Console.WriteLine(One parameter: + a);
}

/* Hata! Geri donus tipleri farkli olsa bile
iki ovlDemo(int) gecerli degil. */
public int ovlDemo(int a) {
Console.WriteLine(One parameter: + a);
return a * a;
}
Kod iindeki aklamalarn da iaret ettii gibi, iki metodun geri dn tiplerinin farkl
olmas ar ykleme ilemi iin yeterli deildir.
Blm 3ten hatrlayacanz gibi, C# baz otomatik tip dnmleri salar. Bu
dnmler, ar yklenmi metotlarn tiplerine de uygulanr. Aadaki rnee bakalm:
/* Otomatik tip donusumleri asiri yuklenmis metotlardan
hangisinin kullanilacaginin belirlenmesinde etkili olabilir. */

using System;
BLM 8: METOTLAR VE SINIFLARA DAHA YAKINDAN BR BAKI

HERKES N C#
213

class Overload2 {
public void f(int x) {
Console.WriteLine(Inside f(int): + x);
}

public void f(double x) {
Console.WriteLine(Inside f(double): + x);
}
}

class TypeConv {
public static void Main() {
Overload2 ob = new 0verload2();

int i = 10;
double d = 10.1;

byte b = 99;
short s = 10;
float f = 11.5F;

ob.f(i); // ob.f(int)i cagirir
ob.f(d); // ob.f(double)i cagirir

ob.f(b); // ob.f(int)i cagirir -- tip donusumu
ob.f(s); // ob.f(int)i cagirir -- tip donusumu
ob.f(f); // ob.f(double)i cagirir -- tip donusumu
}
}
Program, u kty retir:
Inside f(int): 10
Inside f(double): 10.1
Inside f(int): 99
Inside f(int): 10
Inside f(double): 11.5
Bu rnekte, f()nin sadece iki versiyonu tanmlanmtr: int parametresi olan bir
versiyon ve double parametresi olan ikinci versiyon. Ancak f()ye bir byte, short ya da
float deeri aktarmak mmkndr. byte ve short kullanldnda C# bunlar otomatik
olarak inte dntrr. Dolaysyla f(int) arlr. float kullanldnda ise bu parametre
doublea dntrlr ve f(double) kullanlr.
Otomatik dnmlerin ancak parametrelerle argmanlar arasnda dorudan bir eleme
olmad durumlarda kullanldn anlamak nemlidir. rnein, yukardaki programda
f()nin byte parametreli bir versiyonu olduunda farkl bir durum ortaya kacaktr:
// f(byte)i ekle.

using System;


HERKES N C#
KISIM I C# DL

214
class Overload2 {
public void f(byte x) {
Console.WriteLine(Inside f(byte): + x);
}

public void f(int x) {
Console.WriteLine(Inside f(int): + x);
}

public void f(double x) {
Console.WriteLine(Inside f(double): + x);
}
}

class TypeConv {
public static void Main() {
Overload2 ob = new Overload2();

int i = 10;
double d = 10.1;

byte b = 99;
short s = 10;
float f = 11.5F;

ob.f(i); // ob.f(int)i cagirir
ob.f(d); // ob.f(double)i cagirir

ob.f(b); /* ob.f(byte)i cagirir
bu durumda tip donusumu olmaz */

ob.f(s); // ob.f(int)i cagirir -- tip donusumu
ob.f(f); // ob.f(double)i cagirir -- tip donusumu
}
}
imdi bu program altrdmzda aadaki kty elde ederiz:
Inside f(int): 10
Inside f(double): 10.1
Inside f(byte): 99
Inside f(int): 10
Inside f(double): 11.5
Artk f()nin byte argman alan bir versiyonu mevcut olduundan, f() bir byte
argmanla arldnda parametre otomatik olarak inte dntrlmez ve f(byte) arlr.
Ar ykleme versiyonlarndan hangisinin kullanlacan belirlemede hem ref hem de
out rol alr. rnein, aadaki programda iki farkl metot tanmlanmaktadr:
public void f(int x) {
Console.WriteLine(Inside f(int): + x);
}

public void f(ref int x) {
BLM 8: METOTLAR VE SINIFLARA DAHA YAKINDAN BR BAKI

HERKES N C#
215
Console.WritetLine(Inside f(ref int): + x);
}
Bu nedenle,
ob.f(i)

f(int x)i,

ob.f(ref i)

ise f(ref int x)i armaktadr.
Metotlarn ar yklenmesi, ok biimlilii destekler, nk bu, C#n tek arayz, ok
metot modelini uygulamaya geirme yntemlerinden biridir. yle ki: Metotlarn ar
yklenmesini desteklemeyen dillerde her metodun ismi farkl olmaldr. Ancak sk sk, aslnda
tamamen ayn ilemi yapan, sadece kullandklar veri tiplerinde ayrlan metotlar uygulamak
zorunda kalrsnz. rnek olarak mutlak deer fonksiyonunu ele alalm. Ar yklemeyi
desteklemeyen dillerde bu fonksiyonun genelde ya da daha fazla versiyonu vardr. Her
birinin ad biraz farkldr. rnein Cde abs() fonksiyonu bir tamsaynn mutlak deerini
dndrrken, labs() fonksiyonu long int iin, fabs() da kayan noktal deerler iin
kullanlr. C, ar yklemeyi desteklemedii iin, bu fonksiyonlarn yapt i esasen ayn
olmasna ramen, her fonksiyonun isminin ayr olmas gereklidir. Bu da durumu olduundan
daha karmak bir hale sokmaktadr. Farkl fonksiyonlarn altnda yatan kavram ayn olmasna
ramen, farkl ismi hatrlamak gerekmektedir. Bu durum C#ta geerli deildir, nk her
bir mutlak deer metodu ayn ismi kullanabilir. Hatta C#n standart snf ktphanesinde
Abs() adl bir mutlak deer fonksiyonu vardr. Bu metot C#n System.Math snf tarafndan
nmerik snflar zerinde ilem yapabilecek ekilde ar yklemeye tabi tutulmaktadr. C#,
Abs()n hangi versiyonunun kullanlacana, argmann tipine bakarak kendisi karar
vermektedir.
Ar yklemenin balca yararlarndan biri, birbirleriyle ilgili metotlara ortak bir isimle
eriim salanmasdr. Yani, Abs ismi, gerekletirilmekte olan genel faaliyeti simgelemektedir.
Belli bir durumda metodun hangi zel versiyonunun kullanlacana karar vermek derleyiciye
kalmaktadr. Siz programclarn sadece yaplan genel ilemi hatrlamas yeterli olmaktadr. ok
biimliliin uygulanmas ile, birden fazla isim tek bir isme indirgenmitir. Belki bu rnek ol-
duka basittir ama kavram genilettiiniz takdirde, ar yklemenin ok daha byk boyutlu
karmak durumlarn ynetilmesini nasl kolaylatrdn anlayabilirsiniz.
Bir metodu ar yklediiniz zaman, o metodun her bir versiyonu istediiniz herhangi bir
ii yapabilir. Ar yklenmi metotlarn birbirleriyle ilintili olmas gerektiine dair bir kural
yoktur. Ancak, stil asndan, metotlarn ar yklenmesi byle bir ilikinin var olduunu ima
etmektedir. Dolaysyla, birbirleriyle ilgisi olmayan metotlar ar yklemek iin ayn ismi
kullanmanz mmkn olsa bile bunu yapmamalsnz. rnein, sqr ad altnda, parametresi
int olunca saynn karesini, parametresi float olunca saynn karekkn dndren metotlar

HERKES N C#
KISIM I C# DL

216
oluturmamalsnz. Metotlarn ar yklenmesini bu ekilde uygulamak amaca ters der. Pra-
tikte, sadece birbirleriyle ok yakndan ilgili ilemler zerinde ar ykleme yapmalsnz.
C#ta imza (signature) terimi tanmlanmaktadr. Bu terim, bir metot ile onun parametre
listesini ierir. Ar ykleme asndan deerlendirildiinde, ayn snf iinde iki metot ayn
imzaya sahip olamaz. mza tanmnn metodun dn tipini iermediine dikkat edin. Bunun
nedeni, C#n ar yklemeyi zmlemek iin geri dn tipini kullanmamasdr. Ayrca,
imza, eer varsa params parametresini de iermemektedir, params da ar ykleme
zmlenmesinde kullanlmamaktadr.
Yaplandrclar Ar Yklemek
Tpk metotlar gibi, yaplandrclar da ar yklenebilir. Bu ekilde, nesneleri ok eitli
yollardan yaplandrmanz mmkn olur. rnein, aadaki program ele aln:
// Asiri yuklenmis bir yapilandiriciyi gosterir.

using System;

class MyClass {
public int x;

public MyClass() {
Console.WriteLine(Inside MyClass().);
x = 0;
}

public MyClass(int i) {
Console.WriteLine(Inside MyClass(int).);
x = i;
}

public MyClass(double d) {
Console.WriteLine(Inside MyClass(double).);
x = (int) d;
}

public MyClass(int i, int j) {
Console.WriteLine(Inside MyClass(int, int).);
x = i * j;
}
}

class OverloadConsDemo {
public static void Main() {
MyClass t1 = new MyClass();
MyClass t2 = new MyClass(88);
MyClass t3 = new MyClass(17.23);
MyClass t4 = new MyClass(2, 4);

Console.WriteLine(t1.x: + t1.x);
Console.WriteLine(t2.x: + t2.x);
BLM 8: METOTLAR VE SINIFLARA DAHA YAKINDAN BR BAKI

HERKES N C#
217
Console.WriteLine(t3.x: + t3.x);
Console.WriteLine(t4.x: + t4.x);
}
}
Programn kts aada gsterilmitir:
Inside MyClass().
Inside MyClass(int).
Inside MyClass(double).
Inside MyClass(int, int).
t1.x: 0
t2.x: 88
t3.x: 17
t4.X: 8
MyClass(), her biri ile farkl bir nesne kurulan drt ekilde ar yklenebilir. new
gereklendiinde, normal yaplandrc belirtilen parametreler baz alnarak arlr. Bir snfn
yaplandrcsn ar ykleyerek snfnzn kullancsna nesnelerin yaplandrlma ekliyle
ilgili esneklik verirsiniz.
Yaplandrclarn ar yklenmesinin en yaygn nedenlerinden biri, bir nesnenin dierine
ilk deer atamasna imkan vermektir. rnein, ite bir yndan bir baka yn kurmay
mmkn klan ve daha nce gelitirilen Stack snfnn ileri versiyonu:
// Karakaterler icin bir yigin sinifi.

using System;

class Stack {
// bu uyeler privatetir
char[] stck; // yigini tutar
int tos; // yiginin tepesinin indeksi

// buyuklugu bilinen bir bos Stack yapilandir
public Stack(int size) {
stck = new char[size]; // yigin icin bellek alani ayir
tos = 0;
}

// Yigindan bir Stack yapilandir.
public Stack(Stack ob) {
// yigin icin bellek alani ayir
stck = new char[ob.stck.Length];

// elemanlari yeni yigina kopyala
for(int i=0; i < ob.tos; i++)
stck[i] = ob.stck[i];

// yeni yigin icin tosu ayarla
tos = ob.tos;
}

// Karakterleri yigina ekle.

HERKES N C#
KISIM I C# DL

218
public void push(char ch) {
if(tos == stck.Length) {
Console.WriteLine( -- Stack is full.);
return;
}

stck[tos] = ch;
tos++;
}

// Yigindan bir karakter cikar.
public char pop() {
if(tos == 0) {
Console.WriteLine( -- Stack is empty.);
return (char) 0;
}

tos--;
return stck[tos];
}

// Yigin doluysa true dondur.
public bool full() {
return tos==stck.Length;
}

// Yigin bossa true dondur.
public bool empty() {
return tos==0;
}

// Yiginin toplam kapasitesini dondur.
public int capacity() {
return stck.Length;
}

// Su an yiginda olan nesnelerin sayisini dondur.
public int getNum() {
return tos;
}
}

// Stack sinifini goster.

class StackDemo {
public static void Main() {
Stack stk1 = new Stack(10);
char ch;
int i;

// stk1e birkac karakter yerlestir
Console.WriteLine(Push A through Z onto stk1.);
for(i = 0; !stk1.full(); i++)
stk1.push((char) (A + i));

BLM 8: METOTLAR VE SINIFLARA DAHA YAKINDAN BR BAKI

HERKES N C#
219
// stck1in bir kopyasini olustur
Stack stk2 = new Stack(stk1);

// stk1in icerigini goster.
Console.Write(Contents of stk1: );
while( !stk1.empty() ) {
ch = stk1.pop();
Console.Write(ch);
}

Console.WriteLine();

Console.Write(Contents of stk2: );
while ( !stk2.empty() ) {
ch = stk2.pop();
Console.Write(ch);
}

Console.WriteLine(\n);
}
}
kt aadaki gibidir:
Push A through Z onto stk1.
Contents of stk1: JIHGFEDCBA
Contents of stk2: JIHGFEDCBA
StackDemoda ilk yn olan stk1, yaplandrlr ve karakterlerle doldurulur. Bu yn
daha sonra ikinci ynnn, yani stk2nin yaplandrlmas iin kullanlr. Bu ilem aadaki
Stack yaplandrcsnn altrlmasna neden olur:
// Yigindan bir Stack yapilandir

public Stack(Stack ob) {
// yigin icin bellek alani ayir
stck = new char[ob.stck.Length];

// elemanlari yeni yigina kopyala
for(int i = 0; i < ob.tos; i++)
stck[i] = ob.stck[i];

// yeni yigin icin tosu ayarla
tos = ob.tos;
}
Bu yaplandrc iinde, ob parametresi zerinden aktarlan ynn elemanlarn
tutabilecek uzunlukta bir dizi iin bellek alan ayrlr. Sonra, ob dizisinin ierii yeni diziye
kopyalanr ve tosa uygun bir deer atanr. Yaplandrcnn ilemi bittikten sonra yeni ve
orijinal ynlar ayr ama ayndr.


HERKES N C#
KISIM I C# DL

220

this Araclyla Ar Yklenmi Bir Yaplandrcy
armak
Ar yklenmi yaplandrclarla alrken bir yaplandrcnn dierini armas kimi
zaman kullanl olur. C#ta bu, this anahtar kelimesinin bir baka ekli kullanlarak
gerekletirilir. Genel yap aada gsterildii gibidir:
yaplandrc-ismi(parametre-listesi1) : this(parametre-listesi2) {
// ... yaplandrc gvdesi; gvde bo olabilir
}
Yaplandrc altrldnda, parametre-listesi2 ile belirtilen parametre listesi ile
eleen ar yklenmi yaplandrc ilk olarak altrlr. Sonra, orijinal yaplandrc iinde
mevcut ifade varsa bu ifadeler altrlr. te bir rnek:
// this araciligiyla bir yapilandirici cagirmayi gosterir.

using System;

class XYCoord {
public int x, y;

public XYCoord() : this(0, 0) {
Console.WriteLine(Inside XYCoord());
}

public XYCoord(XYCoord obj) : this(obj.x, obj.y) {
Console.WriteLine(Inside XYCoord(obj));
}

public XYCoord(int i, int j) {
Console.WriteLine(Inside XYCoord(int, int));
x = i;
y = j;
}
}

class OverloadConsDemo {
public static void Man() {
XYCoord t1 = new XYCoord();
XYCoord t2 = new XYCoord(8, 9);
XYCoord t3 = new XYCoord(t2);

Console.WriteLine(t1.x, t1.y: + t1.x + , + t1.y);
Console.WriteLine(t2.x, t2.y: + t2.x + , + t2,y);
Console.WriteLine(t3.x, t3.y: + t3.x + , + t3.y);
}
}
Programn kts aada gsterilmitir:
BLM 8: METOTLAR VE SINIFLARA DAHA YAKINDAN BR BAKI

HERKES N C#
221
Inside XYCoord(int, int)
Inside XYCoord()
Inside XYCoord(int, int)
Inside XYCoord(int, int)
Inside XYCoord(obj)
t1.x, t1.y: 0, 0
t2.x, t2.y: 8, 9
t3.x, t3.y: 8, 9
Programn ileyii u ekildedir: XYCoord snfnda, x ve y alanlarna gerekten ilk deer
atayan tek yaplandrc XYCoord(int,int) metodudur Dier iki yaplandrc sadece this
araclyla XYCoord{int,int) metodunu arrlar. rnein, t1 nesnesi oluturulduunda
bu nesnenin yaplandrcs, XYCoord() arlr. Bu, this(0,0)n altrlmasna neden
olur ki bu, bu rnekte, XYCoord(0,0)a yaplan bir arya dnmektedir. t2nin
oluturulmas da ayn ekilde gerekletirilir.
Ar yklenmi yaplandrclar this araclyla armann kullanl olabilmesinin
nedenlerinden biri, bu sayede kodun gereksiz yere tekrarnn nlenebilmesidir. Yukardaki
rnekte, yaplandrclarn nn de ayn ilk deer atama sekansn tekrarlamalar iin bir
neden yok. Bu tekrarlar this kullanlarak nlenmektedir. Bir baka avantaj da udur: Bu
sayede, argmanlar aka belirtilmediinde kullanlan dolayl varsaylan argmanlara sahip
yaplandrclar oluturabilirsiniz. rnein, aada gsterilen ekilde, bir baka XYCoord
yaplandrcs oluturabilirsiniz:
public XYCoord(int x) : this(x, x) { }
Bu yaplandrc otomatik olarak y koordinatna, x koordinat ile ayn deeri varsaylan
deger olarak atar. Bu varsaylan argmanlar dikkatlice kullanmak elbette akllca olur; nk
bu argmanlarn yanl kullanm, snflarnz kullanan kullanclar kolaylkla karkla
drebilir.
Main() Metodu
u ana dek Main() metodunun tek eklini kullanmaktaydnz. Ancak, Main()in ar
yklenmi eitli ekilleri vardr. Kimisi bir deer dndrmek iin kullanlabilir, kimisi
argman alabilir. Bunlarn her biri burada incelenmektedir.
Main ()den Deer Dndrmek
Program sona erdiinde, Main()den bir deer dndrerek Main()i aran prosese
(genellikle bu iletim sistemidir) bir deer dndrebilirsiniz. Bunun iin Main()in u eklini
kullanabilirsiniz:
public static int Main()
Dikkat ederseniz, void olarak deklare edilmek yerine Main()in bu versiyonu int dn
tipine sahiptir.

HERKES N C#
KISIM I C# DL

222
Genellikle Main()in dn deeri, programn normal olarak m, yoksa baz anormal
koullara bal olarak m sona erdiini gsterir. Alldk olarak, 0 dn deeri genellikle
normal bir sona iaret eder. Dier deerlerin tm bir tr bir hatann meydana geldiini
gsterir.
Main()e Argman Aktarmak
Programlarn pek ou, komut satr argman denilen argmanlar alrlar. Komut satr
argman; program altrldnda, komut satr zerinde program isminin dorudan peinden
gelen bilgidir. C# programlarnda bu argmanlar Main() metoduna aktarlr. Sz konusu
argmanlar almak iin Main()in aadaki ekillerinden birini kullanmalsnz:
public static void Main(string[ ] argmanlar)
public static int Main(string[ ] argmanlar)
lk ekil void dndrr; ikincisi, nceki blmde anlatld gibi, bir tamsay deer
dndrmek iin kullanlabilir. Her ikisi iin de komut satr argmanlar Main()e aktarlan bir
string dizisinde birer karakter katar olarak saklanrlar.
rnein, aadaki program, kendisi ile birlikte arlan komut satr argmanlarnn
tmn ekranda gsterir:
// Tum komut satiri bilgisini gosterir.

using System;

class CLDemo {
public static void Main(strirtg[] args) {
Console.WriteLine(There are + args.Length +
command-line arguments.);

Console.WriteLine(They are: );
for(int i = 0; i < args.Length; i++)
Console.WriteLine(args[i]);
}
}
Eer CLDemo u ekilde altrlrsa:
CLDemo one two three
Aadaki kty ekranda greceksiniz:
There are 3 command-line arguments.
They are:
one
two
three
Komut sahn argmanlarnn ne ekilde kullanlabileceinin tadna varmak iin bir sonraki
program ele aln. Bu program mesajlar ifreler ya da mesaj ifrelerini zer. ifrelenecek veya
BLM 8: METOTLAR VE SINIFLARA DAHA YAKINDAN BR BAKI

HERKES N C#
223
ifresi zlecek mesaj komut satrnda belirtilir. ifreleme yntemi ok basittir: Bir kelimeyi
ifrelemek iin her harf bir artrlr. Bylece; A, B olur ve bu ekilde srer. ifre zmek iinse
her harf bir azaltlr.
// Mesaji sifreler veya mesajin sifresini cozer.

using System;

class Cipher {
public static int Main(string[] args) {

// argumanlarin mevcut olup olmadigini kontrol et
if(args.Length < 2) {
Console.WriteLine(Usage: encode/decode
word1 [word2...wordN]);
return 1; // basarisizlik kodunu dondur
}

/* argumanlar mevcutsa, ilk arguman encode veya decode
olmalidir */
if(args[0] != encode & args[0] != decode) {
Console.WriteLine(First arg must be encode or decode.);
return 1; // basarisizlik kodunu dondur
}

// mesaji sifrele ya da sifresini coz
for(int n = 1; n < args.Length; n++) {
for(int i = 0; i < args[n].Length; i++) {
if(args[O] == encode)
Console.Write((char) [args[n][i] + 1) );
else
Console.Write((char) (args[n][i] - 1) );
}
Console.Write( );
}
Console.WriteLine();

return 0;
}
}
Program kullanmak iin ifrelenmesini ya da ifresinin zlmesini istediiniz kelime
beinin peinden encode veya decode komutunu belirtin. Programn Cipher olarak
adlandrldn varsayarsak iki rnek alma ekli yle olabilir:
C:Cipher encode one two
pof uxp

C:Cipher decode pof uxp
one two
Bu programda iki ilgin zellik mevcuttur. Birincisi; programn, almasna devam etme-
den nce, komut satr argmannn mevcut olup olmadn nasl kontrol ettiine dikkat edin.

HERKES N C#
KISIM I C# DL

224
Bu ok nemlidir ve genelletirilebilir. Program, bir veya daha fazla komut satr argmannn
mevcut olmasma bel balarsa, doru argmanlarn tedarik edilmi olduunu daima
dorulamaldr. Bunu baaramamas, programn kmesine yol aabilir. Ayrca, komut satr ar-
gmanlarnn ilki encode ya da decode olmas gerektii iin, program ilerlemeye
balamadan bunu da kontrol eder.
kincisi, programn biti kodunu nasl dndrdne dikkat edin. Eer gerekli olan komut
satr mevcut deilse, anormal sonlanmaya iaret eden 1 dndrlr. Aksi halde, program sona
erdiinde 0 dndrlr.
Yinelenme
C#ta bir metot kendi kendisini arabilir. Bu ileme yinelenme (recursion) denir ve kendi
kendisini aran bir metoda da yinelenen (recursive) metot denilir. Yinelenme genel olarak bir
eyi kendisiyle tanmlama anlamna gelir ve kendi kendisine referansta bulunarak yaplan ta-
nma (circular definition) biraz benzer. Yinelenen bir metodun en nemli bileeni, kendi
kendisini aran bir ifadeye sahip olmasdr. Yinelenme, gl bir kontrol mekanizmasdr.
Yinelenmenin klasik rnei, bir saynn faktriyelinin hesaplanmasdr. N saysnn
faktriyeli, 1 ile N arasndaki tm tam saylarn arpmndan oluur. rnein 3 faktriyel
1x2x3 yani 6dr. Aadaki program bir saynn faktriyelinin yinelenme ile nasl
hesaplandn gstermektedir. Karlatrma yapabilmek iin ayn programn yinelenme
iermeyen bir versiyonu da verilmitir.
// Basit bir yinelenme ornegi.

using System;

class Factorial {
// Bu yinelenmeli bir fonksiyondur.
public int factR(int n} {
int result;

if(n == 1) return 1;
result = factR(n - 1) * n;
return result;
}

// Bu ise ayni fonksiyonun iterasyonlu esdeeridir.
public int factI(int n) {
int t, result;

result = 1;
for(t = 1; t = n; t++) result *= t;
return result;
}
}

class Recursion {
public static void Main() {
BLM 8: METOTLAR VE SINIFLARA DAHA YAKINDAN BR BAKI

HERKES N C#
225
Factorial f = new Factorial();

Console.WriteLine(Factorials using recursive method.);
Console.WriteLine(Factorial of 3 is + f.factR(3));
Console.WriteLine(Factorial of 4 is + f.factR(4));
Console.WriteLine(Factorial of 5 is + f.factR(5));
Console.WriteLine();

Console.WriteLine(Factorials using iterative method.);
Console.WriteLine(Factorial of 3 is + f.factI(3));
Console.WriteLine(Factorial of 4 is + f.factI(4));
Console.WriteLine(Factorial of 5 is + f.factI(5));
}
}
Programn kts yledir:
Factorials using recursive method.
Factorial of 3 is 6
Factorial of 4 is 24
Factorial of 5 is 120

Factorials using iterative method.
Factorial of 3 is 6
Factorial of 4 is 24
Factorial of 5 is 120
Yinelemeli olmayan factI() metodunun nasl alt herhalde aktr. Bu metot, 1den
balayarak her admda o ana kadar getirilen arpm sonucunu o admdaki say ile arparak
ilerlemektedir.
Yinelenmeli factR() metodunun ileyii ise biraz daha karmaktr. factR(), 1
argman ile arldnda metot, 1 dndrmektedir. Baka bir argmanla arldnda ise
dndrd deer factR(n-1)*n ifadesinin sonucudur. Bu ifadenin deerini bulmak iin
factR() bu kez de n-1 argmanyla arlmaktadr. Kullanlan argman, yani n, 1 saysna
eit olana kadar bu sre devam etmektedir. rnein, 2nin faktriyeli hesaplanrken,
factR()a yaplan ilk ar sonucunda 1 argman ile ikinci bir ar oluturulmaktadr. kinci
ar 1 argman ile yapld iin 1 dndrmekte, bu rakam daha sonra 2 ile (yani factR()a
yaplan ilk arnn argman ile) arplmakta ve bylece ilk arnn dndrecei say
bulunmaktadr. Eer denemek isterseniz, factR()n iine WriteLine() ifadeleri koyarak
metodun her seviyede nasl arldn ve ara arpmlarn ne olduunu grmek ilgin olabilir.
Bir metot kendi kendisini ardnda sistem ynnda (system stack) yeni yerel
deikenlere ve parametrelere yer ayrlr. Metodun kodu, batan itibaren bu yeni deikenler
kullanlarak altrlr. Yinelenen bir ar metodun yeni bir kopyasn oluturmaz. Sadece
argmanlar yenidir. Yinelenen arlar geri dndnde eski yerel deikenler ve parametreler
yndan kartlrlar ve programn ileyii, metodun iinde arnn yapld noktadan devam
eder. Yinelenen metotlarn adeta bir teleskop" gibi uzayp geri ksaldn dnebiliriz.

HERKES N C#
KISIM I C# DL

226
te bir baka yinelenme rnei daha. Aada yer verdiimiz displayRev() metodu,
kendisine aktarlan karakter katar argmann tersinden yazmak iin yinelenme
kullanmaktadr.
// Bir karakter katarini yinelenme kullanarak tersinden yazar.

using System;

class RevStr {

// Karakter katarini tersinden yaz.
public void displayRev(string str) {
if(str.Length 0)
displayRev(str.Substring(1, str.Length 1));
else
return;

Console.Write(str[0]);
}
}

class RevStrDemo {
public static void Main() {
string s = this is a test;
RevStr rsOb = new RevStr();

Console.WriteLine(Original string: + s);

Console.Write(Reversed string: );
rsOb.displayRev(s);

Console.WriteLine();
}
}
Programn kts yledir:
Original string: this is a test
Reversed string: tset a si siht
Programda displayRev() her arldnda, nce strnin uzunluunun sfrdan byk
olup olmadn kontrol eder. Eer uzunluk sfrdan bykse, displayRev() strden ilk
karakterin karlmasyla oluan yeni bir karakter katar ile yinelenmeli olarak arlr. Bu
sre, uzunluu sfr olan bir karakter katar parametre olarak aktarlana kadar devam eder.
Sfr uzunluktaki karakter katarna ulaldnda, yani orijinal karakter katarnn sonu
geldiinde, bu sefer de yinelenme ilemleri zlerek geri dnlr ve her admda o admdaki
karakter katarnn ba harfi yazlr. Bu da orijinal karakter katarnn tersten yazlmasn salar.
Pek ok program parasnn yinelenmeli versiyonlar, iterasyonlu versiyonlardan biraz
daha yava alr. Bunun nedeni, yaplan ek metot arlarnn kaynak kullanm ve ynetim
bakmndan ek i karmasdr. Bir metodun ar sayda yinelenmeli olarak arlmas sistem
ynnn tamasna (stack overflow) neden olabilir. Parametreler ve yerel deikenler sistem
BLM 8: METOTLAR VE SINIFLARA DAHA YAKINDAN BR BAKI

HERKES N C#
227
ynnda sakland iin, her yinelenmeli ar bu parametrelerin yeni bir kopyasn oluturur.
Bu da baz durumlarda yn kapasitesinin dolmasna halta tamasna neden olabilir. Bu da
C#n kural d durum oluturmasyla sonulanr. Ancak, yinelenmeli bir ar kontrolden
kmadka, byk olaslkla, bu konuda endie etmenize gerek olmayacaktr.
Yinelenmenin ana avantaj, baz algoritmalarn iterasyonlu biimlerine gre yinelenmeli
olarak daha basit ve net uygulanabilmesidir. rnein, QuickSort algoritmasn iterasyonlu
olarak uygulamak olduka gtr. Aynca, baz problemler, zellikle de yapay zekayla ilgili
problemler, doalar itibariyle yinelenmeli zmlere daha yatkn grnmektedir.
Yinelenmeli metotlar yazarken mutlaka if gibi bir koullu ifade kullanmalsnz. Bu
ifade, yeni bir yinelenmeli ar yapmadan geri dnmelidir. Aksi halde metodu ardnzda
asla geri dnmeyecektir. Yinelenme ile alrken bu hata ok yaygn olarak yaplr.
Yinelenmeyle urarken bol bol WriteLine() ifadeleri kullanarak ileyii izleyebilir ve bir
hata yaptysanz programn almasn durdurabilirsiniz.
statici Anlamak
Bazen bir snfn herhangi bir nesnesinden bamsz olarak kullanacanz bir snf yesi
tanmlamanz gerekebilir. Normal olarak bir snf yesine o snfn bir nesnesi zerinden eriil-
mesi gereklidir. Ancak, belli bir rnee referansta bulunmadan kendi bana kullanlabilecek
bir ye oluturmak da mmkndr. Byle bir ye oluturmak iin, o yenin deklarasyonundan
nce bana static anahtar kelimesini yazn. Bir ye static olarak tanmland zaman, o
ye, kendi snfndan herhangi bir nesne oluturulmadan nce ve herhangi bir nesneye
referansta bulunmadan kullanlabilir. Hem metotlar hem de deikenleri static olarak
deklare edebilirsiniz. static bir yenin en yaygn rnei Main()dir. Main(), programnz
baladnda iietim sistemi tarafndan arlmak zorunda olduu iin static olarak deklare
edilmek zorundadr.
static bir yeyi snfn dnda kullanmak iin yenin snfn yazmal, peinden de nokta
operatrn kullanmalsnz. Bu durumda herhangi bir nesne oluturmanz gerekmez. Hatta,
static bir yeye bir nesne rnei zerinden erimek mmkn deildir. static bir yeye an-
cak kendi snfnn ad zerinden eriilebilir. rnein, Timer adl bir snfa ait count adl bir
static deikene 10 deerini atamak istiyorsanz su satr kullann:
Timer.count = 10;
Bu biim, normal rnek deikenlerine bir nesne zerinden erime yntemine
benzemektedir; tek fark, snf isminin kullanlyor olmasdr. static bir metot da ayn
ekilde, yani snf isminden sonra nokta operatr kullanlarak arlabilir.
static olarak deklare edilen deikenler esas itibariyle global deikenlerdir. Bir
static deikenin snfna ait nesneler deklare edildiinde static deikenin herhangi bir
kopyas oluturulmaz. Snfn tm rnekleri ayn static deikeni paylar. static bir
deikene ilk deer atamas, o deikenin snf yklenirken yaplr. lk deer atamas ak bir

HERKES N C#
KISIM I C# DL

228
ekilde yaplmyorsa, deikene, nmerik deerler iin 0, nesne referanslar iin null, bool
tipi deikenler iin ise false deeri atanr. Dolaysyla, static bir deikenin her zaman bir
deeri vardr.
static bir metotla normal bir metot arasndaki fark, static metodun herhangi bir nesne
oluturmaya gerek kalmadan snfnn ismi kullanlarak anlabilmesidir. Bunun bir rneini
daha nce grmtk: C#n System.Math snf iinde static bir metot olan Sqrt() byle
bir metottu.
te, static bir deiken ve static bir metot oluturan bir rnek:
// Static kullanir.

using System;

class StaticDemo {
// Static bir degisken
public static int val = 100;

// Static bir metod
public static int valDiv2() {
return val / 2;
}
}

class SDemo {
public static void Main() {

Console.WriteLine(Initial value of StaticDemo.val is
+ StaticDemo.val);

StaticDemo.val = 8;
Console.WriteLine(StaticDemo.val is + StaticDemo.val);
Console.WriteLine(StaticDemo.valDiv2(): +
StaticDemo.valDiv2());
}
}
Program u kty retir:
Initial value of StaticDemo.val is 100
StaticDemo.val is 8
StaticDemo.valDiv2(): 4
ktdan anlald gibi, static bir deikene ilk deer program baladnda,
deikenin snfndan herhangi bir nesne oluturulmadan nce atanr.
static metotlarla ilgili eitli kstlamalar vardr:
1. static bir metodun bir this referans olamaz.

2. static bir metot dier static metotlar dorudan arabilir. Ancak kendi
snfndan bir rnek metodu dorudan aramaz. Bunun nedeni, rnek metotlarn
BLM 8: METOTLAR VE SINIFLARA DAHA YAKINDAN BR BAKI

HERKES N C#
229
bir snfa zg rnekler zerinde almas, static bir metodun ise bu zellie
sahip olmamasdr.

3. static bir metot sadece static olan verilere dorudan erimek zorundadr.
static bir metot bir rnek deikenine dorudan eriemez, nk snfnn bir
rnei zerinde ilem yapmak durumunda deildir.
rnein, aadaki snfta, valDivDenom() adl static metot geersizdir:
class StaticError {
int denom = 3; // normal bir ornek degisken
static int val = 1024; // static bir degisken

// Hata! static olmayan bir degiskene
static bir metodun icinden dogrudan erisilemez */
static int valDivDenom() {
return val/denom; // hata oldugundan derleme gerceklesmez!
}
}
Burada denom, static bir metodun iinden eriilmesi mmkn olmayan normal bir rnek
deikenidir. Ancak valin kullanmnda problem yoktur, nk val, static bir deikendir.
Ayn problem, static olmayan bir metot, ayn snfn static bir metodunun iinden
arlmaya alldnda da ortaya kar. rnein:
using System;

class AnotherStaticError {
// static olmayan metod.
void nonStaticMeth() {
Console.WriteLine(Inside nonStaticMeth().);
}

/* Hata! static bir metodun icinden static olmayan
bir metot dogrudan cagrilamaz. */
static void staticMeth() {
nonStaticMeth(); /* hatali oldugu icin derleme
gereklesmeyecektir. */
}
}
Bu durumda static olmayan (yani rnek olan) bir metodu static bir metodun iinden
armaya almak sonucunda derleyici hatas ortaya kmtr.
u nokta nemlidir: static bir metot, kendi snfnn rnek metotlarn arabilir ve
rnek deikenlerine eriebilir. Ancak bunu o snfn bir nesnesi zerinden yapmak
zorunluluundadr. Bunlarla ilgili tek kstlama, rnek metotlar ya da deikenleri nesne
belirtmeden kullanamamasdr. rnein aadaki program paras gayet geerlidir:
class MyClass {
// static olmayan metod.

HERKES N C#
KISIM I C# DL

230
void nonStaticMeth() {
Console.WriteLine(Inside nonStaticMeth().);
}

/* static olmayan bir metot static bir metodun icinden nesne
referansi kullanarak cagrilabilir. */
public static void staticMeth(MyClass ob) {
ob.nonStaticMeth(); // Bu ifade gecerlidir.
}
}
static alanlar herhangi spesifik bir nesneden bamsz olduu iin bu alanlar tm bir
snfa uygulanmas sz konusu bilgileri tutmak iin yararldr. Byle bir durumun rnei
aada verilmitir. Bu rnekte, eldeki nesne saysn tutmak iin static bir alan
kullanlmaktadr.
// Ornekleri saymak icin static bir alan kullanir.

using System;

class CountInst {
static int count = 0;

// nesne olusturuldugunda countu artir
public CountInst() {
count++;
}

// nesne yok edildiginde countu eksilt
-CountInst() {
Count--;
}

public static int getcount() {
return count;
}
}

class CountDemo {
public static void Main() {
CountInst ob;

for(int i = 0; i < 10; i++) {
ob = new CountInst();
Console.WriteLine(Current count: +
CountInst.getcount());
}
}
}
Programn kts u ekildedir:
Current count: 1
Current count: 2
Current count: 3
BLM 8: METOTLAR VE SINIFLARA DAHA YAKINDAN BR BAKI

HERKES N C#
231
Current count: 4
Current count: 5
Current count: 6
Current count: 7
Current count: 8
Current count: 9
Current count: 10
CountInst tipinden bir nesne her oluturulduunda, static alan olan count artrlr.
Bir nesne yok edildiinde de count eksiltilir. Bylece, count daima o an mevcut olan
nesnelerin saysn tutar. Bu, ancak static bir alan kullanmyla mmkn olabilir. Bir rnek
deikeninin bu sayy tutmas mmkn deildir, nk count spesifik bir rnekle deil tm
snfla ilgilidir.
imdi static kullanan bir rnee daha bakalm. Bu blmn balarnda bir snf fabrikas
kullanlarak snf nesnelerinin nasl oluturabileceini grmtk. O rnekte snf fabrikas
static olmayan bir metottu. Dolaysyla sadece bir nesne referans araclyla
arabiliyordu. Bu nedenle, fabrika metodunun arlabilmesi iin o snfn varsaylan
nesnesinin oluturulmas gerekliydi. Ancak, bir snf fabrikasn uygulamann daha iyi bir yolu
static metot kullanmaktr. Bylece snf fabrikas gereksiz bir nesne oluturmakszn
arlabilir. Bu iyiletirmeyi yanstan static snf fabrikas rnei aada yer almaktadr:
// Static bir sinif fabrikasinin kullanimi.

using System;

class MyClass {
int a, b;

// MyClass icin bir sinif fabrikasi olustur.
static public MyClass factory(int i, int j) {
MyClass t = new MyClass();

t.a = i;
t.b = j;

return t; // bir nesne dondur
}

public void show() {
Console.WriteLine(a and b: + a + + b);
}
}

class MakeObjects {
public static void Main() {
int i, j;

// fabrikayi kullanarak nesneler olustur
for(i = 0, j = 10; i < 10; i++, j--) {
MyClass ob = MyClass.factory(i, j); // bir nesne al
ob.show();

HERKES N C#
KISIM I C# DL

232
}

Console.WriteLine();
}
}
Bu versiyonda factory() u satrdaki kod ile kendi snfnn ad ile arlmaktadr:
MyClass ob = MyClass.factory(i, j); // bir nesne al
Fabrikay kullanmak iin nce MyClass nesnesi oluturmaya gerek yoktur.
static Yaplandrclar
Bir yaplandrc da static olarak belirtilebilir, static bir yaplandrc tipik olarak bir
rnee deil de bir snfa ait olan niteliklere (attributes) balang deeri atamak iin kullanlr.
Bir baka ifade ile, static bir yaplandrc, bir snfa ait herhangi bir nesne oluturulmadan
nce o snfn baz zelliklerine ilk deer atayabilir. te, basit bir rnek:
// static bir yapilandirici kullanir.
using System;

class Cons {
public static int alpha;
public int beta;

// static yapilandirici
static Cons() {
alpha = 99;
Console.WriteLine(Inside static constructor.);
}

// ornek yapilandirici
public Cons() {
beta = 100;
Console.WriteLine(Inside instance constructor.);
}
}

class ConsDemo {
public static void Main() {
Cons ob = new Cons();

Console.WriteLine(Cons.alpha: + Cons.alpha);
Console.WriteLine(ob.beta: + ob.beta);
}
}
Programn kts yledir:
Inside static constructor.
Inside instance constructor.
Cons.alpha: 99
ob.beta: 100
BLM 8: METOTLAR VE SINIFLARA DAHA YAKINDAN BR BAKI

HERKES N C#
233
Dikkat ederseniz, static yaplandrc otomatik olarak ve rnek yaplandrcdan nce
arlmaktadr. Bu, genelletirilebilir. Tm durumlarda static yaplandrc herhangi bir
rnek yaplandrcdan nce altrlacaktr. Ayrca, static yaplandrclar private
olmaldrlar ve programnz tarafndan arlamazlar.




D O K U Z U N C U B L M

OPERATRLERN AIRI
YKLENMES




















9
BLM 9: OPERATRLERN AIRI YKLENMES

HERKES N C#
235
C#, bir operatrn anlamn, oluturmu olduunuz snfa bal olarak tanmlamanza
imkan vermektedir. Bu ilem operatrlerin ar yklenmesi olarak adlandrlr. Bir operatr
ar ykleyerek sz konusu operatrn kullanmn, oluturduunuz snf iin geniletirsiniz.
Operatrn etkileri tamamen sizin kontrolnzdedir ve bir snftan dierine deiiklik
gsterebilir. rnein, bir bal listenin tanml olduu bir snf, listeye bir nesne eklemek iin +
operatrn kullanabilir. Bir yn gerekleyen bir snf da yna bir nesne yerletirmek iin +
operatrn kullanabilir. Bir baka snf ise + operatrn tmyle farkl bir ekilde
kullanabilir.
Bir operatr ar yklendiinde bu operatrn orijinal anlam kaybolmaz. Sadece, belirli
bir snfa bal olarak yeni bir ilem eklenmi olur. Bu yzden, rnein bir bal listeyi ele
almas iin + operatrn ar yklemek, operatrn tamsaylara bal olarak tanmlanm
anlamnn (yani, toplama ilemi) deimesine neden olmaz.
Operatrlerin ar yklenmesinin salad balca avantaj udur: Bu ilem, yeni bir snf
tipini programlama ortamnza kesintisiz olarak entegre etmenize imkan verir. Tiplerin bu
eklide geniletilebilmesi, C# gibi nesne ynelimli dillerin gcnn nemli bir parasdr. Bir
snf iin operatrler tanmland andan itibaren, C#n normal deyim sz dizimini kullanarak
bu snfn nesneleri zerinde ilem yapabilirsiniz. Hatta bir nesneyi, dier tiplerdeki verileri
ieren deyimlerde bile kullanabilirsiniz. Operatrlerin ar yklenmesi, C#n en gl
zelliklerinden biridir.
Operatrlerin Ar Yklenmesiyle lgili Temel
Kavramlar
Operatrlerin ar yklenmesi, metotlarn ar yklenmesiyle yakndan balantldr. Bir
operatr ar yklemek iin bir operatr metodu oluturmak amacyla operator anahtar
kelimesini kullanrsnz. Operatr metodu, operatrn kendi snfna bal olarak faaliyetlerini
tanmlar.
ki eit operatr metodu vardr: tekli (unary) operatrler iin ve ikili operatrler iin. Her
birinin genel yaps aada gsterilmitir:
// Tekli bir operatrn ar yklenmesinin genel yaps
public static dn-tipi operator op(param-tipi operand)
{
// ilemler
}

// kili bir operatrn ar yklenmesinin genel yaps
public static dn-tipi operator op(param-tipi1 operand1, param-tipi1 operand2)
{
// ilemler
}

HERKES N C#
KISIM I C# DL

236
Burada, ar yklenecek operatr, sz gelii + veya /, op yerine yerletirilir. dn-tipi,
belirtilen ilem tarafndan dndrlen deerin tipidir. Dn tipi, tercih ettiiniz herhangi tipte
olabilse bile, genellikle operatrn ar yklenmekte olduu snf ile ayn tiptedir. Bu
korelasyon, ar yklenmi operatrn deyimlerde kullanmn kolaylatrr. Tekli operatrler
iin operand, operand zerinden aktarlr. kili operatrler iin ise operandlar operand1 ve
operand2 zerinden aktarlr.
Tekli operatrler iin operand, operatrn tanmlanmakta olduu snf ile ayn tipte
olmaldr. kili operatrler iin operandlardan en az biri kendi snf ile ayn tipte olmaldr. Bu
nedenle, henz oluturmadnz nesneler iin C# operatrlerini ar ykleyemezsiniz.
rnein, + operatrn int veya string iin yeniden tanmlayamazsnz.
Bir dier husus: Operatr parametreleri ref veya out niteleyicilerini kullanmamaldr.
kili Operatrleri Ar Yklemek
Operatrlerin ar yklenme ileminin ne ekilde ilediini anlamak iin gelin, iki ikili
operatr, rnein + ve - operatrlerini ar ykleyen bir rnekle balayalm. Aadaki
program, boyutlu uzayda bir nesnenin koordinatlarn tutan ThreeD adnda bir snf
oluturmaktadr. Ar yklenmi +, bir ThreeD nesnesinin koordinatlarn tek tek bir baka
nesnenin koordinatlarna ekler. Ar yklenmi - bir nesnenin koordinatlarn bir
dierininkinden kartr.
// Operatorlerin asiri yuklenmesine bir ornek.

using System;

// Uc boyutlu bir koordinat sinifi.
class ThreeD {
int x, y, z; // uc boyutlu koordinatlar

public ThreeD() { x = y = z = 0; }
public ThreeD(int i, int j, int k) { x = i; y = j; z = k; }

// Ikili + operatorunu asiri yukle
public static ThreeD operator +(ThreeD op1, ThreeD op2)
{
ThreeD result = new ThreeD();

/* Bu,iki noktanin koordinatlarini toplar
ve sonucu dondurur. */
result.x = op1.x + op2.x; // Bunlar tamsayi toplama;
result.y = op1.y + op2.y; // +, bunlara bagli olarak
result.z = op1.z + op2.z; // orijinal anlamini korur

return result;
}

// Ikili - operatorunu asiri yukle.
public static ThreeD operator -(ThreeD op1, ThreeD op2)
BLM 9: OPERATRLERN AIRI YKLENMES

HERKES N C#
237
{
ThreeD result = new ThreeD();

/* Operandlarin sirasina dikkat edin.
op1, soldaki operand; op2 ise sagdaki. */
result.x = op1.x - op2.x; // bunlar, tamsayi cikarmadir
result.y = op1.y - op2.y;
result.z = op1.z - op2.z;

return result;
}

// x, y, z koordinatlarini goster.
public void show()
{
Console.WriteLine(x + , + y + , + z);
}
}

class ThreeDDemo {
public static void Main() {
ThreeD a = new ThreeD(1, 2, 3);
ThreeD b = new ThreeD(10, 10, 10);
ThreeD c = new ThreeD();

Console.Write(Here is a: );
a.show();
Console.WriteLine();
Console.Write(Here is b: );
b.show();
Console.WriteLine();

c = a + b; //a ve byi topla
Console.Write(Result of a + b: );
c.show();
Console.WriteLine();

c = a + b +c; // a,b ve cyi topla
Console.Write(Result of a + b + c: );
c.show();
Console.WriteLine();

c = c - a; // a'yi cikar
Console.Write(Result of c - a: );
c.show();
Console.WriteLine();

c = c b; // byi cikar
Console.Write(Result of c - b: );
c.show();
Console.WriteLine();
}
}
Bu program aadaki kty retir:

HERKES N C#
KISIM I C# DL

238
Here is a: 1, 2, 3
Here is b: 10, 10, 10
Result of a + b: 11, 12, 13
Result of a + b + c: 22, 24, 26
Result of c - a: 21, 22, 23
Result of c - b: 11, 12, 13
Gelin, ar yklenmi + operatrnden balayarak yukardaki program dikkatlice
inceleyelim. ThreeD tipindeki iki nesne zerine + operatr uygulandnda,
operator+()da grld gibi bu nesnelerin her birinin koordinatlarnn iddeti toplanr.
Ancak, bu metodun, operandlarnn hibirinin deerini deitirmediine dikkat edin. Bunun
yerine metot, ilemin sonucunu ieren ThreeD tipinde yeni bir nesne dndrr. + ileminin her
iki nesnenin ieriini deitirmemesinin nedenini anlamak iin standart aritmetik + ileminin u
ekilde uygulann ele aln: 10+12. Bu ilemin sonucu 22dir, fakat ne 10 ne de 12 bu ilem
sonucunda deitirilmitir. Ar yklenmi bir operatrn, operandlarndan birinin deerini
deitirmesini nleyecek hibir kural mevcut olmamasna ramen, ar yklenmi bir
operatrn faaliyetlerinin operatrn alldk anlam ile tutarl olmas en iyisidir.
operator+() metodunun ThreeD tipinde bir nesne dndrdne dikkat edin. Geri,
metot herhangi geerli bir C# tipini dndrebilirdi; ancak, metodun bir ThreeD nesnesi
dndrmesi gerei + operatrnn a+b+c gibi bileik deyimlerde kullanlmasna imkan
vermektedir. Burada a+b, ThreeD tipinde bir sonu retir. Sonra bu deer cye eklenebilir.
a+b ileminin sonucunda baka tipte bir deer retilmi olsayd bu tr bir deyim almazd.
Bir baka nemli husus ise udur: Koordinatlar operator+() metodunun iinde birbiri ile
toplandnda, koordinatlarn tek tek toplanmas, tamsay toplamas olarak sonulanr, Bunun
nedeni, her bir koordinatn, yani x, y ve znin bir tamsay nicelik olmasdr. + operatrnn
ThreeD tipindeki nesneler iin ar yklenmesinin, tamsay deerlere uygulanma ekli
zerinde hibir etkisi olmaz.
Simdi operatr-() metoduna gz atalm. - operatr tpk + operatr gibi alr; tek
fark, parametre srasnn bu kez nemli olmasdr. Toplamann deime zellii olduunu, fakat
karmann bu zellii olmadn hatrlayn. (Yani, A-B ile B-A ayn deildir!) Tm ikili
operatrler iin operatre aktarlan ilk parametre soldaki operand ierecektir. kinci parametre
ise sa taraftakini ierecektir. Deime zellii olmayan operatrlerin ar yklenmi
versiyonlarn uygularken hangi operandn solda hangisinin sada olduunu hatrlamalsnz.
Tekli Operatrleri Ar Yklemek
Tekli operatrler de tpk ikili operatrler gibi ar yklenir. En temel fark, elbette, bu kez
tek bir operandn olmasdr. rnein, ThreeD snf iin tekli eksi operatrn ar ykleyen
bir metot aadaki gibidir:
BLM 9: OPERATRLERN AIRI YKLENMES

HERKES N C#
239
// Tekli - operatorunu asiri yukler.
public static ThreeD operator (ThreeD op)
{
ThreeD result = new ThreeD();

result.x = -op.x;
result.y = -op.y;
result.z = -op.z;

return result;
}
Burada, operandn negatif hale getirilmi alanlarn ieren yeni bir nesne oluturulmaktadr.
Sonra da bu nesne dndrlmektedir. Dikkat ederseniz, operand deimemitir. Bunun nedeni
yine, tekli eksi operatrnn alldk anlamn korumaktr. rnein, u tr bir deyimde,
a = -b
a, bnin negatif hale getirilmi eklini alr fakat b deimez.
Yine de, bir operatr metodunun operandnn ieriini deitirmeye gerek duyaca iki du-
rum mevcuttur; ++ ve --. Bu operatrlerin alldk anlamlar artrma ve eksiltme olduu iin
ar yklenmi ++ veya -- de genellikle operandn artrmal ya da eksiltmelidir. Bylece, bu
iki operatr ar yklediinizde operand genellikle deiiklie urar. rnein, ThreeD snf
iin bir operatr++() metodu aada yer almaktadr:
// Tekli ++ operatorunu asiri yukle.
public static ThreeD operator ++(ThreeD op)
{
// ++ icin, argumani degistir
op.x++;
op.y++;
op.z++;

return op; // operand dondurulur
}
Dikkat ederseniz, op ile ilikilendirilen nesne bu metot tarafndan deiiklie
uramaktadr. Bylece, ++ ilemindeki operand artrlm olur. Deitirilen nesne de ayrca
dndrlr. Bu, ++ operatrnn daha byk bir deyimde kullanlmas iin gereklidir.
te, tekli -- ve ++ operatrn gsteren nceki rnek programn geniletilmi bir
versiyonu:
// Operatorlerin asiri yuklenmesi hakkinda birkac ornek daha

using System;

// Uc boyutlu koordinat sinifi.
class ThreeD {
int x, y, z; // uc boyutlu koordinatlar


HERKES N C#
KISIM I C# DL

240
public ThreeD() { x = y = z = 0; }
public ThreeD(int i, int j, int k) { x = i; y = j; z = k; }

// Ikili + operatrn asiri yukle
public static ThreeD operator +(ThreeD op1, ThreeD op2)
{
ThreeD result = new ThreeD();

/* Bu iki noktanin koordinatlarini toplar ve
sonucu dondurur. */
result.x = op1.x + op2.x;
result.y = op1.y + op2.y;
result.z = op1.z + op2.z;

return result;
}

// Ikili - operatorunu asiri yukle.
public static ThreeD operator -(ThreeD op1, ThreeD op2)
{
ThreeD result = new ThreeD();

/* Operandlarin sirasina dikkat edin.
op1 sol taraftaki operand, op2 ise sag taraftaki. */
result.x = op1.x - op2.x;
result.y = op1.y op2.y;
result.z = op1.z - op2.z;

return result;
}

// Tekli - operatorunu asiri yukle.
public static ThreeD operator -(ThreeD op)
{
ThreeD result = new ThreeD();

result.x = -op.x;
result.y = -op.y;
result.z = -op.z;

return result;
}

// Tekli ++ operatorunu asiri yukle.
public static ThreeD operator ++(ThreeD op)
{
// ++ icin, argumani degistir
op.x++;
op.y++;
op.z++;

return op;
}

// X, Y, Z koordinatlarini goster.
BLM 9: OPERATRLERN AIRI YKLENMES

HERKES N C#
241
public void show()
{
Console.WriteLine(x + , + y + , + z);
}
}

class ThreeDDemo {
public static void Main() {
ThreeD a = new ThreeD(1, 2, 3);
ThreeD b = new ThreeD(10, 10, 10);
ThreeD c = new ThreeD();

Console.Write(Here is a: );
a.show();
Console.WriteLine();
Console.Write(Here is b: );
b.show();
Console.WriteLine();

c = a + b; // a ve byi topla
Console.Write(Result of a + b: );
c.show();
Console.WriteLine();

c = a + b + c; //a, b ve cyi topla
Console.Write(Result of a + b + c: );
c.show();
Console.WriteLine();

c = c - a; // ayi cikar
Console.Write(Result of c a: );
c.show();
Console.WriteLine();

c = c - b; // byi cikar
Console.Write(Result of c - b: );
c.show();
Console.WriteLine();

c = -a; // cye -a degerini ata
Console.Write(Result of a: );
c.show();
Console.WriteLine();

a++; // ayi bir artir
Console.Write(Result of a++: );
a.show();
}
}
Programn kts aada gsterilmitir:
Here is a: 1, 2, 3
Here is b: 10, 10, 10

HERKES N C#
KISIM I C# DL

242
Result of a + b: 11, 12, 13
Result of a + b + c: 22, 24, 26
Result of c - a: 21, 22, 23
Result of c - b: 11, 12, 13
Result of -a: -1, -2, -3
Result of a++: 2, 3, 4
Bildiiniz gibi, ++ ve -- operatrlerinin hem nek, hem de sonek formlar mevcuttur.
rnein, hem
++a;
hem de
a++;
artrma operatrnn geerli kullanmlardr. Ancak, ++ ya da -- ar yklendiinde her
iki form da ayn metodu arr. Bylece, ar ykleme sz konusu olduunda ++ veya --
operatrlerinin nekli veya sonekli formlarn ayrt etmek mmkn deildir.
Standart C# Tipleri zerindeki lemleri Kontrol Altna
Almak
Herhangi bir snf ve operatr iin bir operatr metodunun kendisi ar yklenebilir.
Bunun en bilinen nedenlerinden biri, snf tipi ve dier veri tipleri, sz gelii standart tipler
arasndaki ilemlere imkan vermektir. rnein, bir kez daha ThreeD snfn ele aln. Bu
noktaya kadar + operatrn nasl ar ykleyeceinizi grmtnz. Bu sayede, + operatr
bir ThreeD nesnesinin koordinatlarn bir baka nesnenin koordinatlaryla toplar. Ancak,
ThreeD iin tanmlamak isteyebileceiniz tek toplama yntemi bu deildir. rnein, bir
ThreeD nesnesinin her koordinatna bir tamsay deer eklemek yararl olabilir. Bu tr bir ilem
eksenlerin evriminde kullanlabilir. Bu tr bir ilemi gerekletirmek iin + operatrn,
aadaki gibi ikinci kez ar yklemeniz gerekir:
// nesne + int icin ikili + operatorunu asiri yukle.
public static ThreeD operator +(ThreeD op1, int op2)
{
ThreeD result = new ThreeD();

result.x = op1.x + op2;
result.y = op1.y + op2;
result.z = op1.z + op2;

return result;
}
BLM 9: OPERATRLERN AIRI YKLENMES

HERKES N C#
243
kinci parametrenin int tipinde olduuna dikkat edin. Bylece, yukardaki metot, bir
ThreeD nesnesinin her alanna bir tamsay deer eklenmesine imkan vermektedir. Buna izin
verilebilir, nk nceden akland gibi, bir ikili operatr ar yklerken operandlardan
yalnzca biri, operatrn ar yklenmekte olduu snf ile ayn tipte olmaldr. Dier operand
herhangi baka bir tipte olabilir.
te, ThreeDnin iki adet ar yklenmi + metodu ieren bir versiyonu:
/* nesne + nesne ve nesne + int icin
toplama operatorunu asiri yukle. */

using System;

// Uc boyutlu koordinat sinifi.
class ThreeD {
int x, y, z; // Uc boyutlu koordinatlar

public ThreeD() { x = y = z = 0; }
public ThreeD(int i, int j, int k) { x = i; y = j; z = k; }

// nesne + nesne icin ikili + operatorunu asiri yukle.
public static ThreeD operator +(ThreeD op1, -ThreeD op2)
{
ThreeD result = new ThreeD();

// Bu, iki noktanin koordinatlarini toplar ve sonucu dondurur.
result.x = op1.x + op2.x;
result.y = op1.y + op2.y;
result.z = op1.z + op2.z;

return result;
}

// nesne + int icin ikili + operatorunu asiri yukle
public static ThreeD operator +(ThreeD op1, int op2)
{
ThreeD result = new ThreeD();

result.x = op1.x + op2;
result.y = op1.y + op2;
result.z = op1.z + op2;

return result;
}

// X, Y, Z koordinatlarini goster.
public void show()
{
Console.WriteLine(x + , + y + , + z);
}
}

class ThreeDDemo {
public static void Main() {

HERKES N C#
KISIM I C# DL

244
ThreeD a = new ThreeD(1, 2, 3);
ThreeD b = new ThreeD(10, 10, 10);
ThreeD c = new ThreeD();

Console.Write(Here is a: );
a.show();
Console.WriteLine();
Console.Write(Here is b: );
b.show();
Console.WriteLine();

c = a + b; // nesne + nesne
Console.Write(Result of a + b: );
c.show();
Console.WriteLine();

c = b + 10; // nesne + int
Console.Write(Result of b + 10: );
c.show();
}
}
Bu programn kts aada gsterilmitir:
Here is a: 1, 2, 3
Here is b: 10, 10, 10
Result of a + b: 11, 12, 13
Result of b + 10: 20, 20, 20
ktnn da dorulad gibi, + operatr iki nesneye uygulandnda nesnelerin
koordinatlar toplanr. +, bir nesne ve bir tamsayya uygulandnda koordinatlar tamsay deer
kadar artrlr.
+ operatrnn az nce gsterilen ar yklenmi ekli ThreeD snfna yararl bir beceri
katm olmakla birlikte, ii tam olarak bitirmi olmuyor. imdi neden byle olduunu
aklayalm. operator + (ThreeD,int) metodu u ifadelere imkan verir:
ob1 = ob2 + 10;
Fakat ne yazk ki, u trlere imkan vermez:
ob1 = 10 + ob2;
Bunun nedeni, tamsay argmann sag taraftaki operand olan ikinci argman olmasdr.
Problem, yukardaki ifadede tamsay argmann sola yerletirilmesidir. Her iki ifade eklini de
mmkn klmak iin + operatrn bir kez daha ar yklemeniz gerekecek. Bu versiyonda ilk
parametre int tipinde, ikinci parametre ThreeD tipinde olmaldr. operator+() metodunun
bir versiyonu nesne + tamsay ilemini, dier versiyonu ise tamsay + nesne ilemini ele alr. +
operatrn (ya da dier ikili operatrlerden herhangi birini) bu ekilde ar yklemek standart
BLM 9: OPERATRLERN AIRI YKLENMES

HERKES N C#
245
bir tipin, operatrn sol ya da sa tarafnda bulunmasna imkan vermektedir. te, +
operatrn imdi anlatlan ekliyle ar ykleyen ThreeDnin bir versiyonu:
/* nesne + nesne, nesne + int ve
int + nesne icin + operatorunu asiri ykler. */

using System;

// uc boyutlu koordinat sinifi.
class ThreeD {
int x, y, z; // uc boyutlu koordinatlar

public ThreeD() { x = y = z = 0; }
public ThreeD(int i, int j, int k) { x = i; y = j; z = k; }

// nesne + nesne icin ikili + operatorunu asiri yukle.
public static ThreeD operator +(ThreeD op1, ThreeD op2)
{
ThreeD result = new ThreeD();

/* Bu, iki noktanin koordinatlarini toplar
ve sonucu dondurur. */
result.x = op1.x + op2.x;
result.y = op1.y + op2.y;
result.z = op1.z + op2.z;

return result;
}

// nesne + int icin ikili + operatorunu asiri yukle.
public static ThreeD operator +(ThreeD op1, int op2)
{
ThreeD result = new ThreeD();

result.x = op1.x + op2;
result.y = op1.y + op2;
result.z = op1.z + op2;

return result;
}

// int + nesne icin ikili + operatorunu asiri yukle.
public static ThreeD operator +(int op1, ThreeD op2)
{
ThreeD result = new ThreeD();

result.x = op2.x + op1;
result.y = op2.y t op1 ;
result.z = op2.z + op1;

return result;
}

// X, Y, Z koordinatlarini goster.
public void show()

HERKES N C#
KISIM I C# DL

246
{
Console.WriteLine(x + , + y + , + z);
}
}

class ThreeDDemo {
public static void Main() {
ThreeD a = new ThreeD(1, 2, 3);
ThreeD b = new ThreeD(10, 10, 10);
ThreeD c = new ThreeD();

Console.Write(Here is a: );
a.show();
Console.WriteLine();
Console.Write(Here is b: );
b.show();
Console.WriteLine();

c = a + b; // nesne + nesne
Console.Write(Result of a + b: );
c.show();
Console.WriteLine();

c = b + 10; // nesne + int
Console.Write(Result of b + 10: );
c.show();
Console.WriteLine();

c = 15 + b; // int + nesne
Console.Write(Result of 15 + b: );
c.show();
}
}
Bu programn kts aada gsterilmitir:
Here is a: 1, 2, 3
Here is b: 10, 10, 10
Result of a + b: 11, 12, 13
Result of b + 10: 20, 20, 20
Result of 15 + b: 25, 25, 25
likisel Operatrleri Ar Yklemek
== ya da < gibi ilikisel operatrler de ar yklenebilir ve bu ilemler aka bellidir.
Genellikle, ar yklenmi bir operatr true veya false deeri dndrr. Bu, bu
operatrlerin normal kullanmlarn korur ve ar yklenmi ilikisel operatrlerin koul
ifadelerinde kullanlmasna imkan verir. Eer farkl bir tipte bir sonu dndrrseniz,
operatrn becerisini byk lde kstlyorsunuz demektir.
BLM 9: OPERATRLERN AIRI YKLENMES

HERKES N C#
247
te, ThreeD snfnn < ve > operatrlerini ar ykleyen bir versiyonu:
// < ve > operatorlerini asiri yukle.

using System;

// Uc boyutlu koordinat sinifi.
class ThreeD {
int k, y, z; // Uc boyutlu koordinatlar

public ThreeD() { x = y = z = 0; }
public ThreeD(int i, int j, int k) { x = i; y = j; z = k; }

// < operatorunu asiri yukle.
public static bool operator <(ThreeD op1, ThreeD op2)
{
if((op1.x < op2.x) && (op1.y < op2.y) && (op1.z < op2.z))
return true;
else
return false;
}

// > operatorunu asiri yukle.
public static bool operator >(ThreeD op1, ThreeD op2)
{
if((op1.x > op2.x) && (op1.y > op2.y) && (op1.z > op2.z))
return true;
else
return false;
}

// X, Y, Z koordinatlarini goster.
public void show()
{
Console.WriteLine(x + , + y + , + z);
}
}

class ThreeDDemo {
public static void Main() {
ThreeD a = new ThreeD(5, 6, 7);
ThreeD b = new ThreeD(10, 10, 10);
ThreeD c = new ThreeD(1, 2, 3);

Console.Write(Here is a: );
a.show();
Console.Write(Here is b: );
b.show();
Console.Write(Here is c: );
c.show();

Console.WriteLine();

if(a > c) Console.WriteLine(a > c is true);
if(a < c) Console.WriteLine(a < c is true);

HERKES N C#
KISIM I C# DL

248
if(a > b) Console.WriteLine(a > b is true);
if(a < b) Console.WriteLine(a < b is true);
}
}
Bu programn kts aadaki gibidir:
Here is a: 5, 6, 7
Here is b: 10, 10, 10
Here is c: 1, 2, 3

a > c is true
a < b is true
likisel operatrleri an ykleme ilemini etkileyen nemli bir kstlama sz konusudur:
Bu operatrleri ift ift ar yklemelisiniz. rnein, < operatrn ar yklyorsanz, >
operatrn de ar yklemelisiniz; ya da tam tersini yapmalsnz. Operatr iftleri aada
gsterilmitir:
== !=
< >
<= >=
Bir dier konu ise: == ve != operatrlerini ar yklyorsanz, genellikle
Object.Equal() ve Object.GetHashCode() metotlarn devre d brakmanz gerekir.
Bu metotlar ve bunlar devre d brakma (override) teknii Blm 1lde anlatlmaktadr.
true ve false Ar Yklemek
true ve false anahtar kelimeleri ar ykleme kapsamnda tekli operatr olarak da
kullanlabilirler. Bu operatrlerin ar yklenmi versiyonlar, oluturduunuz snflara bal
olarak true ve false deerlerinin alldk kullanmna imkan verirler. true ve false bir
snf iin uygulanr uygulanmaz sz konusu snfn nesnelerini if, while, for ve do-while
ifadelerini kontrol etmek amacyla ya da bir ? deyiminde kullanabilirsiniz. Hatta, bu nesneleri
zel mantk trlerini, sz gelii bulank mantk (fuzzy logic) uygulamak iin bile
kullanabilirsiniz.
true ve false operatrleri, ift olarak ar yklenmelidir. Sadece bir tekini ar
ykleyemezsiniz. Her ikisi de tekli operatrdr ve aadaki genel yapya sahiplerdir:
public static bool operator true(param-tipi operand)
{
// true veya false dndr
}

public static bool operator false(param-tipi operand)
{
// true veya false dndr
}
Dikkat ederseniz, her ikisi de bir bool sonu dndrmektedir.
BLM 9: OPERATRLERN AIRI YKLENMES

HERKES N C#
249
Aadaki rnek ThreeD snf iin true ve falseun nasl uygulanabileceini
gstermektedir. Koordinatlardan en az biri sfrdan farklysa ThreeD nesnesinin doru olduu
varsaylr. Koordinatlarn de sfrsa, nesne yanltr. Ayrca, kullanmn gstermek
amacyla eksiltme operatr de uygulanmtr.
// ThreeD iin true ve false'i asiri yukle.

using System;

// Uc boyutlu koordinat sinifi.
class ThreeD {
int x, y, z; // Uc boyutlu koordinatlar

public ThreeD() { x = y = z = 0; }
public TnreeD(int i, int j, int k) { x = i; y = j; z = k; }

// trueyu asiri yukle.
public static bool operator true(ThreeD op) {
if((op.x != 0) || (op.y != 0) || (op.z != 0))
return true; // en az bir koordinat sifirdan farkli
else
return false;
}

// false'u asiri yukle.
public static bool operator false(ThreeD op) {
if((op.x == 0) && (op.y == 0) && (op.z == 0))
return true; // tum koordinatlar sifir
else
return false;
}

// Tekli - operatorunu asiri yukle.
public static ThreeD operatr --(ThreeD op)
{
op.x--;
op.y--;
op.z--;

return op;
}

// X, Y, Z koordinatlarini goster.
public void show()
{
Console.WriteLine(x + , + y + , + z);
}
}

class TrueFalseDemo {
public static void Main() {
ThreeD a = new ThreeD(5, 6, 7);
ThreeD b = new ThreeD(10, 10, 10);
ThreeD c = new ThreeD(0, 0, 0);

HERKES N C#
KISIM I C# DL

250

Console.Write(Here is a: );
a.show();
Console.Write(Here is b: );
b.show();
Console.Write(Here is c: );
c.show();
Console.WriteLine();

if(a) Console.WriteLine(a is true.);
else Console.WriteLine(a is false.);

if(b) Console.WriteLine(b is true.);
else Console.WriteLine(b is false.);

if(c) Console.WriteLine(c is true.);
else Console.WriteLine(c is false.);

Console.WriteLine();

Console.WriteLine(Control a loop using a ThreeD object.);
do {
b.show();
b--;
} while(b);
}
}
kt aada gsterilmitir:
Here is a: 5, 6, 7
Here is b: 10, 10, 10
Here is c: 0, 0, 0

a is true.
b is true.
c is false.

Control a loop using a ThreeD object.
10, 10, 10
9, 9, 9
8, 8, 8
7, 7, 7
6, 6, 6
5, 5, 5
4, 4, 4
3, 3, 3
2, 2, 2
1, 1, 1
ThreeD nesnelerin if ifadelerini ve while dngsn kontrol etmek iin nasl
kullanldna dikkat edin. if ifadeleri sz konusu olduunda, ThreeD nesnesi true
kullanlarak deerlendirilir. Bu ilemin sonucu doru ise, if ifadesi baarl olur. do-while
dngsnde ise dngnn her iterasyonunda b bir kez azaltlr. Dng, b doru deerine sahip
BLM 9: OPERATRLERN AIRI YKLENMES

HERKES N C#
251
olduka (yani, en az bir adet sfrdan farkl koordinat ierdii srece) iterasyona devam eder. b
tamamen sfr koordinatlarn ierdii zaman, true operatr uygulandnda b yanl olarak
deerlendirilir ve dng sona erer.
Mantksal Operatrleri Ar Yklemek
Badiiniz gibi, C#ta u mantksal operatrler tanmldr: &, |, !, && ve ||. Bunlardan
yalnzca &, | ve ! ar yklenebilir Ancak, belirli kurallara uyarak her eye ramen ksa devre
&& ve || operatrlerinin avantajlar elde edilebilir. Bu durumlarn her biri bu blmde
incelenmektedir.
Mantksal Operatrlerin Ar Yklenmesine Basit Bir
Yaklam
Gelin, en basit durumla balayalm. Eer ksa devre mantksal operatrlerden
yararlanmayacaksnz, tahmin edebileceiniz gibi & ve | operatrlerini, her biri bir bool sonu
dndrecek ekilde ar ykleyebilirsiniz. Ar yklenmi ! operatr de bir bool sonu
dndrecektir.
te, ThreeD tipindeki nesneler iin !, & ve | mantksal operatrlerini ar ykleyen bir
rnek. nceki gibi, bu operatrlerin de, koordinatlarn en az biri sfrdan farkl olduunda
bir ThreeD nesnesinin true olduunu varsayarlar. Koordinatlarn de sfrsa, nesne false
deerine sahiptir.
/* ThreeD icin !, | ve & operatorlerini asiri yuklemek icin
basit bir yontem */

using System;

// Uc boyutlu koordinat sinifi.
class ThreeD {
int x, y, z; // Uc boyutlu koordinatlar

public ThreeD() { x = y = z = 0; }
public ThreeD(int i, int j, int k) { x = i; y = j; z = k; }

// | operatorunu asiri yukle.
public static bool operator |(ThreeD op1, ThreeD op2)
{
if( ((op1.x != O) || (op1.y != 0) || (op1.z != 0)) |
((op2.x != 0) || (op2.y != 0) || (op2.z != 0)) )
return true;
else
return false;
}

// & operatorunu asiri yukle.
public static bool operator &(ThreeD op1, ThreeD op2)

HERKES N C#
KISIM I C# DL

252
{
if( ((op1.x != 0) && (op1.y != 0) && (op1.z != 0)) &
(op2.x != 0) && (op2.y != 0) && (op2.z != 0)) )
return true;
else
return false;
}

// Overload |.
public static bool operator !(ThreeD op)
{
if((op.x != 0) || (op.y != 0) || (op.z != 0))
return false;
else return true;
}

// X, Y, Z koordinatlarini goster.
public void show()
{
Console.WriteLine(x + , + y + , + z);
}
}

class TrueFalseDemo {
public static void Main() {
ThreeD a = new ThreeD(5, 6, 7);
ThreeD b = new TrreeD(10, 10, 10);
ThreeD c = new TrreeD(0, 0, 0);

Console.Write(Here is a: );
a.show();
Console.Write(Here is b: );
b.show();
Console.Write(Here is c: );
c.show();
Console.WriteLine();

if(!a) Console.WriteLine(a is false.);
if(!b) Console.WriteLine(b is false.);
if(!c) Console.WriteLine(c is false.);

Console.WriteLine();

if(a & b) Console.WriteLine(a & b is true.);
else Console.WriteLine(a & b is false.);

if(a & c) Console.WriteLine(a & c is true.);
else Console.WriteLine(a & c is false.);

if(a | b) Console.WriteLine(a | b is true.);
else Console.WriteLine(a | b is false.);

if(a | c) Console.WriteLine(a | c is true.);
else Console.WriteLine(a | c is false.);
}
BLM 9: OPERATRLERN AIRI YKLENMES

HERKES N C#
253
}
Programn kts aada gsterilmitir:
Here is a: 5, 6, 7
Here is b: 10, 10, 10
Here is c: 0, 0, 0

c is false.

a & b is true.
a & c is false.
a | b is true.
a | c is true.
Bu yntemde, &, | ve ! operatr metotlarnn her biri bir bool sonu dndrmektedir.
Operatrler normal biimde (yani, bir bool sonu bekleyen yerlerde) kullanlacaksa bu
gereklidir. Hatrlarsanz, tm standart tipler iin mantksal bir ilemin sonucu bool tipinde bir
deerdir. Bu nedenle, bu operatrlerin ar yklenmi versiyonlarn bool tipinde dndrmek
mantkl bir yaklamdr. Ne yazk ki, bu yntem ancak ksa devre operatrlere ihtiyacnz
olmayacaksa ie yarar.
Ksa Devre Operatrleri Mmkn Klmak
&& ve || ksa devre operatrlerinin kullanmn mmkn klmak iin drt kurala
uymalsnz. ncelikle, sz konusu snf, & ve | operatrlerini ar yklemelidir. kinci olarak,
ar yklenmi & ve | metotlarnn dn tipi, operatrlerin ar yklenmekte olduu snfa ait
bir nesne olmaldr. ncs, parametrelerin her biri operatrn ar yklenmekte olduu
snfn bir nesnesine referans olmaldr. Drdncs ise, true ve false operatrleri de sz
konusu snf iin ar yklenmelidir. Bu koullar saklandnda, ksa devre operatrler
otomatik olarak kullanma hazr hale gelir,
Aadaki program, ksa devre && ve || operatrlerini mmkn klmak amacyla & ve |
operatrlerinin ThreeD snf iin dzgn olarak ne ekilde uygulanmas gerektiini
gstermektedir.
/* ThreeD icin !, | ve & operatorlerini asiri yuklemenin daha iyi
bir yolu. Bu versiyon && ve || operatorlerini otomatik olarak
mumkun kilar. */

using System;

// Uc boyutlu koordinat sinifi.
class ThreeD {
nt x, y, z; // Uc boyutlu koordinatlar

public ThreeD() { x = y = z = 0; }
public ThreeD(int i, int j, int k) { x = i; y = j; z = k; }

// Kisa devre kullanim icin | operatorunu asiri yukle.

HERKES N C#
KISIM I C# DL

254
public static ThreeD operator |(ThreeD op1, ThreeD op2)
{
if( ((op1.x != 0) || (op1.y != 0) || (op1.z != 0)) |
((op2.x != 0) || (op2.y != 0) || (op2.z != 0)) )
return new ThreeD(1, 1, 1);
else
return new ThreeD(0, 0, 0);
}

// Kisa devre kullanim icin & operatorunu asiri yukle.
public static ThreeD operator &(ThreeD op1, ThreeD op2)
{
if( ((op1.x != 0) && (op1.y != 0) && (op1.z != 0)) &
((op2.x != 0) && (op2.y != 0) && (op2.z != 0)) )
return new ThreeD(1, 1, 1);
else
return new ThreeD(0, 0, 0);
}

// ! operatorunu asiri yukle.
public static bool operator !(ThreeD op)
{
if(op) return false;
else return true;
}

// true operatorunu asiri yukle.
public static bool operator true(ThreeD op) {
if((op.x != 0) || (op.y != 0) || (op.z != 0))
return true; // en azindan bir koordinat sifirdan farkli
else
return false;
}

// false'u asiri yukle.
public static bool operator false(ThreeD op) {
if((op.x == 0) && (op.y == 0) && (op.z == 0))
return true; // tum koordinatlar sifira esit
else
return false;
}

// X, Y, Z koordinatlarini goster.
public void show()
{
Console.WriteLine(x + , + y + , + z);
}
}

class TrueFalseDemo {
public static void Main() {
ThreeD a = new ThreeD(5, 6, 7);
ThreeD b = new ThreeD(10, 10, 10);
ThreeD c = new ThreeD(0, 0, 0);

BLM 9: OPERATRLERN AIRI YKLENMES

HERKES N C#
255
Console.Write(Here is a: );
a.show();
Console.Write(Here is b: );
b.show();
Console.Write(Here is c: );
c.show();
Console.WriteLine();

if(a) Cansole.WriteLine(a is true.);
if(b) Console.WriteLine(b is true.);
if(c) Console.WriteLine(c is true.);

if(!a) Console.WriteLine(a is false.);
if(!b) Console.WriteLine(b is false.);
if(!c) Console.WriteLine(c is false.);

Console.WriteLine();

Console.WriteLine(Use & and |);
if(a & b) Console.WriteLine(a & b is true.);
else Console.WriteLine(a & b is false.);

if(a & c) Console.WriteLine(a & c is true.);
else Console.WriteLine(a & c is false.);

if(a | b) Console.WriteLine(a | b is true.);
else Console.WriteLine(a | b is false.);

if(a | c) Console.WriteLine(a | c is true.);
else Console.WriteLine(a | c is false.);

Console.WriteLine();

// simdi kisa devre operatorleri kullan
Console.WriteLine(Use short-circuit && and ||);
if(a && b) Console.WriteLine(a && b is true.);
else Console.WriteLine(a && b is false.);

if(a && c) Console.WriteLine(a && c is true.);
else Console.WriteLine(a && c is false.);

if(a || b) Console.WriteLine(a || b is true.);
else Console.WriteLine(a || b is false.);

if(a || c) Console.WriteLine(a || c is true.);
else Console.WriteLine(a || c is false.);
}
}
Programn kts aadaki gibidir:
Here is a: 5, 6, 7
Here is b: 10, 10, 10
Here is c: 0, 0, 0


HERKES N C#
KISIM I C# DL

256
a is true.
b is true.
c is false.

Use & and |
a & b is true.
a & c is false.
a | b is true.
a | c is true.

Use short-circuit && and ||
a && b is true.
a && c is false.
a || b is true.
a || c is true.
Gelin imdi & ve | operatrlerinin nasl uygulandna yakndan bakalm. lgili metotlar
aada gsterilmitir;
// Kisa devre kullanim icin | operatorunu asiri yukle.
public static ThreeD operator |(ThreeD op1, ThreeD op2)
{
if( ((op1.x != 0) || (op1.y != 0) || (op1.z != 0)) |
((op2.x != 0) || (op2.y != 0) || (op2.z != 0)) )
return new ThreeD(1, 1, 1);
else
return new ThreeD(0, 0, 0);
}

// Kisa devre kullanim icin & operatorunu asiri yukle.
public static ThreeD operator &(ThreeD op1, ThreeD op2)
{
if( ((op1.x != 0) && (op1.y != 0) && (op1.z != 0)) &
((op2.x != 0) && (op2.y != 0) && (op2.z != 0)) )
return new ThreeD(1, 1, 1);
else
return new ThreeD(0, 0, 0);
}
ncelikle her ikisinin de ThreeD tipinde bir nesne dndrdklerine dikkat edin. Bu nesne-
nin nasl retildiine de dikkat edin. Sz konusu ilemin sonucu true ise, true deerinde (en
azndan bir koordinat sfrdan farkl olan) bir ThreeD nesnesi oluturulur ve dndrlr.
Sonu false ise, bu durumda false deerinde bir nesne oluturulur ve dndrlr. Bylece,
u tr bir ifadede:
if(a & b) Console.WriteLine(a & b is true.);
else Console.WriteLine(a & b is false.);
a&b ileminin sonucu, bir ThreeD nesnesidir. Bu rnekte, bu nesne true deerine
sahiptir. true ve false operatrleri tanml olduu iin elde edilen nesne true operatrne
tabi tutulur ve bir bool sonu dndrlr. Bu rnekte sonu truedur ve if baarl olur.
BLM 9: OPERATRLERN AIRI YKLENMES

HERKES N C#
257
Gerekli kurallar takip edilmi olduu iin ksa devre operatrler artk ThreeD nesneleri ile
kullanlmaya hazrdr. Bu operatrler u ekilde alr: lk operand, operatr true (|| iin)
veya operatr false (&& iin) kullanlarak test edilir. lemin sonucu belirlenebilirse,
karlk gelen & veya | deyiminin deeri hesaplanmaz. Aksi halde, sonucu belirlemek iin
karlk gelen ar yklenmi & veya | kullanlr. Bylece, && veya || kullanmak, yalnzca
deyimin sonucu ilk operand ile belirlenemedii taktirde, karlk gelen & veya | metodunun
arlmasna neden olur. rnein, programdaki u ifadeyi ele aln:
if(a || c) Console.WriteLine(a || c is true.);
true operatr nce aya uygulanr. Bu durumda a doru deerine sahip olduu iin |
operatr metodunu kullanmaya gerek yoktur. Ancak, ayn ifade u ekilde yazlm olsayd:
if(c || a) Console.WriteLine(c || a is true.);
Bu durumda true operatr cye uygulanacakt - ki, c bu rnekte false deerine
sahiptir. Bylece, ann true olup olmadn saptamak iin (bu rnekte dorudur) | operatr
metodu arlacakt.
Geri, ksa devre operatrleri mmkn klmak iin kullanlan tekniin ilk bakta biraz
dolambal olduunu dnebilirsiniz. Ancak biraz daha dnrseniz bunun mantkl
olduunu grrsnz. true ve falseu bir snf iin ar ykleyerek, derleyicinin ksa devre
operatrlerini aka ar yklemek zorunda kalmadan bu operatrlerden yararlanmasna
imkan tanm olursunuz. Ayrca, koul deyimlerinde nesneleri kullanma becerisine de
kavuursunuz. Genel olarak, & ve | operatrlerinin ok kstl olarak uygulanmasna ihtiyacnz
yoksa, bunlar tam olarak uygulamanz ok daha iyi olur.
Dnm Operatrleri
Baz durumlarda, bir snfa ait bir nesneyi dier veri tiplerini ieren bir deyim iinde
kullanmak isteyeceksiniz. Bazen bir veya daha fazla operatr ar yklemek bunu
gerekletirmek iin yardmc olabilir. Ancak, dier durumlarda ihtiyacnz olan yalnzca, sz
konusu snf tipinden hedef tipe dnmdr. Bu gibi durumlar ele almak iin C#, dnm
operatr (conversion operator) denilen zel bir operatr metodu tipi tanmlamanza imkan
verir. Dnm operatr, snfnza ait bir nesneyi bir baka tipe dntrr. Aslnda;
dnm operatr, tip atamas operatrn ar ykler. Dnm operatrleri, bir snfa ait
nesnelerin dier veri tipleriyle serbeste bir araya getirilmesine imkan vererek snf tiplerinin
C# programlama ortamna tamamen entegre edilmesine yardmc olmaktadrlar. Dier veri
tiplerine dnm tanml olduu srece bu geerlidir.
ki eit dnm operatr mevcuttur: implicit (kapal) ve explicit (ak). Her
birinin genel yaps aada gsterilmitir:
public static operator implicit hedef-tip(kaynak-tip v) { return deer; }
public static operator explicit hedef-tip(kaynak-tip v) { return deer; }

HERKES N C#
KISIM I C# DL

258
Burada hedef-tip, dnm gerekletireceiniz hedef tip; kaynak-tip,
dntreceiniz tip; deer ise dnm sonrasnda snfn sahip olaca deerdir. Dnm
operatrleri hedef-tip tipinde veriler dndrr ve baka tip belirleyicilerine izin verilmez.
Eer dnm operatr implicit olarak belirtilmise, dnm otomatik olarak
gerekletirilir (sz gelii, bir nesne hedef tiple birlikte bir deyim iinde kullanldnda).
Dnm operatr explicit olarak belirtilmise, dnm bir tip atamas kullanldnda
arlr. Ayn hedef ve kaynak tipleri iin hem kapal hem de ak dnm operatrleri
tanmlayamazsnz.
Dnm operatrn gz nnde canlandrmak iin ThreeD snf iin bir dnm
operatr oluturacaz. Diyelim ki, ThreeD tipinde bir nesneyi bir tamsay deyim iinde
kullanabilmek iin bir tamsayya dntrmek istiyorsunuz. Ayrca; dnm, boyutun
arpm kullanlarak gerekletirilecek. Bunu baarmak iin aadaki gibi bir implicit
dnm operatr kullanacaksnz:
public static implicit operator int(ThreeD op1)
{
return op1.x * op1.y * op1.z;
}
te, bu dnm operatrn rnekleyen bir program:
// Kapali donusum operatoru kullanan bir ornek.

using System;

// Uc boyutlu koordinat sinifi.
class ThreeD {
int x, y, z; // uc boyutlu koordinatlar

public ThreeD() { x = y = z = 0; }
public ThreeD (int i, int j, int k) { x = i; y = j; z = k; }

// Ikili + operatorunu asiri yukle
public static ThreeD operator +(ThreeD op1, ThreeD op2)
{
ThreeD result = new ThreeD() ;

result.x = op1.x + op2.x;
result.y = op1.y + op2.y;
result.z = op1.z + op2.z;

return result;
}

// ThreeDden inte kapali donusum.
public static implicit operator int(ThreeD op1)
{
return op1.x * op1.y * op1.z;
}

BLM 9: OPERATRLERN AIRI YKLENMES

HERKES N C#
259
// X, Y, Z koordinatlarini goster.
public void show()
{
Console.WriteLine(x + , + y + , + z);
}
}

class ThreeDDemo {
public static void Main() {
ThreeD a = new ThreeD(1, 2, 3);
ThreeD b = new ThreeD(10, 10, 10);
ThreeD c = new ThreeD();
int i;

Console.Write(Here is a: );
a.show();
Console.WriteLine();
Console.write( Here is b: );
b.show();
Console.WriteLine();

c = a + b; // a ve byi topla
Console.Write(Result of a + b: );
c.show();
Console.WriteLine();

i = a; // inte donustur
Console.WriteLine(Result of i = a: + i);
Console.WriteLine();

i = a * 2 - b; // inte donustur
Console.WriteLine(result of a * 2 - b: + i);
}
}
Bu program aadaki kty ekranda gsterir:
Here is a: 1, 2, 3
Here is b: 10, 10, 10
Result of a + b: 11, 12, 13
Result of i = a: 6
result of a * 2 - b: -988
Programdan grld gibi, bir ThreeD nesne, i=a gibi bir tamsay deyim iinde
kullanldnda nesne zerine dnm uygulanr. Bu spesifik rnekte dnm 6 deerini
dndrr. Bu deer, ann iinde saklanan koordinatlarn arpmdr. Ancak, bir deyim inte
dnm gerektirmiyorsa, dnm operatr arlmaz. c=a+b iin operator int()in
arlmamasnn nedeni budur.

HERKES N C#
KISIM I C# DL

260
Hatrlarsanz, farkl ihtiyalar karlamak iin farkl dnm operatrleri
tanmlayabilirsiniz. doublea ya da longa dntren bir tane tanmlayabilirsiniz, rnein.
Bunlarn her biri otomatik ve bamsz olarak uygulanr.
implicit dnm operatr; bir deyim iinde bir dnm gerektiinde, bir metoda bir
nesne aktarlrken, bir atama ifadesi iinde ve de hedef tip iin ak bir tip atamas kullanrken
otomatik olarak uygulanr. Alternatif olarak, yalnzca ak bir tip atamas kullanldnda
arlmak zere bir explicit dnm operatr de tanmlayabilirsiniz. explicit dnm
operatr otomatik olarak arlmaz. rnein, nceki programn inte ak dnm
gerekletirmek zere yeniden zerinde allm versiyonu ite u ekildedir:
// Acik donusum kullanir.

using System;

// Uc boyutlu koordinat sinifi.
class ThreeD {
int x, y, z; // Uc boyutlu koordinatlar

public ThreeD() { x = y = z = 0; }
public ThreeD(int i, int j, int k) { x = i; y = j, z = k; }

// Ikili + operatorunu asiri yukle
public static ThreeD operator +(ThreeD op1, ThreeD op2)
{
ThreeD result = new ThreeD();

result.x = op1.x + op2.x;
result.y = op1.y + op2.y;
result.z = op1.z + op2.z;

return result;
}

// 8u artik acik.
public static explicit operator int(ThreeD op1)
{
return op1.x * op1.y * op1.z;
}

// X, Y, Z koordinatlarini goster.
public void show()
{
Console.WriteLine(x + , + y + , + z);
}
}

class ThreeDDemo {
public static void Main() {
ThreeD a = new ThreeD(1, 2, 3);
ThreeD b = new ThreeD(10, 10, 10);
ThreeD c = new ThreeD();
int i;
BLM 9: OPERATRLERN AIRI YKLENMES

HERKES N C#
261

Console.Write(Here is a: );
a.show();
Console.WriteLine();
Console.Write(Here is b: );
b.show();
Console.WriteLine();

c = a + b; // a ve byi topla
Console.Write(Result of a + b: );
c.show();
Console.WriteLine();

i = (int) a; // inte acik olarak donustur - tip atamasi gerekli
Console.WriteLine(Result of i = a: + i);
Console.WriteLine();

i = (int)a * 2 - (int)b; // tip atamalari gerekiyor
Console.WriteLine(result of a * 2 b: + i);
}
}
Dnm operatr artk explicit olarak belirtildii iin inte dnm bir tip atamas
yoluyla ak olarak yaplmaldr. rnein, aadaki satrda tip atamasn kaldrrsanz, program
derlenmeyecektir:
i = (int) a; // inte acik olarak donustur - tip atamasi gerekli
Dnm operatrleriyle ilgili birka kstlama sz konusudur:
Dnm ya hedef tipi ya da kaynak tipi sizin oluturduunuz bir snf olmaldr.
rnein, doubledan inte dnm yeniden tanmlayamazsnz.

Objectten veya Objecte dnm tammlayamazsnz.

Ayn kaynak ve hedef tipleri iin hem kapal hem de ak dnm tanmlayamazsnz

Temel snftan tretilmi snfa dnm tanmlayamazsnz.
(Temel ve tretilmi snflarla ilgili aklama iin Blm 11e bakn.)

Bir arayzden veya bir arayze dnm tanmlayamazsnz.
(Arayzlerle ilgili aklama iin Blm 12ye bakn.)
Bu kurallara ek olarak, implicit ve explicit dnm operatrleri arasnda karar
verirken normalde uymanz gereken neriler de mevcuttur. Kullanl olmalarna ramen kapal
dnmler yalnzca, dnmn doas gerei hatasz olduu durumlarda kullanlmaldr.
Bunu garanti etmek iin kapal dnmler yalnzca u iki koul salandnda
oluturulmaldr: Birincisi, kesme, tama ya da iaret kayb gibi bilgi kayplar meydana
gelmemelidir. kincisi: dnm, kural d bir duruma neden olmamaldr. Eer dnm bu
iki koulu salayamyorsa, bu durumda ak dnm kullanmalsnz.

HERKES N C#
KISIM I C# DL

262
Operatrleri Ar Yklemekle lgili pular ve
Kstlamalar
Ar yklenmi bir operatrn tanmlanm olduu snf erevesindeki ileyii,
operatrn C#n standart tipleri erevesindeki varsaylan kullanmyla bir ilgisi olmas
gerekmez. Yine de, kodunuzun yaps ve okunakll asndan ar yklenmi bir operatr,
mmknse operatrn orijinal kullanmn yanstmaldr. rnein, ThreeD ile balantl +
operatr, tamsay tipleriyle balantl + operatr ile kavramsal adan benzerdir. +
operatrn asl grevinden farkl olarak, rnein bir / operatr gibi alacak ekilde bir
snfa bal olarak tanmlamak ok bir yarar salamayacaktr. Buradaki ana fikir udur: Ar
yklenmi bir operatre istediiniz herhangi bir anlam verebiliyor olsanz bile, anlalrlk
asndan en iyisi, operatrn yeni anlamnn orijinal anlamyla ilgili olmasdr.
Operatrlerin ar yklenmesiyle ilgili baz kstlamalar da sz konusudur. Hibir operat-
rn ncelik srasn deitiremezsiniz. Operatr metodunuz bir operand gz ard etmeyi tercih
edebilse bile, operatrn gerektirdii operand saysn deitiremezsiniz. Ar ykleme
yapamayacanz birka operatr de vardr. Belki de en nemlisi, herhangi bir atama operat-
rn, += gibi bileik atamalar da dahil olmak zere ar ykleyemezsiniz. Ar ykleme
yapamayacanz dier operatrler unlardr:
&& || [] () new is
sizeof typeof ? - . =
Tip atamas () operatrn aka ar yklemeniz mmkn olmasa da, daha nce sz
ettiimiz gibi, bu ilevi gerekletiren dnm operatrleri oluturabilirsiniz.
+= gibi operatrlerin ar yklenememesi ciddi bir kstlama gibi grnebilir. Ancak, bu
aslnda ciddi bir kstlama deildir. Genel olarak, bir operatr tanmlam iseniz ve bu operatr
bir bileik ifadede kullanlyorsa, bu durumun sonucu olarak ar yklenmi operatr metodu-
nuz arlr. Dolaysyla += otomatik olarak operator+()nin size ait olan versiyonunu
kullanr. rnein, ThreeD snf zerinde konutuumuzu varsayarsak, u eklide bir sekans
kullanrsnz:
ThreeD a = new ThreeD(l, 2, 3);
ThreeD b = new ThreeD(10, 10, 10);

b += a; // a ve byi topla
ThreeDnin operator+() otomatik olarak arlr, bye 11, 12, 13 koordinat atanr.
Son bir nokta: Dizi indeksleme operatrn [] bir operatr metodu kullanarak ar
ykleyemeseniz bile, bir sonraki blmde tanmlanan indeksleyiciler (indexers)
oluturabilirsiniz.

BLM 9: OPERATRLERN AIRI YKLENMES

HERKES N C#
263
Operatrlerin Ar Yklenmesine Bir Baka rnek
Bu blm boyunca operatrlerin ar yklenmesini gstermek iin ThreeD snfn
kullanmaktayz. Bu balamda, ThreeD snf ok iimize yarad. Ancak, bu blm
noktalamadan nce bir baka rnek zerinden gemek de yararl olur. Hangi snf kullanlrsa
kullanlsn, operatrlerin ar yklenmesiyle ilgili genel prensipler ayn olmasna ramen,
aadaki rnek, zellikle tiplerin geniletilebilirlii sz konusu olduunda operatrleri ar
yklemenin gcn gstermeye yardmc olmaktadr.
Bu rnekte drt bitlik bir tamsay tipi gelitirilmekte ve bu tip iin birka ilem
tanmlanmaktadr. Belki de biliyorsunuzdur, biliimin ilk yllarnda drt bitlik nicelikler
yaygnd, nk drt bit, bir byten yarsn simgeliyordu. Ayrca, onaltlk bir rakam da
tutabilecek kadar bykt. Drt bit, yarm byte olduu iin drt bitlik niceliklerden kimi zaman
nybble olarak sz edilir. Programclarn, kodlarn her seferinde bir nybble olarak girdikleri
n panelli makinelerin kullanld gnlerde nybble cinsiden dnmek sradan, gnlk bir iti!
imdilerde yaygn olmasa da drt bitlik tip hala C#n dier tamsaylarna enteresan bir katk
salamaktadr. Geleneksel olarak nibble, iaretsiz bir deerdir.
Aadaki rnek bir nybble veri tipini gereklemek iin Nybble snfn kullanmaktadr.
Snfn depolama altyaps olarak int kullanlmaktadr; fakat bu, snfta tutulabilecek deerleri
0 ile 15 arasna snrlamaktadr. Programda aadaki operatrler tanmlanr:
Bir Nybble bir Nybblea eklemek

Bir inti bir Nybblea eklemek

Bir Nybble bir inte eklemek

Byktr ve kktr

Artrma operatr

Nybbledan inte dnm

intten Nybblea dnm
Bir snf tipinin C# tip sistemine nasl tam olarak entegre edilebileceini gstermesi asn-
dan bu ilemler yeterlidir. Yine de, komple bir Nybble uygulamas iin dier operatrlerin t-
mn tanmlamanz gerekecektir. Bunlar kendi kendinize eklemeyi denemek isteyebilirsiniz.
Komple Nybble snf, snfn kullanmn gsteren NybbieDemo ile birlikte aada
gsterilmektedir:
// Nybble adinda 4 bitlik tip olusturur.

using System;

// 4 bitlik tip
class Nybble {
int val; // depolama altyapisi

HERKES N C#
KISIM I C# DL

264

public Nybble() { val = 0; }

public Nybble(int i) {
val = i;
val = val & 0xF; //alt 4 biti kaybetme
}

// Nybble + Nybble icin ikili + operatorunu asiri yukle.
public static Nybble operator +(Nybble opi, Nybble op2)
{
Nybble result = new Nybble();

result.val = op1.val + op2.val;
result.val = result.val & 0xF; // alt 4 biti kaybetme

return result;
}

// Nybble + int icin ikili + operatorunu asiri yukle.
public static Nybble operator +(Nybble op1, int op2)
{
Nybble result = new Nybble();

result.val = op1.val + op2;
result.val = result.val & 0xF; // alt 4 biti kaybetme

return result;
}

// int + Nybble icin ikili + operatorunu asiri yukle.
public static Nybble operator + (int op1, Nybble op2)
{
Nybble result = new Nybble();

result.val = op1 + op2.val;
result.val = result.val & 0xF; // alt 4 biti kaybetme

return result;
}

// ++ operatorunu asiri yukle.
public static Nybble operatr ++(Nybble op)
{
op.val++;

op.val = op.val & 0xF; // alt 4 biti kaybetme

return op;
}

// > operatorunu asiri yukle.
public static bool operator >(Nybble op1, Nybble op2)
{
if(op1.val > op2.val) return true;
BLM 9: OPERATRLERN AIRI YKLENMES

HERKES N C#
265
else return false;
}

// < operatorunu asiri yukle.
public static bool operator <(Nybble op1, Nybble op2)
{
if(op1.val < op2.val) return true;
else return false;
}

// Bir Nybblei inte donustur
public static implicit operator int (Nybble op)
{
return op.val;
}

// Bir inti Nybblea donustur
public static implicit operator Nybble (int op)
{
return new Nybble(op);
}
}

class NybbleDemo {
public static void Main() {
Nybble a = new Nybble(1);
Nybble b = new Nybble(10);
Nybble c = new Nybble();
int t;

Console.WriteLine(a: + (int) a);
Console.WriteLine(b: + (int) b);

// bir if ifadesinde bir Nybble kullan
if(a < b) Console.WriteLine(a is less than b\n);

// iki Nybblei topla
c = a + b;
Console.WriteLine(c after c = a + b: + (int) c);

//Bir Nybblea bir int ekle
a += 5;
Console.writeLine(a after a += 5: + (int) a);

Console.WriteLine();

// Bir Nyyblei bir tamsayi deyim icinde kullan
t = a * 2 + 3;
Console.WriteLine(Result of a * 2 + 3: + t);

Console.WriteLine();

//int atamasini ve tasmayi goster
a = 19;
Console.WriteLine(Result of a = 19: + (int) a);

HERKES N C#
KISIM I C# DL

266

Console.WriteLine();

// donguyu kontrol etmek icin Nybble kullan
Console.WriteLine(Control a for loop with a Nybble.);
for(a = 0; a < 10; a++)
Console.Write((int) a + );

Console.WriteLine();
}
}

Programn kts aada gsterilmitir:
a: 1
b: 10
a is less than b

c after c = a + b: 11
a after a += 5: 6

Result of a * 2 + 3: 15

Result of a = 19: 3

Control a for loop with a Nybble.
0 1 2 3 4 5 6 7 8 9
Nybblen ileyiinin byk ksm kolaylkla anlalyor olsa gerek. Yine de, zerinde
durulmas gereken nemli bir nokta vardr: Bir Nybblen C# tip sistemine entegrasyonunda
dnm operatrleri byk rol oynar. Dnmler Nybbledan inte ya da intten
Nybblea eklinde tanmland iin bir Nybble nesnesi aritmetik deyimler iine rahatlkla
kartrlabilir. rnein, programdaki u deyimi ele aln:
t = a * 2 + 3;
Burada, tpk 2 ve 3 gibi t de bir inttir, ama a bir Nybbledr. Nybblen dahili olarak
inte dntrlmesinden dolay, deyimdeki bu iki tip birbiriyle uyumludur. Bu rnekte,
deyimin kalan int tipinde olduu iin a, inte kendi dnm metodu tarafndan
dntrlr.
intten Nybblea dnm bir Nybble nesnesine bir int deer atanmasna imkan tanr.
rnein, programdaki u ifade
a = 19:
u ekilde alr, intten Nybblea dntren operatr altrlr. Bu, 19 deerinin alt 4
bitini (bunun deeri 3tr nk 19, Nybblen menzilinden taar) ieren yeni bir Nybble
nesnesinin oluturulmasna neden olur. Bu nesne daha sonra aya atanr. Dnm operatrleri
olmasayd, bu tr deyimlere izin verilmeyecekti.
BLM 9: OPERATRLERN AIRI YKLENMES

HERKES N C#
267
Nybbledan inte dnm ayrca for dngsnde de kullanlmaktadr. Bu dnm
olmadan for dngsn bu denli ak bir ekilde yazmak mmkn olmayacakt.




O N U N C U B L M

NDEKSLEYCLER VE
ZELLKLER





















10
BLM 10: NDEKSLEYCLER VE ZELLKLER

HERKES N C#
269
Bu blmde birbiriyle yakn ilikisi olan iki zel tipte snf yesi incelenmektedir:
indeksleyiciler (indexers) ve zellikler (properties). Bunlarn her biri, C#n tip sistemine
entegrasyonunu artrarak ve esnekliini gelitirerek ait olduklar snfn gcn geniletirler.
ndeksleyiciler, bir nesnenin tpk bir dizi gibi indekslenebilecei bir mekanizma salar.
zellikler ise, bir snfa ait rnek verilere eriimi ynetmek iin standardize edilmi yollardan
biridir. Bu iki kavram birbiriyle ilgilidir, nk bunlarn her ikisi de C#n bir baka zelliine,
eriimciye (accessor) dayanmaktadr.
ndeksleyiciler
Bildiiniz gibi, dizi indeksleme ilemi [] operatr kullanlarak gerekletirilir. []
operatrn, kendi oluturduunuz snflar iin ar yklemeniz mmkndr; fakat bir operatr
metodu kullanamazsnz. Bunun yerine, bir indeksleyici tanmlarsnz. ndeksleyici, bir
nesnenin tpk bir dizi gibi indekslenmesine imkan verir. ndeksleyiciler temel olarak, bir veya
daha fazla kstlamaya tabi olan zel dizilerin oluturulmasn desteklemek iin kullanlr.
Ancak; indeksleyicileri, dizi benzeri bir sz diziminin avantajl olaca amalar iin
kullanabilirsiniz. ndeksleyiciler bir veya daha fazla boyuta sahip olabilir. Biz tek boyutlu
indeksleyiciler ile balayacaz.
Tek Boyutlu ndeksleyici Oluturmak
Tek boyutlu bir indeksleyici aadaki gibi bir genel yapya sahiptir:
eleman-tipi this [int indeks] {
// get eriimcisi
get {
//indeks ile belirtilen deeri dndr
}

// set eriimcisi.
set {
// indeks ile belirtilen deeri ayarla
}
}
Burada, eleman-tipi indeksleyicinin temel tipidir. Bylece, indeksleyici tarafndan
eriilen her eleman eleman-tipi tipinde olacaktr. Bu, dizinin temel tipine karlk gelir.
indeks parametresi, eriilmekte olan elemann indeksini alr. Bu parametrenin teknik olarak
int tipinde olmas gerekmez, fakat indeksleyiciler tipik olarak dizi indeksleme ilevi
saladklar iin, tamsay tipi allmtr.
ndeksleyicinin gvdesi iinde get ve set adnda iki eriimci (accessor) tanmlanr.
Eriimci, metot ile ayndr; tek fark, eriimcinin dn deerinin ve parametre deklarasyonunun
olmamasdr. ndeksleyici kullanldnda eriimciler otomatik olarak arlr ve her iki
eriimci de parametre olarak indeksi alr. Eer indeksleyici bir atama ifadesinin sol tarafnda
ise, set eriimcisi arlr; bu durumda indeks ile belirtilen eleman ayarlanmaldr. Aksi

HERKES N C#
KISIM I C# DL

270
halde, get eriimcisi arlr; bu kez indeks ile ilikilendirilmi deer dndrlmelidir. set
metodu ayrca, belirtilen indekse atanmakta olan deeri ieren ve value olarak adlandrlan
bir deer de alr.
ndeksleyicinin salad avantajlardan biri, uygun olmayan eriimleri nleyerek bir
dizinin nasl eriildiini tam olarak kontrol edebilmenizdir. te bir rnek. Aadaki programda
FailSoftArray snf, snr hatalarn yakalayan bir dizi gereklemektedir. Bu sayede, eer
bir dizi, snr dnda indekslenirse alma zamannda ortaya kan kural d durumlar
nlenmi olur. Bu ilem, diziyi bir snfn iine private ye olarak paketleyerek ve dizinin
yalnzca indeksleyici yoluyla eriimine imkan vererek gerekletirilir. Bu yntem sayesinde,
dizinin snrlar dnda kalan eriim denemeleri, bu tr bir giriimin zarife snmlendirilmesi
ile nlenebilir (bylece arpma yerine yumuak ini elde edilmi olur). FailSoftArray,
indeksleyici kulland iin normal dizi notasyonu kullanlarak eriilebilir.
// fail-soft bir dizi olusturmak icin indeksleyici kullanir.

using System;

class FailSoftArray {
int[] a; // temel teskil eden diziye referans

public int Length; // Length, public uyedir

public bool errflag; // son islemin sonucunu gosterir

// Buyuklugu verilen diziyi yapilandir.
public FailSoftArray(int size) {
a = new int[size];
Length = size;
}

// Bu, FailSoftArray icin bir indeksleyicidir.
public int this[int index] {
//Bu, get erisimcisidir.
get {
if(ok(index)) {
errflag = false;
return a[index];
} else {
errflag = true;
return 0;
}
}

// Bu, set erisimcisidir.
set {
if(ok(index)) {
a[index] = value;
errflag a false;
}
else errflag = true;
}
BLM 10: NDEKSLEYCLER VE ZELLKLER

HERKES N C#
271
}
// indeks sinirlar icindeyse true dondur.
private bool ok(int index) {
if(index >= 0 & index < Length) return true;
return false;
}
}

// fail-soft diziyi goster.
class FSDemo {
public static void Main() {
FailSoftArray fs = new FailSoftArray(5);
int x;

// sessiz cokusleri goster
Console.WriteLine(Fail quietly.);
for(int i = 0; i < (fs.Length * 2); i++)
fs[i] = i * 10;

for(int i = 0; i < (fs.Length * 2); i++) {
x = fs[i];
if(x != -1) Console.Write(x + );
}
Console.WriteLine();

// simdi, basarisiz durumlar uret
Console.WriteLine(\nFail with error reports.);
for(int i = 0; i < (fs.Length * 2); i++) {
fs[i] = i * 10;
if(fs.errflag)
Console.WriteLine(fs[ + i + ] out-of-bounds);
}

for(int i = 0; i < (fs.Length * 2); i++) {
x = fs[i];
if(!fs.errflag) Console.Write(x + );
else
Console.WriteLine(fs[ + i + ] out-of-bounds);
}
}
}
Programn kts aada gsterilmitir:
Fail quietly.
0 10 20 30 40 0 0 0 0 0

Fail with error reports.
fs[5] out-of-bounds
fs[6] out-of-bounds
fs[7] out-of-bounds
fs[8| out-of-bounds
fs[9] out-of-bounds
0 10 20 30 40 fs[5] out-of-boundS
fs[6] out-of-bounds

HERKES N C#
KISIM I C# DL

272
fs[7] out-of-bounds
fs[8] out-of-bounds
fs[9] out-of-bounds
ndeksleyici, dizi snrlarnn almasn nlemektedir. Gelin imdi, indeksleyicinin her
parasna daha yakndan bakalm. ndeksleyici u satrla balar:
public int tnis[int index] {
Bu ifade, int tipinde elemanlar zerinde ilem gren bir indeksleyici deklare etmektedir.
ndeks, index zerinden aktarlr. ndeksleyici publictir. Bu sayede, kendi snf dnda
kalan kod tarafndan kullanlmasna imkan verilir.
get() eriimcisi aada gsterilmitir:
get {
if(ok(index)) {
errflag = false;
return a[index];
}
else {
errflag = true;
return 0;
}
}
get eriimcisi dizi snr hatalarn nler. Eer belirtilen indeks snrlar iindeyse, indekse
karlk gelen eleman dndrlr. Eer indeks snr dna tayorsa, hi bir ilem gerekletiril-
mez ve tama meydana gelmez. FailSoftArrayin bu versiyonunda errflag adnda bir
deiken, tm ilemlerin sonucunu ierir. Bu atan, her ilemden sonra sz konusu ilemin
baarl veya baarsz olduunu deerlendirmek iin incelenebilir.
set eriimcisi aada gsterilmitir. Bu da snr hatalarn nler.
set {
if(ok(index)) {
a[index] = value;
errflag = false;
}
else
errflag = true;
}
Burada, eer index snrlar iindeyse, value iinde aktarlan deer, karlk gelen
elemana atanr. Aksi halde, errflaga true deeri verilir. Hatrlarsanz, bir eriim
metodunda value atanmakta olan deeri ieren otomatik bir parametredir. Bunu deklare
etmenize gerek yoktur (zaten edemezsiniz).
ndeksleyiciler hem geti hem de seti desteklemek zorunda deildir. Yalnzca get
eriimcisini uygulayarak salt okunur bir indeksleyici oluturabilirsiniz. Yalnzca seti
uygulayarak da sal yazlr bir indeksleyici oluturabilirsiniz.
BLM 10: NDEKSLEYCLER VE ZELLKLER

HERKES N C#
273
ndeksleyiciler Ar Yklenebilir
Bir indeksleyici ar yklenebilir. Parametresi ve indeks olarak kullanlan argman
arasnda en yakn tip elemesine sahip olan versiyon, altrlan versiyon olacaktr. te,
FailSoftArray indeksleyicisini double tipinde indeksler iin ar ykleyen bir rnek.
double indeksleyici, indeksini en yakn tamsay deere yuvarlamaktadr.
// FailSoftArray indeksleyicisini asiri yuklemek.

using System;

class FailSoftArray {
int[] a; // temel teskil eden diziye referans

public int Length; // Length, public uyedir

public bool errflag; // son islemin sonucunu gosterir

// Buyuklugu verilen diziyi yapilandir.
public FailSoftArray(int size) {
a = new int[size];
Length = size;
}

// Bu, FailSoftArray icin bir int indeksleyicisidir.
public int this[int index] {
// Bu, get erisimcisidir.
get {
if (ok(index)) {
errflag = false;
return a[index];
} else {
errflag = true;
return 0;
}
}

// Bu, set erisimcisidir
set {
if(ok(index)) {
a[index] = value;
errflag = false;
}
else errflag = true;
}
}

/* Bu, FailSoftArray icin bir baska indeksleyicidir.
Bu indeks, double arguman alir. Sonra bu argumani en
yakin tamsay indekse yuvarlar. */
public int this[double idx] {
// Bu, get erisimcisidir.
get {

HERKES N C#
KISIM I C# DL

274
int index;

// en yakin tamsayya yuvarla
if((idx - (int) idx) < 0.5) index = (int) idx;
else index = (int) idx + 1;

if(ok(index)) {
errflag = false;
return a[index];
} else {
errflag = true;
return 0;
}
}

// Bu, set erisimcisidir.
set {
int index;

// en yakin tamsayiya yuvarla
if((idx - (int) idx) < 0.5) index = (int) idx;
else index = (int) idx + 1;

if (ok(index)) {
a[index] = value;
errflag = false;
}
else errflag = true;
}
}

// indeks sinirlarin icindeyse true dondur.
private bool ok(int index) {
if(index >= 0 & index < Length) return true;
return false;
}
}

// fail-soft diziyi goster.
class FSDemo {
puplic static void Main() {
FailSoftArray fs = new FailSoftArray(5);

// fs icine bazi degerler yerlestir
for(int i = 0; i < fs.Length; i++)
fs[i] = i;

// simdi int ve double'larla indeksle
Console.WriteLine(fs[1]: + fs[1]);
Console..WriteLine(fs[2]: + fs[2]);

Console.WriteLine(fs[1.1]: + fs[1.1]);
Console.WriteLine(fs[1.6]: + fs[1.6]);
}
}
BLM 10: NDEKSLEYCLER VE ZELLKLER

HERKES N C#
275
Bu program aadaki kty retir:
fs[1]: 1
fs[2]: 2
fs[1.1]: 1
fs[1.6]: 2
ktdan grld gibi, double indeksler en yakn tamsay deere yuvarlanr. Spesifik
olarak, 1.1, 1e; 1.6, 2ye yuvarlanr.
Bir indeksleyiciyi bu programda gsterildii ekilde ar yklemek geerli olsa da, bu yay-
gn bir kullanm deildir. Genellikle bir indeksleyici, bir snfa ait bir nesnenin indeks olarak
kullanlmasn mmkn klmak iin, indeksin zel baz yollardan hesaplanmas ile ar
yklenebilir.
ndeksleyeciler, Temel Niteliinde Bir Dizi Gerektirmez
Bir indeksleyicinin aslnda bir dizi zerinde ilem grmesi iin hi bir gereklilik
olmadn kavramak nemlidir. ndeksleyici, yalnzca indeksleyici kullancsna dizi gibi bir
ilevsellik salamaldr. rnein, aadaki program 0dan l5e kadar 2nin kuvvetlerini ieren
ve salt okunur bir dizi gibi davranan bir indeksleyiciye sahiptir. Ancak, gerekte bir dizinin
mevcut olmadna dikkat edin. Bunun yerine indeksleyici, sadece verilen indeksin gerek
deerini hesaplamaktadr.
// Indeksleyiciler gercek dizi uzerinde islem gormek zorunda degildir.

using System;

class PwrOfTwo {

/* 0dan 15e kadar 2nin kuvvetlerini iceren bir mantksal
diziye erisir. */
public int this[int index] {
// 2nin kuvvetini hesapla ve dondur.
get {
if((index >= 0) && (index < 16)) return pwr(index);
else return -1;
}

// set erisimcisi mevcut degil
}

int pwr(int p) {
int result = 1;

for(int i = 0; i < p; i++)
result *= 2;

return result;
}
}

HERKES N C#
KISIM I C# DL

276

class UsePwrOfTwo {
public static void Main() {
PwrOfTwo pwr = new PwrOfTwo();

Console.Write(First 8 powers of 2: );
for(int i = 0; i < 8; i++)
Console.Write(pwr[i] + );
Console.WriteLine();

Console.Write(Here are some errors: );
Console.Write(pwr[-1] + + pwr[17]);

Console.WriteLine();
}
}
Programn kts aadaki gibidir:
First 8 powers of 2: 1 2 4 8 16 32 64 128
Here are some errors: -1 -1
PwrOfTwo iin indeksleyicinin get eriimcisi olduuna, ama set eriimcisi olmadna
dikkat edin. nceden akland gibi bu, indeksleyicinin salt okunur olduu anlamna
gelmektedir. Bylece, bir PwrOfTwo nesnesi bir atama ifadesinin sa tarafnda kullanlabilir,
fakat sol tarafnda kullanlamaz. rnein, yukardaki programa u ifadeyi eklemeye almak
ie yaramayacaktr:
pwr[0] = 11; // derlenmeyecektir
Bu ifade, derleme hatasna neden olacaktr, gnk indeksleyici iin tanml bir set()
eriimcisi mevcut deildir.
ndeksleyicileri kullanmakla ilgili iki nemli kstlama mevcuttur. Birincisi, bir
indeksleyici bir depolama yeri tanmlamad iin indeksleyicinin rettii bir deer, bir metoda
ref veya out parametresi olarak aktarlamaz. kinci olarak, bir indeksleyici kendi snfnn bir
rnek yesi olmaldr; static olarak deklare edilemez.
ok Boyutlu ndeksleyiciler
ok boyutlu diziler iin de indeksleyiciler tanmlayabilirsiniz. rnein, aada iki boyutlu
bir fail-soft dizisi gryorsunuz. ndeksleyicinin deklare edilme ekline zellikle dikkat edin.
// Iki boyutlu fail-soft dizi.

using System;

class FailSoftArray20 {
int[,] a; // temel teskil eden 2 boyutlu diziye referans
int rows, cols; // boyutlar
public int Length; // Length public uyedir

BLM 10: NDEKSLEYCLER VE ZELLKLER

HERKES N C#
277
public bool errflag; // son islemin sonucunu gosterir

// Boyutlari verilen bir dizi yapilandir.
public FailSoftArray2D(int r, int c) {
rows = r;
cols = c;
a = new int[rows, cols];
Length = rows * cols;
}

// Bu, FailSoftArray2D icin bir indeksleyicidir.
public int this[int index1, int index2] {
// Bu, get erisimcisidir.
get {
if(ok(index1, index2)) {
errflag = false;
return a[index1, index2];
} else {
errflag = true;
return 0;
}
}

// Bu, set erisimcisidir.
set {
if(ok(index1, index2)) {
a[index1, index2] = value;
errflag = false;
}
else errflag = true;
}
}

// indeksler sinirlarin icindeyse true dondur.
private bool ok(int index1, int index2) {
if(index1 >= 0 & index1 < rows & index2 >= 0 &
index2 < cols) return true;

return false;
}
}

// 2 boyutlu indeksleyiciyi goster.
class TwoDIndexerDemo {
public static void Main() {
FailSoftArray2D fs = new FailSoftArray2D(3, 5);
int x;

// sessiz cokusleri goster
Console.WriteLine(Fail quietly.);
for(int i = 0; i < 6; i++)
fs[i, i] = i*10;

for(int i = 0; i < 6; i++) {
x = fs[i, i];

HERKES N C#
KISIM I C# DL

278
if(x != -1) Console.Write(x + );
}
Console.WriteLine();

// simdi, basarisiz durumlari uret
Console.WriteLine(\nFail with error reports.);
for(int i = 0; i < 6; i++) {
fs[i, i] = i * 10;
if(fs.errflag)
Console.WriteLine(fs[ +i+, +i+] out-of-bounds);
}

for(int i = 0; i < 6; i++) {
x = fs[i, i];
if(!fs.errflag) Console.Write(x + );
else
Console.WriteLine(fs[ + i + , + i + ] out-of-
bounds);
}
}
}
Bu programn kts aada gsterilmitir:
Fail quietly.
0 10 20 0 0 0

Fail with error reports.
fs[3, 3] out-of-bounds
fs[4, 4] out-of-bounds
fs[5, 5] out-of-bounds
0 10 20 fs[3, 3] out-of-bounds
fs[4, 4] out-of-bounds
fs[5, 5] out-of-bounds
zellikler
Bir baka snf yesi tipi ise zelliktir (property). zellik, bir alan bu alana erien metot ile
birletirir. Elinizdeki kitaptaki nceki baz rneklerde gsterilmi olduu gibi, sk sk bir nesne-
nin kullanclar iin kullanma hazr bir alan oluturmak istersiniz; ama ayn zamanda, bu alan
iin izin verilen ilemler zerindeki kontrol de devaml klmak istersiniz. rnein, sz konusu
alana atanabilecek deerlerin araln snrlandrmak isteyebilirsiniz. Bu amac, bir private
deiken ve bu deikenin deerine erimek iin gerekli metotlar araclyla
gerekletirmemiz mmkn olsa da, zelliklerden yararlanmak ok daha iyi ve ok daha
verimli bir yaklamdr.
zellikler indeksleyicilere benzer. Bir zellik, bir isim ve bununla birlikle get ve set
eriimcilerini ierir. Eriimciler, bir deikenin deerini almak ve ayarlamak iin kullanlr. Bir
zelliin en temel faydas, zelliin isminin deyimlerde ve atamalarda normal bir deiken gibi
kullanlabilmesidir; aslnda get ve set eriimcileri otomatik olarak arlr. Bu, bir
indeksleyicinin get ve set metotlarnn otomatik olarak kullanlmas ile ayndr.
BLM 10: NDEKSLEYCLER VE ZELLKLER

HERKES N C#
279
Bir zelliin genel yaps u ekildedir:
tip isim {
get {
// get eriimci kodu
}

set {
// set eriimci kodu
}
}
Burada tip, zelliin tipini belirler; rnein, tip, int olabi1ir. isim ise zelliin
ismidir. zellik bir kez tanmlandktan sonra zellik isminin her kullanm, ilgili eriimcinin
arlmasyla sonulanr. set eriimcisi, otomatik olarak, zellie atanmakta olan deeri ieren
value adnda bir parametre alr.
zelliklerin depolama konumlar tanmlamadn kavramak nemlidir. Bylece, zellik
bir alana eriimi ynetir. Ancak, zelliin kendisi bu alan salamaz. Alan, zellikten bamsz
olarak belirtilmelidir.
te, prop adnda bir alana erimek iin myprop adnda bir zellik tanmlayan basit bir
rnek. Bu rnekte zellik, yalnzca pozitif deerlerin atanmasn mmkn klyor.
// Basit bir ozellik ornegi,

using System;

class SimpProp {
int prop; // myprop ile kontrol edilmekte olan alan

public SimpProp() { prop = 0; }

/*Bu, private ornek degiskeni propa erisimi destekleyen bir
ozelliktir. Bu ozellik yalnizca pozitif degerlere izin
verir.
public int myprop {
get {
return prop;
}
set {
if(value >= 0) prop = value;
}
}
}

// Bir ozellik goster.
class PropertyDemo {
public static void Main() {
SimpProp ob = new SimpProp();

Console.WriteLine(Original value of ob.myprop: + ob.myprop);


HERKES N C#
KISIM I C# DL

280
ob.myprop = 100; // deger ata
Console.WriteLine(Value of ob.myprop: + ob.myprop);

// propa negatif degerler atayamazsiniz
Console.WriteLine(Attempting to assign -10 to ob.myprop);
ob.myprop = -10;
Console.WriteLine(Value of ob.myprop: + ob.myprop);
}
}
Bu programn kts aada gsterilmitir:
Original value of ob.myprop: 0
Value of ob.myprop: 100
Attempting to assign -10 to ob.myprop
Value of ob.myprop: 100
Gelin bu program imdi dikkatlice inceleyelim. Programda prop adnda bir private alan
ve myprop adnda propa eriimi kontrol eden bir zellik tanmlanr. nceden akland
zere, zelliin kendisi bir depolama yeri tanmlamaz. zellik basite, bir alana eriimi kontrol
eder. Bylece, temel niteliinde bir alan olmadan zellik kavram diye bir ey olmaz. stelik,
prop, private olduu iin yalnzca myprop araclyla eriilebilir.
myprop zellii public olarak belirtildii iin, kendi snfnn dnda kalan kod
tarafndan da eriilebilir. Bu akla yatkndr, nk myprop, zel olan propa eriim
salamaktadr. get eriimcisi yalnzca propun deerini dndrr, set eriimcisi ise, propun
deerini sadece ve sadece deer pozitif olduunda ayarlar. Bylece, myprop zellii propun
hangi deerlere sahip olabileceini kontrol eder. te zellikler bu nedenle nemlidir.
myprop ile tanmlanan zelliin tipine okunur-yazlr zellik denir, nk bu tr bir
zellik, temel oluturan alann okunmasna ve yazlmasna imkan verir. Ancak, salt okunur ve
salt yazlr zellikler oluturmak da mmkndr. Salt okunur bir zellik oluturmak iin
yalnzca get eriimcisini tanmlayn. Salt yazlr bir zellik tanmlamak iin ise yalnzca set
eriimcisi tanmlayn.
fail-soft dizisinin snfn daha da gelitirmek iin zellik kullanabilirsiniz.
Bildiiniz gibi, tm diziler kendileriyle ilikilendirilmi bir Length zelliine sahiptir.
imdiye kadar FailSoftArray snfnda bu ama iin yalnzca Length adnda bir public
tamsay alan kullanld. Geri, bu iyi bir uygulama deildi, nk bu, Lengthe fail-soft
dizisinin uzunluundan baka baz deerler atanmasna da imkn vermektedir. (rnein, kt
niyetli bir programc bu deeri kasten bozabilir.) FailSoftArrayin aadaki versiyonunda
gsterildii gibi, Lengthi salt okunur bir zellie dntrerek bu durumu dzeltebiliriz:
// FailSoftArraya Length ozelligini ekler.

using System;

class FailSoftArray {
int[] a; // temel niteliginde diziye referans
BLM 10: NDEKSLEYCLER VE ZELLKLER

HERKES N C#
281
int len; // dizinin uzunlugu - Length ozelligine dayanir

public bool errflag; // son islemin sonucunu gosterir

// Buyuklugu verilen diziyi yapilandir.
public FailSoftArray(int size) {
a = new int[size];
len = size;
}

// Salt okunur Length ozelligi.
public int Length {
get {
return len;
}
}

// Bu, FailSoftArray icin bir indeksleyicidir.
public int this [int index] {
// Bu, get erisimcisidir.
get {
if(ok(index)) {
errflag = false;
return a[index];
} else {
errflag = true;
return 0;
}
}

// Bu, set erisimcisidir.
set {
if(ok(index)) {
a[index] = value;
errflag = false;
}
else errflag = true;
}
}

// indeks sinirlarin icindeyse true dondur.
private bool ok(int index) {
if(index >= 0 & index < Length) return true;
return false;
}
}

// Gelistirilmis fail-soft dizisini goster.
class ImprovedFSDemo {
public static void Main() {
FailSoftArray fs = new FailSoftArray(5);
int x;

// Length okunabilir
for(int i = 0; i < fs.Length; i++)

HERKES N C#
KISIM I C# DL

282
fs[i] = i * 10;

for(int i = 0; i < fs.Length; i++) {
x = fs[i];
if (x != -1) Console.Write(x + );
}
Console.WriteLine();

// fs.Length = 10; // Hata, gecersiz!
}
}
Artk Length veri saklamak iin private deiken leni kullanan bir zelliktir.
Length, sadece bir get eriicisini tanmlamaktadr. Bu da Lengthin salt okunur olduu
anlamna gelmektedir. Dolaysyla, Lengthi okumak mmkndr, ancak onun deerini
deitirmek mmkn deildir. Bunu kendi kendinize kantlamak isterseniz, kaynak kodunda
aadaki satrn bandaki aklama iaretini kaldrn:
// fs.Length = 10; // Hata, gecersiz!
Aklama iaretini kaldrdktan soma program derlemeye altnzda, Lengthin salt
okunur olduuna dair bir hata mesaj alacaksnz.
Length zelliinin eklenmesi FailSoftArrayi gelitirse de, zelliklerin
salayabilecei tek gelime bundan ibaret deildir. Kendisine eriimin salt okunur olarak
snrlanmas gereken errflag yesi de bir zellie dntrmek iin ok uygun bir adaydr.
FailSoftArray zerinde yapacamz son gelitirmeler aada gsterilmitir. Burada Error
adn verdiimiz ve veri tutmak iin orijinal errflag deikenini kullanan bir zellik
oluturmaktayz:
// errflagi bir ozellige donusturur.

using System;

class FailSoftArray {
int[] a; // temel teskil eden diziye referans
int len; // dizinin uzunlugu

bool errflag; // artik private olarak kullaniyoruz

// Buyuklugu verilen diziyi yapilandir.
public FailSoftArray(int size) {
a = new int[size];
len = size;
}

// Salt okunur Length ozelligi.
public int Length {
get {
return len;
}
}
BLM 10: NDEKSLEYCLER VE ZELLKLER

HERKES N C#
283

// Salt okunur Error ozelligi.
public bool Error {
get {
return errflag;
}
}

// Bu, FailSoftArray icin bir indeksleyicidir.
public int this[int index] {
// Bu, get erisimcisidir.
get {
if(ok(index)) {
errflag = false;
return a[index];
} else {
errflag = true;
return 0;
}
}

// Bu, set erisimcisidir.
set {
if(ok(index)) {
a[index] = value;
errflag = false;
}
else errflag = true;
}
}

// indeks sinirlarin icindeyse true dondur.
private bool ok(int index) {
if(index >= 0 & index < Length) return true;
return false;
}
}

// Gelistirilmis fail-soft diziyi goster.
class FinalFSDemo {
public static void Main() {
FailSoftArray fs = new FailSoftArray(5);

// Error ozelligini kullan
for(int i = 0; i < fs.Length + 1; i++) {
fs[i] = i * 10;
if(fs.Error)
Console.WriteLine(Error with index + i);
}
}
}
Error zelliinin oluturulmasyla birlikte, FailSoftArrayde iki deiiklik yaplmas
gerekmitir: Birincisi; artk Error zelliinin altndaki veri deposu olarak kullanlan

HERKES N C#
KISIM I C# DL

284
errflag, private hale getirilmitir. Bu nedenle errflaga artk dorudan eriim mmkn
deildir. kinci olarak; salt okunur bir Error zellii eklenmitir. Artk hatalar yakalamak
isteyen programlarn bu Error zelliini sorgulamalar gerekecektir. Main()de bu durumun
bir uygulamasna yer verilmi, kastl olarak snr hatas yaplm ve bu hatay yakalamak iin
Error zellii kullanlmtr.
zelliklerle lgili Kstlamalar
zelliklerle ilgili baz nemli kstlamalar sz konusudur. Birincisi, bir zellik bir veri
depolama yeri tanmlamad iin onun bir metoda ref ya da out parametresi olarak
aktarlmas mmkn deildir. kincisi, bir zellii ar ykleyemezsiniz. (Ayn deikene
erien iki farkl zelliiniz olabilir ama bu pek alldk bir durum deildir.) Son olarak,
derleyici tarafndan byle bir kural zorla uygulanmasa da, bir zellik get eriimcisi
arldnda ilgili olduu deikenin durumunu deitirmemelidir. Bir baka ifade ile get
ileminin bozucu olmamas gereklidir.
ndeksleyiciler ve zelliklerin Kullanm
nceki rnekler, indeksleyiciler ve zelliklerle ilgili temel mekanizmay bize gsterdiler,
ama bunlarn tam gcn henz ortaya koymadlar. Blm tamamlamak zere yapacamz
rnekte, RangeArray adl bir snf gelitireceiz. Bu snf, indeks aral programc tarafndan
gelitirilen bir dizi tanmlamak iin indeksleyiciler ve zellikler kullanmaktadr.
Bildiiniz gibi, C#ta dizi indeksleri daima sfrdan balar. Ancak, baz uygulamalarda dizi
indekslerinin herhangi bit noktadan balayabilmesi yararl olmaktadr, rnein, baz durum-
larda indeksi 1den balatmak kolaylk salayabilir. Baka durumlarda da, rnein -5ten
5e giden bir indeks aral kullanmak iin negatif indekslere izin vermek yarar salayabilir.
Burada gelitirilen RangeArray snf, bu ve dier indeksleme trlerinin tanmlanmasna ve
kullanmna olanak salamaktadr.
RangerArrayi kullanarak yle bir kod yazabilirsiniz:
RangeArray ra = new RangeArray(-5, 10);
// indeksleri -5ten 10a giden bir dizi

for(int i = -5; i <= 10; ra[i] = i;
// indeks -5ten 10a gitmektedir
Tahmin edebileceiniz gibi, ilk satrda indeksleri -5ten 10a (u noktalar dahil) giden
RangeArray adl dizi yaplandrlmaktadr. lk argman, balang indeksini belirlemektedir.
kinci argman da biti indeksini vermektedir. ra bir kez bu ekilde kurulduktan sonra, ona -
5 ila 10 arasnda deien indekslerle referansta bulunmak olanakl olmaktadr.
Aada bu dizinin kullanmn gsteren RangeArrayDemo snf ile birlikte RangeArray
snfnn tamamna yer verilmektedir. RangeArray, burada uyguland biimde int
BLM 10: NDEKSLEYCLER VE ZELLKLER

HERKES N C#
285
deerlerinden oluan dizileri desteklemektedir ama siz kodu deitirerek, dier herhangi bir
veri tipine de uyarlayabilirsiniz.
/* Indeks araligi varsayilandan farkli bir dizi sinifi
olusturur. RangeArray sinifi, indekslemenin sifirdan
farkli bir degerden baslamasina olanak saglar. Bir
RangeArray olusturdugunuzda, baslangic ve bitis
indekslerini de belirlersiniz. Indeks olarak negatif
sayilar da kullanilabilir. Ornegin, indeksleri -
5ten 5e, 1den 10a ya da 50den 56ya giden
diziler olusturabilirsiniz.
*/

using System;

class RangeArray {
// private veriler
int[] a; // temel teskil eden diziye referans
int lowerBound; // en kucuk indeks
int upperBound; // en buyuk indeks

// ozelliklerin verileri
int len; // Length ozelligine temel teskil eden degisken
bool errflag; // outcomea temel teskil eden degisken

// Diziyi verilen sinirlarla yapilandir.
public RangeArray(int low, int high) {
highn++;
if (high <= low) {
Console.WriteLine(Invalid Indices);
high = 1; // guvenlik icin minimal bir dizi olustur
low = 0;
}
a = new int[high - low];
len = high - low;

lowerBound = low;
upperBound = --high;
}

// Salt okunur Length ozelligi.
public int Length {
get {
return len;
}
}

// Salt okunur Error ozelligi.
public bool Error {
get {
return errflag;
}
}

// RangeArray'in indeksleyicisi.

HERKES N C#
KISIM I C# DL

286
public int this[int index] {
// Bu, get erisimcisidir.
get {
if(ok(index)) {
errflag = false;
return a[index - lowerBound];
} else {
errflag = true;
return 0;
}
}

// Bu, set erisimcisidir.
set {
if(ok(index)) {
a[index lowerBound] = value;
errflag = false;
}
else errflag = true;
}
}

// indeks sinirlar icindeyse true dondur.
private bool ok(int index) {
if(index >= lowerBound & index <= upperBound) return true;
return false;
}
}

// Indeks-aralik dizisini goster.
class RangeArrayDemo {
public static void Main() {
RangeArray ra - new RangeArray(-5, 5);
RangeArray ra2 = new RangeArray(1, 10);
RangeArray ra3 = new RangeArray(-20, -12);

// rayi goster
Console.writeLine(Length of ra: + ra.Length);

for(int i = -5; i <= 5; i++)
ra[i] = i;

Console.Write(Contents of ra: );
for(int i = -5; 1 <= 5; i++)
Console.Write(ra[i] + );

Console.WriteLine(\n);

// ra2yi goster
Console.WriteLine(Length of ra2: + ra2.Length);

for(int i = 1; i <= 10; i++)
ra2[i] = i;

Console.Write(Contents of ra2: );
BLM 10: NDEKSLEYCLER VE ZELLKLER

HERKES N C#
287
for(int i = 1; i <= 10; i++)
Console.Write(ra2[i] + );

Console.WriteLine(\n);

// ra3u goster
Console.WriteLine(Length of ra3: + ra3.Length);

for(int i = -20; i <= -12; i++)
ra3[i] = i;

Console.Write(Contents of ra3: );
for(int i = -20; i <= -12; i++)
Console.Write(ra3[i] + );

Console.WriteLine(\n);
}
}
Programn kts yledir:
Length of ra: 11
Contents of ra: -5 -4 -3 -2 0 1 2 3 4 5

Length of ra2: 10
Contents of ra2: 1 2 3 4 5 6 7 8 9 10

Length of ra3: 9
Contents of ra3: -20 -19 -18 -17 -16 -15 -14 -13 -12
Program ktsnn da dorulad gibi, RangeArray tipinden nesneler, sfrdan
balamayan indekslere de sahip olabilmektedirler. imdi gelin, RangeArrayin nasl
uygulandna biraz daha yakndan bakalm:
RangeArray, aadaki private rnek deikenlerini tanmlayarak balar:
// private veriler
int[] a; // temel teskil eden diziye referans
int lowerBound; // en kucuk indeks
int upperBound; // en buyuk indeks

// ozelliklerin verileri
int len; // Length ozelligine temel teskil eden degisken
bool errflag; // outcomea temel teskil eden degisken
Temel oluturan diziye a ile referans verilir. Bu dizi iin gerekli bellek alan RangeArray
yaplandrcs tarafndan ayrlr. Dizi indekslerinin alt limiti lowerBound deikeninde, st
limiti de upperBound deikeninde tutulur. Ardndan, Length ve Error zelliklerini
destekleyen rnek deikenler deklare edilir.
RangeArray yaplandrcs aada gsterilmitir:
// Diziyi verilen sinirlarla yapilandir.

HERKES N C#
KISIM I C# DL

288
public RangeArray (int low, int high) {
high++;
if (high <= low) {
Console.WriteLine(Invalid Indices);
high = 1; // guvenlik icin minimal bir dizi olustur
low = 0;
}
a = new int[high - low];
len = high - low;

lowerBound = low;
upperBound = --high;
}
Bir RangeArray, indeks alt snr low zerinden, st snr da high zerinden aktarlarak
yaplandrlr. Daha sonra dizinin bykln hesaplamak iin high deerine artrma
uygulanr. Bunun nedeni belirtilen indeks deerlerinin her iki utaki snrlar da iine almasdr.
Ardndan st snrn alt snrdan byk olduunun salamas yaplmaktadr. st snr alt
snrdan byk deilse, hata mesaj verilir ve tek elemanl bir dizi oluturulur. Length
zelliine temel oluturan len deikeni, dizideki elemanlarn saysna eitlenir. Son olarak da
lowerBound ve upperBounda deer atamas yaplr.
RangeArray; Length ve Error zelliklerinin uygulanmasn aada gsterildii ekilde
gerekletirir:
// Salt okunur Length ozelligi.
public int Length {
get {
return len;
}

// Salt okunur Error ozelligi.
public bool Error {
get {
return errflag;
}
}
Bu zellikler, FailSoftArray tarafndan kullanlan zelliklere benzerdir ve ayn ekilde
alrlar.
Daha sonra RangeArray, indeksleyicisini aada gsterildii gibi uygular:
// RangeArray icin indeksleyici.
public int this[int index] {
// Bu, get erisimcisidir.
get {
if(ok(index)) {
errflag = false;
return a[index - lowerBound];
} else {
errflag = true;
return 0;
BLM 10: NDEKSLEYCLER VE ZELLKLER

HERKES N C#
289
}
}

// 8u, set erisimcisidir.
set {
if(ok(index)) {
a[index lowerBound] = value;
errflag = false;
}
else errflag = true;
}
}
Bu indeksleyici, FailSoftArray tarafndan kullanlana benzemekle birlikte, nemli bir
fark vardr. Dikkat ederseniz, ay indeksleyen deyim u ekildedir:
index - lowerBound
Yukardaki ifade, index ile aktarlan indeks deerini a zerinde kullanlmaya uygun, sfr
tabanl bir indekse evirir. Bu deyim, lowerBound pozitif te olsa, negatif te olsa, sfr da olsa
alr.
ok() metodu aada gsterilmitir:
// indeks sinirlarin icindeyse true dondur.
private bool ok(int index) {
if(index >= lowerBound & index <= upperBound) return true;
return false;
}
ok() metodu da FailSoftArray tarafndan kullanlan metoda benzer. Tek fark, burada
dizinin indeks aralnn lowerBound ve upperBounda bakarak kontrol edilmesidir.
RangeArray, indeksleyicileri ve zellikleri kullanarak oluturabileceiniz kiisel dizi
tiplerinden sadece birini gsterir. Kukusuz birka baka tip oluturmak ta mmkndr.
rnein, gereksinime gre genileyen ve daralan dinamik diziler, ilikisel diziler ve seyrek
diziler oluturabilirsiniz. Altrma olarak bu dizi tiplerinden birini oluturmay denemek
isteyebilirsiniz.



O N B R N C B L M

KALITIM























11
BLM 11: KALITIM

HERKES N C#
291
Kaltm, nesne ynelimli programlamann temel prensibinden biridir, nk kaltm,
hiyerarik snflandrma oluumlarna olanak tanr. Kaltm kullanarak, birbiriyle balantl bir
grup enin ortak zelliklerini tanmlayan genel bir snf oluturabilirsiniz. Bu snf daha sonra
dier, daha spesifik snflara kaltm yoluyla aktarlr ve her snf kendisine zg zellikleri
buna ekler.
C# dilinde kaltm yoluyla aktarlan snfa temel snf denir. Kaltm ilemini gerekletiren
snf tretilmi snf olarak adlandrlr. Bu yzden, tretilmi snf temel snfn zelletirilmi
bir versiyonudur. Tretilmi snf, temel snf tarafndan tanmlanan tm deiken, metot,
zellik, operatr ve indeksleyicileri kaltm yoluyla elde eder ve kendisine zg elemanlar da
ayrca ekler.
Kaltmn Temel Unsurlar
C#, bir snfn kendi deklarasyonuna bir baka snf dahil etmesine olanak tanyarak
kaltm destekler. Bu, bir tretilmi snf deklare edilirken temel snf ta belirtilerek
gerekletirilir. Gelin imdi bir rnekle balayalm. Aadaki TwoDShape adndaki snf, iki
boyutlu genel bir eklin niteliklerini tanmlamaktadr. Sz konusu ekil bir kare, dikdrtgen,
gen vs olabilir.
// Iki boyutlu nesneler icin bir sinif.
class TwoDShape {
public double width;
public double height;

public void showDim() {
Console.WriteLine(Width and height are + width +
and + height);
}
}
TwoDShape, iki boyutlu nesnelerin zel tiplerini tarif eden snflar iin bir temel snf
olarak (yani, bir balang noktas olarak) kullanlabilir. rnein, aadaki program
Triangle adnda bir snf tretmek iin TwoDShapei kullanmaktadr, Trianglen deklare
edilme ekline zellikle dikkat edin.
// Basit bir sinif hiyerarsisi.

using System;

// Iki boyutlu nesneler icin bir sinif.
class TwoDShape {
public double width;
public double height;

public void showDim() {
Console.WriteLine(Width and height are + width +
and + height);
}
}

HERKES N C#
KISIM I C# DL

292

// Triangle, TwoDShapeden tretilir.
class Triangle : TwoDShape {
public string style; // ucgenin sekli

// ucgenin alanini dondur.
public double area() {
return width * heignt / 2;
}

// ucgenin seklini goster.
public void showStyle() {
Console.WriteLine(Triangle is + style);
}
}

class Shapes {
public static void Main() {
Triangle t1 = new Triangle();
Triangle t2 = new Triangle();

t1.width = 4.0;
t1.height = 4.0;
t1.style = isosceles;

t2.width = 8.0;
t2.height = 12.0;
t2.style = right;

Console.WriteLine(Info for t1: );
t1.showStyle();
t1.showDim();
Console.WriteLine(Area is + t1.area());

Console.WriteLine();

Console.WriteLine(Info for t2: );
t2.showStyle();
t2.ShowDim();
Console.WriteLine(Area is + t2.area());
}
}
Bu programn kts aada gsterilmitir:
Info for t1:
Triangle is isosceles
Width and height are 4 and 4
Area is 8

Info for t2:
Triangle is right
Width and height are 8 and 12
Area is 48
BLM 11: KALITIM

HERKES N C#
293
Triangle snf, TwoDShapein belirli bir tipini oluturur. Bu rnekte bu tip bir gendir.
Triangle snf TwoDShapein tmn ierir; ayrca, style alann, area() ve
showStyle() metotlarn da ekler. genin ekli style iinde saklanr; area(), genin
alann hesaplar ve dndrr; showStyle() ise genin eklini ekranda gsterir.
TwoDShapei kaltm yoluyla elde etmek (devralmak) iin Triangleda kullanlan sz
dizimine dikkat edin:
class Triangle ; TwoDShape {
Bu sz dizimi genelletirilebilir. Ne zaman bir snf dierini katlm yoluyla elde etse,
temel snfn ismi tretilmi snfn ismini takip eder ve bu ikisi, iki nokta ile birbirinden ayrlr
C#ta bir snf kaltm yoluyla aktarmak iin kullanlan sz dizimi dikkat ekecek lde basit
ve kullanldr.
Triangle, kendisinin temel snf olan TwoDShapein tm yelerini ierdii iin
area()nn iindeki width ve heighta eriebilir. Ayrca, Main() iinde, t1 ve t2
nesneleri de width ve heighta sanki bunlar Trianglen birer parasym gibi referansta
bulunabilirler. ekil 11.1de TwoDShapein Trianglea nasl dahil edildii kavramsal olarak
gsteriliyor.








EKL 11.1: Triangle snfnn kavramsal gsterimi
TwoDShape, Triangle iin bir temel olsa bile, ayn zamanda tamamen bamsz, kendi
bana varolan bir snftr. Bir trelitmi snf iin temel snf niteliinde olmak, temel snfn
kendi bana kullanlmayaca anlamna gelmez. rnein, aadaki kod paras tamamen
geerlidir;
TwoDShape shape = new TwoDShape();

shape.width = 10;
shape,height = 20;

shape.showDim();
Kukusuz, TwoDShapee ait bir nesne ne TwoDShapeten tretilen snflar hakknda ne de
bu snflara eriimler hakknda bir bilgiye sahip deildir.
width
height

showDim()
style
area()
showStyle()
TwoDShape
Triangle


HERKES N C#
KISIM I C# DL

294
Bir temel snfn kaltm yoluyla aktarld snf deklrasyonunun genel yaps aadaki
gibidir:
class tretilmi-snf-ismi : temel-snf-ismi {
// snfn gvdesi
}
Oluturduunuz her tretilmi snf iin yalnzca bir adet temel snf belirtebilirsiniz. C#,
tek bir tretilmi snf iine birden fazla temel snf kaltm yoluyla aktarmay desteklemez.
(Bu, birden fazla temel snf kaltm yoluyla aktarabildiiniz C++taki yapdan farkldr. C++
kodunu C#a dntrrken bu konuya dikkat edin.) Ancak, bir tretilmi snfn bir baka
tretilmi snfn temel snf olmasn salayan bir kaltm hiyerarisi oluturabilirsiniz.
Kukusuz hibir snf dolayl veya dolaysz olarak kendi kendisinin temel snf olamaz.
Kaltmn balca avantaj udur: Bir grup nesnenin ortak niteliklerini tanmlayan bir temel
snf oluturduktan sonra bu snf, ok daha spesifik olan tretilmi snflardan islenilen sayda
oluturmak iin kullanlabilir. Tretilmi snflarn her biri, kendisine zg snflandrmay tam
olarak biimlendirebilir. rnein, dikdrtgenleri bir snf iine paketleyen ve TwoDShapeten
tretilmi bir baka snf, u ekildedir:
// Dikdortgenler icin TwoDShapeten turetilmis bir sinif.
class Rectangle : TwoDShape {
// Eger dortgen bir kareyse true dondur.
public bool isSquare() {
if(width == height) return true;
return false;
}

// Dikdortgenin alanini dondur.
public double area() {
return width * height;
}
}
Rectangle snf TwoDShapei ierir; ayrca, dikdrtgenin kare olup olmadn
belirleyen isSquare() metodunu ve dikdrtgenin alann hesaplayan area() metodunu da
ekler.
ye Eriimi ve Kaltm
Blm 8de rendiiniz gibi, snf yelerinin izinsiz kullanmlarn veya gereksiz yere
kurcalanmalarn nlemek iin snf yeleri genellikle private olarak deklare edilir. Bir snf
kaltm yoluyla aktarmak, bu private eriim kstlamasn inemez. Bylece, bir tretilmi
snf kendi temel snfnn tm yelerini ierse dahi, temel snfn private olarak deklare
edilmi yelerine eriemez. rnein, eer width ve height, TwoDShape iinde, aada
gsterildii gibi, private olarak deklare edilseydi, Trianglen bunlara erimesi mmkn
olmayacakt:
// private uyeler kalitim yoluyla aktarilamaz.
BLM 11: KALITIM

HERKES N C#
295

// Bu ornek derlenmeyecektir.
using System;

// Iki boyutlu nesneler icin bir sinif.
class TwoDShape {
double width; // artik ozel
double height; // artik ozel

public void showDim() {
Console.WriteLine(Width and height are + width +
and + height);
}
}

// Triangle, TwoDShapeten turetilir.
class Triangle : TwoDShape {
public string style; // ucgenin sekli

// Ucgenin alanini dondur.
public double area() {
return width * height / 2; // Hata, private uyeye erisemez
}

// ucgenin seklini goster.
public void showStyle() {
Console.WriteLine(Triangle is + style);
}
}
Triangle snf derlenmeyecektir, nk area() metodu iindeki width ve heighta
ynelik referanslar eriimin inenmesine neden olur. width ve height imdi private
olduklar iin artk yalnzca kendi snflarnn dier yeleri tarafndan eriilirler. Tretilmi
snflar bunlara eriim hakkna sahip deildir.

NOT

Bir snfn private yesi kendi snfnda private olarak kalacaktr. Byle bir
private ye, tretilmi snflar da dahil olnak zere kendi snf dnda kalan kod
tarafndan eriilemez.

lk bakta, tretilmi snflarn, temel snflarn private yelerine eriimlerinin
olmamasn ciddi bir kstlama gibi dnebilirsiniz, nk bu durum private yelerin
kullanmlarna birok yerde engel olacaktr. Ancak, bu doru deildir, nk C# eitli
zmler salamaktadr. Bunlardan biri, protected (korumal) yeler kullanmaktr.
protected yeler bir sonraki blmde anlatlmaktadr. kinci bir zm, private verilere
eriim salamak amacyla public zellikler ya da metotlar kullanmaktr. nceki blmlerde
grdnz gibi, C# programclar genellikle bir snfn private yelerine metotlar
araclyla ya da sz konusu yeleri zellik haline getirerek eriim izni verirler. te aada
TwoDShape snflarnn width ve height yeleri zellik haline getirilerek yeniden yazlm
versiyonunu grmektesiniz:

HERKES N C#
KISIM I C# DL

296
// private uyeleri ayarlamak ve almak icin ozellik kullanir.

using System;

// Iki boyutlu nesneler icin bir sinif.
class TwoDShape {
double pri_width; // artik ozel
double pri_height; // artik ozel

// width ve height icin ozellikler
public double width {
get { return pri_width; }
set { pri_width = value; }
}

public double height {
get { return pri_height; }
set { pri_height = value; }
}

public void showDim() {
Console.WriteLine(Width and height are + width +
and + height);
}
}

// Ucgenler icin TwoDShapeten turetilmis bir sinif.
class Triangle : TwoDShape {
public string style; // ucgenin sekli

// ucgenin alanini dondur.
public double area() {
return width * height / 2;
}

// Ucgenin seklini goster.
public void showStyle() {
Console.WriteLine(Triangle is + style);
}
}

class Shapes2 {
public static void Main() {
Triangle t1 = new Triangle();
Triangle t2 = new Triangle();

t1.width = 4.0;
t1.height = 4.0;
t1.style = isosceles;

t2.width = 8.0;
t2.height = 12.0;
t2.style = right;

Console.WriteLine(Info for t1: );
BLM 11: KALITIM

HERKES N C#
297
t1.showStyle();
t1.showDim();
Console.WriteLine(Area is + t1.area());

Console .WriteLine();

Console.WriteLine(Info for t2: );
t2.showStyle();
t2.showDim();
Console.writeLine(Area is + t2.area());
}
}
Temci ve tretilmi snflara referansta bulunurken kimi zaman st snf (superclass) ve alt
snf (subclass) terimleri kullanlr. Bu terimler Java programlamasndan gelmektedir. Java'da
st snf olarak adlandrlan, C#ta temel snf olarak adlandrlmaktadr. Javada alt snf deni-
len ise, C#ta tretilmi snf olarak kullanlr. Her iki terim kmesini ounlukla her iki dilin
snflarna uygulanrken greceksiniz, fakat elinizdeki kitapta standart C# terimleri kullanl-
maya devam edecektir. C++ta da temel snf / tretilmi snf terminolojisi kullanlmaktadr.
protected Eriim Kullanm
Az nce akland gibi, bir temel snfn bir private yesi bir tretilmi snf tarafndan
eriilemez. Buradan yle bir sonu kmaktadr: Bir tretilmi snfn temel snfn iindeki
baz yelere eriebilmesini istiyorsanz, tretilmi snfn public olmas gerekir. Kukusuz sz
konusu yeyi public hale getirmek, ayrca bu yeyi kodun dier blmlerinin eriimi iin de
public hale getirir. Oysa, istenilen bu olmayabilir. Neyse ki, bu karm doru deildir, nk
C# bir korumal ye oluturmanza olanak tanr. Bir korumal ye snf hiyerarisi iinde
publictir ama hiyerari dnda privatetr.
Korumal ye protected eriim niteleyicisi kullanlarak oluturulur. Bir snfn bir yesi
protected olarak deklere edilirse, s konusu ye nemli bir istisna haricinde privatetr.
protected ye kaltm yoluyla aktarld zaman, istisnai durum ortaya kar. Bu durumda,
temel snfn protected yesi tretilmi snfn protected yesi halini alr ve bylece
tretilmi snf tarafndan eriilebilir. Bundan dolay, protected niteleyicisini kullanarak,
kendi snflarnda private olan fakat yine de kaltm yoluyla aktarlabilen ve bir tretilmi
snf tarafndan eriilebilen snf yeleri oluturabilirsiniz.
Aada, protected niteleyicisini kullanan basit bir rnek gryorsunuz;
// protectedi tanitir.

using System;

class B {
protected int i, j; // Bde private, fakat D tarafindan erisilebilir

public void set(int a, int b) {
i = a;

HERKES N C#
KISIM I C# DL

298
j = b;
}

public void show() {
Console.WriteLine(i + + j);
}
}

class D : B {
int k; // private

// D, Bnin i ve j uyelerine erisebilir
public void setk() {
k = i * j;
}

public void showk() {
Console.WriteLine(k);
}
)

class ProtectedDemo {
public static void Main() {
D ob = new D();

ob.set(2, 3); // OK, D tarafindan bilinir
ob.show(); // QK, D tarafindan bilinir

ob.setk(); // OK, Dnin bir parcasi
ob.showk(); // OK, Dnin bir parcasi
}
}
Bu rnekte B, kaltm yoluyla Dye aktarld iin ve Bnin iinde i ve j protected
olarak deklare edildikleri iin, setk() metodu bunlara eriemez. Eger i ve j, B tarafndan
private olarak tanmlanm olsalard Dnin bunlara eriimi olmayacakt ve program
derlenmeyecekti.
Tpk public ve private gibi, hangi sayda kaltm katman dahil edilmi olursa olsun
protected stats ye ile birlikte kalr. Bu yzden, bir tretilmi snf bir baka tretilmi
snf iin temel snf olarak kullanlrken, ilk tretilmi snf tarafndan kaltm yoluyla elde
edilen ilk temel snfn herhangi bir protected yesi, ikinci tretilmi snfa da aynen
protected olarak kaltm yoluyla aktarlr.
Yaplandrclar ve Kaltm
Bir hiyerari iinde, hem temel snflarn hem de tretilmi snflarn kendi
yaplandrclarna sahip olmalar mmkndr. Bu ortaya nemli bir soru atar: Tretilmi bu
snfn bir nesnesini yaplandrmaktan hangi yaplandrc sorumludur? Temel snf iindeki mi,
trelilmi snf iindeki mi, yoksa her ikisi de mi? Yant: Nesnenin temel snfa ait paralar
temel snfn yaplandrcs tarafndan, tretilmi snfa ait paralar tretilmi snfn
BLM 11: KALITIM

HERKES N C#
299
yaplandrcs tarafndan yaplandrlr. Bu akla yatkndr, nk temel snfn, tretilmi snf
iindeki eler ve elere eriim hakknda bilgisi yoktur. Bu nedenle, her iki snfn
yaplandrclar ayr olmaldr. nceki rnekler C# tarafndan otomatik olarak oluturulan
varsaylan yaplandrclara dayanyordu; dolaysyla, bu bir sorun deildi. Ancak, pratikte
birok snfn yaplandrcs vardr. Burada, bu durumun nasl kontrol altna alndn
greceksiniz.
Yalnzca tretilmi snfn iinde bir yaplandrc tanmlanrsa, sz konusu sre basittir ve
sadece tretilmi snfn nesnesini yaplandrmaktan ibarettir. Nesnenin temel snfla ilgili par-
as varsaylan yaplandrc tarafndan otomatik olarak yaplandrlr. rnein, ite size,
Trianglen zerinde yeniden allm bir versiyonu. Bu kez Triangle iinde bir
yaplandrc tanmlanmaktadr. Ayrca, style da private hale getirilmitir nk style'n
deeri artk yaplandrc tarafndan verilmektedir.
// Trianglea bir yapilandirici eklemek.

using System;

// Iki boyutlu nesneler icin bir sinif.
class TwoDShape {
double pri_width; // private
double pri_height; // private

// width ve height icin ozellikler.
public double width {
get { return pri_width; }
set { priwidth = value; }
}

public double height {
get { return pri_height; }
set { pri_height = value; }
}

public void showDim() {
Console.WriteLine(Width and height are + width +
and + height);
}
}

// Ucgenler icin TwoDShapeten turetilen bir sinif.
class Triangle : TwoDShape {
string style; // ozel

// Yapilandirici
public Triangle(string s, double w, double h) {
width = w; //temel sinifi ilk kullanima hazirla
height = h; // temel sinifi ilk kullanima hazirla

style = s; // turetilmis sinifi ilk kullanima hazirla
}


HERKES N C#
KISIM I C# DL

300
// Ucgenin alanini dondur.
public double area() {
return width * height / 2;
}

// Ucgenin seklini goster.
public void showStyle() {
Console.WriteLine(Triangle is + style);
}
}

class Shapes3 {
public static void Main() {
Triangle t1 = new Triangle(isosceles, 4.0, 4.0);
Triangle t2 = new Triangle(right, 8.0, 12.0);

Console.WriteLine(Info for t1: );
t1.showStyle();
t1.showDim();
Console.WriteLine(Area is + t1.area());

Console.WriteLine();

Console.WriteLine(Info for t2: );
t2.showStyle();
t2.showDim();
Console.WriteLine(Area is + t2.area())
}
}
Bu rnekte Trianglen yaplandrcs, kaltm yoluyla kendi style alanlarn da birlikte
getiren TwoDShapein yelerini ilk kullanma hazrlar.
Hem temel snfta hem de tretilmi snfta yaplandrc tanmlannca sz konusu sre bi-
raz daha karmak hale gelir, nk bu kez hem temel snfn hem de tretilmi snfn
yaplandrclar altrlmaldr. Bu durumda C#n bir baka anahtar kelimesini kullanmals-
nz: base. basein iki kullanm ekli vardr. Birinci kullanm, temel snfn yaplandrcsn
armaktr. kinci kullanm ise; temel snfn, tretilmi snfn bir yesinden gizledii yesine
erimek iindir. Bu blmde birinci kullanmn inceleyeceiz.
Temel Snfn Yaplandrclarn armak
Tretilmi bir snf kendi temel snf iinde tanmlanm bir yaplandrcy arabilir.
Bunun iin, tretilmi snfn yaplandrc deklarasyonunun geniletilmi bir ekli ve base
anahtar kelimesi kullanlmaldr. Bu geniletilmi deklarasyonun genel yaps aadaki gibidir:
tretilmi-yaplandrc (parametre-listesi) : base(arg-listesi){
// yaplandrcnn gvdesi
}
Burada arg-listesi, temel snf iindeki yaplandrn tarafndan ihtiya duyulan
herhangi bir argman belirtmektedir. ki noktann konumuna dikkat edin.
BLM 11: KALITIM

HERKES N C#
301
basein nasl kullanldn anlamak iin TwoDShapein aadaki programdaki
versiyonunu ele aln. TwoDShapede bu kez width ve height zelliklerine ilk deer atayan
bir yaplandrc tanmlanmaktadr.
// TwoDShapee yapilandiricilar ekle.

using System;

// Iki boyutlu nesneler icin bir sinif.
class TwoDShape {
double pri_width; // private
double pri_height; // private

// TwoDShape icin yapilandirici.
public TwoDShape(double w, double h) {
width = w;
height = h;
}

// width ve height icin ozellikler.
public double width {
get { return pri_width; }
set { pri_width = value; }
}

public double height {
get { return pri_height; }
set { pri_height = value; }
}

public void showDim() {
Console.WriteLine(Width and height are + width +
and + height);
}
}

// Ucgenler icin TwoDShapeten turetilen bir sinif.
class Triangle : TwoDShape {
string style; // ozel

// Temel sinif yapilandiricisini cagir.
public Triangle(string s, double w, double h) : base(w, h) {
style = s;
}

// Ucgenin alanini dondur.
public double area() {
return width * height / 2;
}

// Ucgenin seklini goster.
public void showStyle() {
Console.WriteLine(Triangle is + style);
}

HERKES N C#
KISIM I C# DL

302
}

class Shapes4 {
public static void Main() {
Triangle t1 = new Triangle(isosceles, 4.0, 4.0);
Triangle t2 = new Triangle(right, 8.0, 12.0);

Console.WriteLine(Info for t1: );
t1.showStyle();
t1.showDim();
Console.WriteLine(Area is + t1.area());

Console.WriteLine();

Console.WriteLine(Info for t2: );
t2.showStyle();
t2.showDim();
Console.WriteLine(Area is + t2.area());
}
}
Bu rnekte Triangle(), basei w ve h parametreleriyle arr. Bu, TwoDShape()
yaplandrcsnn arlmasna neden olur. TwoDShape() yaplandrcs bu parametre
deerlerini kullanarak width ve heighta ilk deer atar. Triangle artk bu deerlere kendisi
ilk deer atamaz, Triangle yalnzca kendisine ait bir deer olan stylea ilk deer atar. Bu
sayede, TwoDShape kendi alt nesnesini istedii gibi yaplandrmakta zgr kalr. stelik
TwoDShape, mevcut tretilmi snflardan hangilerinin bilgisi olmad hakknda da bir
ilevsellik ekleyebilir; bylece, mevcut kodun kmesi nlenmi olur.
Temel snf tarafndan tanmlanan herhangi bir yaplandrc base tarafndan arlabilir.
altrlacak olan yaplandrc, argmanlar eleen yaplandrc olacaktr. rnein, ite size
TwoDShape ve Trianglen her ikisinin de geniletilmi versiyonlar. Aadaki rnekte
TwoDShape ve Triangle, hem varsaylan hem de tek argmanl yaplandrc ierirler.
// TwoDShapee biraz daha yapilandirici eklemek.

using System;

class TwoDShape {
double pri_width; // private
double pri_height; // private

// varsayilan yapilandirici.
public TwoDShape() {
width = height = 0.0;
}

// TwoDShape icin yapilandirici.
public TwoDShape(double w, double h) {
width = w;
height = h;
}
BLM 11: KALITIM

HERKES N C#
303

// Esit width ve height degerleri olan bir nesne yapilandir.
public TwoDShape(double x) {
width = height = x;
}

// width ve height icin ozellikler.
public double width {
get { return pri_width; }
set { pri_width = value; }
}

public double height {
get { return pri_height; }
set { pri_height = value; }
}

public void showDim() {
Console.WriteLine(Width and height are + width +
and + height);
}
}

// Ucgenler icin TwoDShapeten turetilen bir sinif.
class Triangle : TwoDShape {
string style; // ozel

/* Varsayilan yapilandirici. Bu, otomatik olarak TwoDShapein
varsayilan yapilandiricisini cagirir. */
public Triangle() {
style = null;
}

// Uc arguman alan yapilandirici.
public Triangle(string s, double w, double h) : base(w, h) {
style = s;
}

// Ikizkenar bir ucgen yapilandir.
public Tnangle(double x) : base(x) {
style = isosceles;
}

// Ucgenin alanini dondur.
public double area() {
return width * height / 2;
}

// Ucgenin seklini goster.
public void showStyle() {
Console.WriteLine(Triangle is + style);
}
}

class Shapes5 {

HERKES N C#
KISIM I C# DL

304
public static void Main() {
Triangle t1 = new Triangle();
Triangle t2 = new Triangle(right, 8.0, 12.0);
Triangle t3 = new Triangle(4.0);

t1 = t2;

Console.WriteLine(Info for t1: );
t1.showStyle();
t1. showDim();
Console.WriteLine(Area is + t1.area());

Console.WriteLine();

Console.WriteLine(Info for t2: );
t2.showStyle();
t2.showDim();
Console.WriteLine(Area is + t2.area());

Console.WriteLine();

Console.WriteLine(Info for t3: );
t3.showStyle();
t3.showDim();
Console.WriteLine(Area is + t3.area());

Console.WriteLine();
}
}
Bu versiyonun kts aadaki gibidir.
Info for t1:
Triangle is right
Width and height are 8 and 12
Area is 48

Info for t2:
Triangle is right
Width and height are 8 and 12
Area is 48

Info for t3:
Triangle is isosceles
Width and height are 4 and 4
Area is 8
Gelin, basein ardnda yatan en nemli kavramlar yeniden gzden geirelim. Bir
tretilmi snf base kelimesi kullanlarak belirtilince, kendisinin dorudan tretildii temel
snfn yaplandrcsn aryordur. Bu, birden fazla seviyeye sahip hiyerariler iin de
geerlidir. Temel snfn yaplandrcsna argman aktarmak iin, bunlar basein argmanlar
olarak belirtmelisiniz. Eer base kelimesi mevcut deilse, bu durumda base snfnn
varsaylan yaplandrcs otomatik olarak arlr,
BLM 11: KALITIM

HERKES N C#
305
Kaltm ve sim Gizleme
Bir tretilmi snfn temel snftaki bir ye ile ayn ismi tayan bir ye tanmlamas
mmkndr. Byle bir durum sz konusu olunca temel snfn yesi tretilmi snf iinde
gizlenmi olur. Bu, C#ta teknik olarak bir hata olmasa da derleyici bir uyar mesaj verecektir.
Bu bir ismin gizlenmekte olduu gereine iaret edecektir. Eer niyetiniz temel snf yesini
gizlemek ise, bu durumda bu uyary nlemek iin tretilmi snf yesinin ncesinde new
anahtar kelimesini kullanmalsnz. newun bu kullanmnn bir nesne rnei olutururkenki
kullanmndan tamamen ayr ve de farkl olduunu kavrayn.
te, isim gizleme ile ilgili bir rnek:
// Kalitim baglantili isim gizleme ile ilgili bir ornek.

using System;

class A {
public int i = 0;
}

// Bir turetilmis sinif olustur.
class B : A {
new int i; // bu i, A'nin icindeki i'yi gizliyor

public B(int b) {
i = b; // Bnin icindeki i
}

public void show() {
Console.WriteLine(i in derived class: + i);
)
}

class NameHiding {
public static void Main() {
B ob = new B(2);

ob.show();
}
}
ncelikle, Bnin iinde i deklare edilirken new'un kullanmna dikkat edin. Aslnda bu
ifade, derleyiciye unu anlatyor: A temel snf iindeki iyi gizleyen i adnda yeni bir
deikenin oluturulmakta olduunun farkndasnz. newu darda brakrsanz, bir uyar
mesaj retilir.
Bu programdan elde edilen kt aadaki gibidir;
i in derived class: 2

HERKES N C#
KISIM I C# DL

306
B, i adnda kendi rnek deikenini tanmlad iin Ann iindeki iyi gizlemektedir. Bu
yzden, show() metodu B tipinde bir nesne zerinde arlrsa inin A iinde tanmlanan
deeri deil de, B tarafndan tanmlanan deeri ekranda gsterilir.
Gizli Bir sme Erimek in base Kullanm
basein biraz this gibi davranan ikinci bir ekli de vardr. Bunun thisten tek fark,
bunun her zaman kendisinin kullanlmakta olduu tretilni snfn tredii temel snfna
referansta bulunmasdr. Bu kullanmn genel yaps u ekildedir:
base.ye
Burada ye, bir metot ya da bir rnek deiken olabilir. basein bu tr kullanm, bir
tretilmi snf iindeki ye isminin temel snf iindeki ayn isimli yeyi gizledii durumlar
iin ok uygundur. Bir nceki rnekteki snf hiyerarisinin u versiyonunu ele aln:
//Isim gizliliginin ustesinden gelmek icin base kullanmak.

using System;

class A {
public int i = 0;
}

// Turetilmis bir sinif olustur.
class B : A {
new int i; // bu i, Anin icindeki iyi gizliyor

public B(int a, int b) {
base.i = a; // bu, Anin icindeki iyi ortaya cikariyor
i = b; // Bnin icindeki i
}

public void show() {
// bu, Anin icindeki iyi gosterir.
Console.WriteLine(i in base class: + base.i);

// bu, Bnin icindeki iyi gosterir.
Console.WriteLine(i in derived class: + i);
}
}

class UncoverName {
public static void Main() {
B Ob = new B(1, 2);

ob.show();
}
}
Bu program aadaki kty ekranda gsterir:
i in base class: 1
BLM 11: KALITIM

HERKES N C#
307
i in derived class: 2
Bnin iindeki i rnek deikeni Ann iindeki iyi gizliyor olsa da base, temel snf
iinde tanmlanm iye eriim imkan verir.
Gizlenmi metotlar da base kullanlarak arlabilir. u rnei ele aln:
// Gizlenmis bir metot cagir.

using System;

class A {
public int i = 0;

// Anin icindeki show()
public void show() {
Console.WriteLine(i in base class: + i);
}
}

// Tretilmis bir sinif olustur.
class B : A {
new int i; // bu i, Anin icindeki iyi gizler

public B(int a, int b) {
base.i = a; // bu i, Anin icindeki iyi ortaya cikarir.
i = b; // Bnin iindeki i
}

// Bu, Anin icindeki show()u gizler.
// new kullanmna dikkat edin.
new public void show() {
base.show(); // bu, Anin icindeki show()u cagirir

// bu, Bnin icindeki iyi gosterir.
Console.WriteLine(i in derived class: + i);
}
}

class UncoverName {
public static void Main() {
B ob = new B(1, 2);

ob.show();
}
}
Programn kts aacda gsterilmitir:
i in base class: 1
i in derived class: 2
Grdnz gibi base.show(), show()un temel snf iinde yer alan versiyonunu
armaktadr.

HERKES N C#
KISIM I C# DL

308
Bir dier husus: Bu programda, Ann iindeki show()u gizleyen show() adnda yeni bir
metot oluturulmakta olduunu bildiinizi derleyiciye anlatmak iin new kullanldna dikkat
edin.
ok Katmanl Hiyerari Oluturmak
u ana dek, yalnzca bir temel snf ve bir tremi snftan oluan basit snf hiyerarilerini
kullanmaktayz. Ancak, istediiniz kadar ok sayda kaltm katman ieren hiyerariler ina
edebilirsiniz. nceden de bahsedildii gibi, bir tretilmi snf bir bakasnn temel snf
olarak kullanmak tamamen geerlidir. rnein, A, B ve C adnda snfn verildiini
varsayarak C, Bden; B de Adan tretilebilir. Bu tr bir durum sz konusu olduunda, tretilmi
snflarn her biri kendi temel snflarnn tmnde yer alan zelliklerin tmn kaltm yoluyla
elde eder. Bu rnekte C, B ve Ann tm zelliklerine kaltm yoluyla sahip olur.
ok katmanl hiyerarinin nasl kullanl olabileceini anlamak iin, aadaki program
ele aln. Bu programda Triangle adndaki tretilmi snf, ColorTriangle adnda tretilmi
snf oluturmak iin temel snf olarak kullanlmaktadr. ColorTriangle, Triangle ve
TwoDShapein tm zelliklerini kaltm yoluyla elde ettii gibi, genin rengini tutan color
adnda bir de alan eklemektedir.
// Cok katmanli bir hiyerarsi.

using System;

class TwoDShape {
double pri_width; // private
double pri_height; // private

// Varsayilan yapilandirici.
public TwoDShape() {
width = height = 0.0;
}

// TwoDShape icin yapilandirici.
public TwoDShape(double w, double h) {
width = w;
height = h;
}

// Esit width ve height degerlerine sahip bir nesne yapilandir
public TwoDShape(double x) {
width = height = x;
}

// width ve height icin ozellikler.
public double width {
get { return pri_width; }
set { pri_width = value; }
}

BLM 11: KALITIM

HERKES N C#
309
public double height {
get { return pri_height; }
set { pri_height = value; }
}

public void showDim() {
Console.WriteLine(Width and height are + width +
and + height);
}

// Ucgenler icin TwoDShapeten turetilen bir sinif.
class Triangle : TwoDShape {
string style; // ozel

/* Varsayilan yapilandirici.
Bu, TwoDShapein varsayilan yapilandiricisini cagirir. */
public Triangle() {
style = null;
}

// Yapilandirici
public Triangle(string s, double w, double h) : base(w, h) {
style = s;
}

// Bir ikizkenar ucgen yapilandir.
public Triangle(double x) : base(x) {
style = isosceles;
}

// ucgenin alanini dondur.
public double area() {
return width * height / 2;
}

// Ucgenin seklini goster.
public void showStyle() {
Console.WriteLne(Triangle is + style);
}
}

// Trianglei genislet.
class ColorTriangle : Triangle {
string color;

public colorTriangle(string c, string s, double w,
double h) : base(s, w, h) {
color = c;
}

// Rengi goster.
public void showColor() {
Console.WriteLine(Color is + color);
}
}

HERKES N C#
KISIM I C# DL

310

class Shapes6 {
public static void Main() {
ColorTriangle t1 =
new ColorTriangle(Blue, right, 8.0, 12.0);
ColorTriangle t2 =
new ColorTriangle(Red, isosceles, 2.0, 2.0);

Console.WriteLine(Info for t1: );
t1.showStyle();
t1.showDim();
t1.showColor();
Console.WriteLine(Area is + t1.area());

Console.WriteLine();

Console.WriteLine(Info for t2: );
t2.showStyle();
t2.showDim() ;
t2.showColor();
Console.WriteLine(Area is + t2.area());
}
}
Bu programn kts aada gsterilmitir:
Info for t1;
Triangle is right
Width and height are 8 and 12
Color is Blue
Area is 48

Info for t2;
Triangle is isosceles
Width and height are 2 and 2
Color is Red
Area is 2
Kaltmdan tr ColorTriangle, nceden tanml Triangle ve TwoDShape
snflarndan yararlanabilir. ColorTrianglen yalnzca kendisine zg, spesifik uygulama
iin gerek duyduu ekstra enformasyonu eklemesi yeterlidir. Bu, kaltmn neminin bir
parasdr; kodun yenide kullanmna olanak tanr.
Bu rnek, bir dier nemli hususu daha aklamaktadr: base daima kendisine en yakn te-
mel snf iindeki yaplandrcyla ilikilidir. ColorTriangle iindeki base, Triangle
iindeki yaplandrcy arr. Triangle iindeki base ise, TwoDShape iindeki
yaplandrcy arr. Bir snf hiyerarisinde eger bir temel snf yaplandrcs parametre
gerektirirse, tm tretilmi snflar bu parametreleri yukarya doru aktarmaldr. Tretilmi
snfn kendisi parametre gerektirsin ya da gerektirmesin, bu durum geerlidir.

BLM 11: KALITIM

HERKES N C#
311
Yaplandrclar Ne Zaman arlr?
Kaltm ve snf hiyerarileri yukarda ele alnrken nemli bir soru aklnza taklm
olabilir: Tretilmi bir snf oluturulunca nce kimin yaplandrcs altrlr; tretilmi
snfn yaplandrcs m, yoksa temel snf tarafndan tanmlanan yaplandrc m? rnein, B
adnda bir tretilmi snf ve A adnda bir temel snf verildiini varsayalm. Ann
yaplandrcs Bninkinden nce mi arlr, yoksa sonra m? Bu sorunun yant udur: Bir snf
hiyerarisinde yaplandrclar, temel snftan tretilmi snfa doru tretilme srasna gre
arlrlar. stelik, base kullanlsn ya da kullanlmasn bu sra ayndr. Eer base
kullanlmazsa, temel snflarn her birinin varsaylan (parametresiz) yaplandrcs
altrlacaktr. Aadaki program yaplandrclarn altrlma srasn gstermektedir:
// Yapilandiricilarin ne zaman cagrilacagini gosterir.

using System;

// Bir temel sinif olustur.
class A {
public A() {
Console.WritaLine(Constructing A.);
}
}

// Adan turetilen bir sinif olustur.
class B : A {
public B() {
Console.WriteLine(Constructing B.);
}
}

// Bden turetilen bir sinif olustur.
class C : B {
public C() {
Console.WriteLine(Constructing C.);
}
}

class orderOfConstruction {
public static void Main() {
C c = new C();
}
}
Bu programn kts aada gsterilmitir:
Constructing A
Constructing B
Constructing C
Grdnz gibi, yaplandrclar tretilme srasna gre arlmaktadr.

HERKES N C#
KISIM I C# DL

312
zerinde biraz dnrseniz, yaplandrclarn tretilme srasna gre arlmalarnn akla
yatkn olduunu grrsnz. Temel snfn tretilmi snflar hakknda bir bilgisi olmad iin
temel snfn gerektirdii herhangi bir ilk kullanma hazrlama ilemi, tretilmi snflar tarafn-
dan gerekletirilen ilk kullanma hazrlama ileminden ayrdr ve muhtemelen de n art
niteliindedir. Bu nedenle, ilk nce gereklenmelidir.
Temel Snf Referanslar ve Tretilmi Nesneler
Bildiiniz gibi, C# veri tiplerine sk skya bal bir dildir. Standart dnmler ve basit
tiplere uygulanan otomatik terfiler bir yana, tip uyumluluu kesinlikle zorlanr, Bu yzden, bir
snf tipindeki bir referans deikeni normalde bir baka snf tipindeki nesneye referansta
bulunamaz. rnein, aadaki program ele aln:
// Bu program derlenmeyecektir.

class X {
int a;

public X(int i) { a = i; }
}

class Y {
int a;

public Y(int i) { a = i; }
}

class IncompatibleRef {
public static void Main() {
X x = new X(10);
X x2;
Y y - new Y(5);

x2 = X; // OK, her ikisi de ayni tipte

x2 = y; // Hata, ayni tipte degiller
}
}
Bu rnekte, X ve Y snflar fiziksel olarak ayn olmalarna ramen, bir Y nesnesini bir X
referans deikenine atamak mmkn deildir, nk tipleri farkldr. Genel olarak, bir nesne
referans deikeni yalnzca kendi tipindeki nesnelere referansta bulunabilir.
Ancak, C#n tipler zerindeki kat basksnn nemli bir istisnas mevcuttur. Bir temel
snfa ait referans deikenine, bu temel snftan tretilmi herhangi bir snfa ait bir nesnenin
referans deer olarak atanabilir. te bir rnek:
// temel sinif referansi, turetilmis sinif nesnesine referansta bulunabilir.

using System;

BLM 11: KALITIM

HERKES N C#
313
class X {
public int a;

public X(int i) {
a = i;
}
}

class Y : X {
public int b;

public Y(int i, int j) : base(j) {
b = i;
}
}

class BaseRef {
public static void Main() {
X x = new X(10);
X x2;
Y y = new Y(5, 6);

x2 = x; // OK, her ikisi de ayni tipte
Console.WriteLine(x2.a: + x2.a);

x2 = y; // bu da tamam cunku Y, Xten turetiliyor
Console.WriteLine(x2.a: + x2.a);

// X referanslari yalnizca Xin uyeleri hakknda bilgi sabibi
x2.a = 19; // OK
// x2.b = 27; // Hata, Xin b adinda bir uyesi yok
}
}
Bu rnekte Y artk Xten tretilmektedir. Bylece, x2ye bir Y nesnesini gsteren referans
deer olarak atanabilir.
Hangi yelerin eriilebileceini belirleyen referans deikeninin tipidir; referans
deikeninin referansta bulunduu nesnenin tipi deildir. Bu ayrm kavramak nemlidir. Yani,
bir tretilmi snf nesnesine referans olarak bir temel snf referans deikeni atanrken sz
konusu nesnenin yalnzca temel snf tarafndan tanmlanan paralarna eriim iznine sahip
olacaksnz. x2nin bir Y nesnesine referansta bulunmasna ramen b deerine eriemiyor
olmasnn nedeni budur. Bu akla yatkndr, nk tretilmi snfn kendi iinde temel snfa
neler eklendiinden, temel snfn haberi yoktur. Programn son satrnn aklama eklinde
programdan karlmas da ite bu sebeptendir.
Yukarda anlatlanlar, deyim yerindeyse bir para uuk grnyor olsa da, bunlarn baz
nemli pratik uygulamalar mevcuttur. Bu uygulamalardan biri burada anlatlmaktadr. Dieri
ise bu blmn ileriki sayfalarnda, sanal metotlar anlatlrken ele alnacaktr.
Tretilmi snf referanslarna temel snf deikenlerinin atand nemli yerlerden biri,
bir snf hiyerarisi iinde yaplandrclar arld zamandr. Bildiiniz gibi, bir snfn

HERKES N C#
KISIM I C# DL

314
kendisine ait bir nesneyi parametre olarak alan bir yaplandrc tanmlamas yaygn bir
uygulamadr. Bu sayede, sz konusu snfn bir nesnenin kopyasn karmasna olanak
tannm olur. Bu tr bir snftan tretilen snflar, bu zellikten yararlanabilirler. rnein,
TwoDShape ve Triangle'n aadaki versiyonlarn ele aln. Bu snflarn her ikisi de
parametre olarak bir nesne alan yaplandrc eklemekteler.
// Bir turetilmis sinif referansini bir temel sinif referansina aktarmak.

using System;

class TwoDShape {
double pri_width; // ozel
double pri_height; // ozel

// Varsayilan yapilandirici.
public TwoDShape() {
width = height = 0.0;
}

// TwoDShape icin yapilandirici.
public TwoDShape(double w, double h) {
width = w;
height = h;
}

// Esit width ve height degerlerine sahip bir nesne yapilandir.
public TwoDShape(double x) {
width = height = x;
}

// Bir nesneden bir baska nesne yapilandir.
public TwoDShape(TwoDShape ob) {
width = ob.width;
height = ob.height;
}

// width ve height icin ozellikler.
public double width {
get { return pri_width; }
set { pri_width = value; }
}

public double height {
get { return pri_height; }
set { pri_height = value; }
}

public void showDim() {
Console.WriteLine(Width and height are + width +
and + height);
}
}

// Ugenler icin TwoDShapeten turetilen bir sinif.
BLM 11: KALITIM

HERKES N C#
315
class Triangle : TwoDShape {
string style; // ozel

// Varsayilan yapilandirici.
public Triangle() {
style = null;
}

// Triangle icin yapilandirici.
public Triangle(string s, double w, double h) : base(w, h) {
style = s;
}

// Bir ikizkenar ucgen yapilandir.
public Triangle(double x) : base(x) {
style = isosceles;
}

// Bir nesneden bir baska nesne yapilandir.
public Triangle(Triangle ob) : base(ob) {
style = ob.style;
}

// Ucgenin alanini dondur.
public double area() {
return width * height / 2;
}

// Ucgenin seklini goster.
public void showStyle() {
Console.WriteLine(Triangle is + style);
}
}

class Shapes7 {
public static void Main() {
Triangle t1 = new Triangle(right, 8.0, 12.0);

// t1in kopyasini cikart
Triangle t2 = new Triangle(t1);

Console.WriteLine(Info for t1: );
t1.showStyle();
t1.showDim();
Console.WriteLine(Area is + t1.area());

Console.WriteLine();

Console.WriteLine(Info for t2: );
t2.showStyle();
t2.showDim();
Console.WriteLine(Area is + t2.area());
}
}

HERKES N C#
KISIM I C# DL

316
Bu programda t2, t1 kullanlarak kurulmutur. Bu nedenle, her ikisi de ayndr. kt
aada gsterildii gibidir:
Info for t1:
Triangle is right
Width and height are 8 and 12
Area is 48

Info for t2:
Triangle is right
Width and height are 8 and 12
Area is 48
Bu Triangle yaplandrcsna zellikle dikkat edin:
// Bir nesneden bir baska nesne yapilandir.
public Triangle(Triangle ob) : base(ob) {
style = ob.style;
}
Bu yaplandrc, Triangle tipinde bir nesne alr ve bu nesneyi (base araclyla)
aada gsterilen TwoDShape yaplandrcsna aktarr:
// Bir nesneden bir baska nesne yapilandir.
public TwoDShape(TwoDShape ob) {
width = ob.width;
height = ob.height;
}
Buradaki en nemli nokta, TwoDShape()in bir TwoDShape() nesnesi bekliyor
olmasdr. Ancak; Triangle(), bir Triangle nesnesi aktarr. nceden akland gibi, bu
kod alr, nk temel snf tipinde bir referans, bir tretilmi snf nesnesine referansta
bulunabilir. Bu nedenle, TwoDShape() tipinde bir referans, TwoDShapeten tretilmi bir
snfn nesnesine aktarmak kesinlikle kabul edilebilir bir yaklamdr. TwoDShape()
yaplandrcs, tretilmi snf nesnesinin yalnzca TwoDShape yesi olan ksmlarna ilk deer
atad iin, sz konusu nesnenin tretilmi snflar tarafndan eklenmi baka yeler de
ierebilecek olmas nemli deildir.
Sanal Metotlar ve Devre D Brakma (Overriding)
Sanal metot, temel snf iinde virtual olarak deklare edilen ve bir veya daha fazla
tretilmi smf iinde yeniden tanmlanan bir metottur. Bylece, her tretilmi snf bir sanal
metodun kendine zg bir versiyonuna sahip olabilir. Sanal metotlar ilgintir, nk sanal
metotlardan biri bir temel snf referans tarafndan arldnda ortaya kan durum ilgintir.
Bu durumda, referans tarafndan referansta bulunulan nesnenin tipine bal olarak C#, sz
konusu metodun hangi versiyonunun arlacan belirler ve bu belirleme alma zamannda
gerekletirilir. Yani, farkl nesnelere referansta bulunuluyorsa sanal metodun farkl
versiyonlar altrlr. Bir baka deyile, sanal metodun hangi versiyonunun altrlacan
belirleyen referansta bulunulan nesnenin tipidir (referansn tipi deildir). Dolaysyla, eer bir
BLM 11: KALITIM

HERKES N C#
317
temel snf bir sanal metot ieriyorsa ve bu temel snftan baka snflar tretilmise, bu
durumda bir temel snf referans araclyla farkl nesne tiplerine referansta bulunulurken
sanal metodun farkl versiyonlar altrlr.
Bir temel snf iinde bir metodu sanal olarak deklare etmek iin metodun deklarasyonunun
nne virtual anahtar kelimesini yerletirirsiniz. Bir sanal metot bir tretilmi snf
tarafndan yeniden tanmlanrken override niteleyicisi kullanlr. Bu nedenle, bir sanal
metodu bir tretilmi snf iinde yeniden tanmlama ilemine metodu devre d brakma
(method overriding) denir. Bir metodu devre d brakrken devre d brakan metodun tip
imzas, devre d braklmakta olan sanal metot ile ayn olmaldr. Ayrca, sanal metotlar
static veya abstract (bu blm iinde ele alnacaktr) olarak belirtilemezler.
Metotlar devre d brakma zellii C#n en gl kavramlarndan birinin temelini
oluturmaktadr: dinamik metot datm (dynamic method dispatch). Dinamik metot datm,
devre d braklan bir fonksiyona yaplan arnn derleme zamannda deil, alma
zamannda zld bir mekanizmadr. Dinamik metot datm nemlidir; nk dinamik
metot datm; C#n programn almas srasnda ok biimlilii nasl uyguladnn bir
gstergesidir.
te size, sanal metotlar ve devre d brakma zelliini gsteren bir rnek:
// Sanal bir metot gosterir.

using System;

class Base {
// Temel bir sinif icinde sanal bir metot olusturur.
public virtual void who() {
Console.WriteLine(who() in Base);
}
}

class Derived1 : Base {
// who() metodunu turetilmis sinif icinden devre disi birak.
public override void who() {
Console.WriteLine(who() in Derived1);
}
}

class Derived2 : Base {
// who() metodunu bir baska turetilmis sinif icinden devre disi birak.
public override void who() {
Console.WriteLine(who() in Derived2);
}
}

class OverrideDemo {
public static void Main() {
Base baseOb = new Base();
Derived1 dOb1 = new Derived1();
Derived2 dOb2 = new Derived2();

HERKES N C#
KISIM I C# DL

318

Base baseRef; // bir temel sinif referansi

baseRef = baseOb;
baseRef.who();

baseRef = dOb1;
baseRef.who();

baseRef = dOb2;
baseRef.who();
}
}
Programn kts aadaki gibidir:
who() in Base
who() in Derived1
who() in Derived2
Bu program Base adnda bir temel snf ve Derived1 ve Derived2 adnda iki tretilmi
snf oluturur. Base, who() adnda bir metot deklare eder ve tretilmi snflar bu metodu
devre d brakr. Main() metodu iinde Base, Derived1 ve Derived2 tipinde nesneler
deklare edilir. Ayrca, baseRef adnda Base tipinde bir referans da deklare edilmektedir.
Program daha sonra her tipten nesneye yaplan referanslar baseRefe atar ve who()yu
armak iin bu referanslar kullanr. ktdan grld gibi, who()nun hangi versiyonunun
altrlaca ar srasnda kendisine referansta bulunulan nesnenin tipi ile belirlenir. Bu
versiyon belirleme ileminde baseRefin snf tipi baz alnmaz.
Sanal metotlar devre d brakmak gerekli deildir. Eer bir tretilmi snf, mevcut bir
sanal metodun kendisine ait bir versiyonunu salamyorsa, bu durumda temel snf iindeki me-
tot kullanlr. rnein:
/* Bir sanal metot devre disi birakilmayinca
temel sinif icindeki metot kullanilir. */

using System;

class Base {
// Temel sinif icinde sanal metot olustur.
public virtual void who() {
Console.WriteLine(who() in Base);
}
}

class Derived1 : Base {
// who()yu turetilmis sinif icinden devre disi birak.
public override void who() {
Console.WriteLine(who() in Derived1);
}
}

class Derived2 : Base {
BLM 11: KALITIM

HERKES N C#
319
// Bu sinif who()yu devre disi birakmaz.
}

class NoOverrideDemo {
public static void Main() {
Base baseOb = new Base();
Derived1 dOb1 = new Derived1();
Derived2 d0b2 = new Derived2();

Base baseRef; // bir temel sinif referansi

baseRef = baseOb;
baseRef.who();

baseRef = dOb1;
baseRef.who();

baseRef = dOb2;
baseRef.who(); // Basedeki who()yu cagir
}
}
Bu programdan ekle edilen kt aada gsterilmitir:
who() in Base
who() in Derived1
who() in Base
Bu rnekte Derived2, who()yu devre d brakmaz. Bylece who(), Derived2
nesnesi zerinde arld zaman Base iindeki who() altrlr.
ok katmanl bir hiyerari sz konusu olduunda, eer bir tretilmi snf bir sanal metodu
devre d brakmyorsa, bu durumda hiyerarinin yukarlarna doru ilerlenir ve metodun ilk
kez devre d brakld yerdeki metot altrlr. rnein;
/* Cok katmanli bir hiyerarside,
hiyerarsinin yukarilarina dogru ilerlerken
devre disi birakilan ilk sanal metot
calistirilacak olan metottur. */

using System;

class Base {
// Temel sinif icinde bir sanal metot olustur.
public virtual void who() {
Console.WriteLine(who() in Base);
}
}

class Derived1 : Base {
// who()yu turetilmis sinif icinden devre disi birak.
public override void who() {
Console.WriteLine(who() in Derived1);
}

HERKES N C#
KISIM I C# DL

320
}

class Derived2 : Derived1 {
// Bu sinif da who()yu devre disi birakmiyor.
}

class Derived3 : Derived2 {
// Bu sinif who()yu devre disi birakmiyor.
}

class NoOverrideDemo2 {
public static void Main() {
Derived3 dOb = new Derived3();

Base baseRef; // bir temel sinif referansi

baseRef = dOb;
baseRef.who(); // Derived1in icindeki who()yu cagir
}
}
kt u ekildedir:
who() in Derived1
Bu rnekte Base kaltm yoluyla Derived1e, Derived1 kaltm yoluyla Derived2ye,
Derived2 ise kaltm yoluyla Derived3e aktarlr. ktnn da dorulad gibi who(),
Derived3 veya Derived2 tarafndan devre d braklmad iin who()nun altrlan
versiyonu Derived1 iinde who()yu devre d brakan versiyondur, nk who()nun
rastlanan ilk versiyonu budur.
Bir dier husus: zellikler de virtual anahtar kelimesi ile deitirilebilir ve override
kullanlarak devre d braklabilirler.

Devre D Braklan Metotlara Neden Gerek Var?
Devre d braklan metotlar, C#n alma zamannda gerekli olan ok biimlilii
desteklemesine olanak tanr. ok biimlilik nesne ynelimli programlama iin gereklidir,
nk ok biimlilik bir yandan bir genel snfn tm trevlerinde ortak olacak metotlar belirt-
meye olanak tanrken, te yandan tretilmi snflara da bu metotlarn bir ksmnn ya da tm-
nn spesifik uygulamalarn tanmlamalarna imkan verir. Devre d braklan metotlar, C#n
tek arayz, ok metot ok biimlilik zelliini uygulamann bir baka yoludur.
ok biimlilii baaryla uygulamann anahtar bir lde, temel ve tretilmi snflarn
hiyerari iinde daha az uzmanlk alanndan daha youn uzmanlk alanna doru ilerlediini
kavramaktr. Doru kullanldnda bir temel snf, tretilmi snfn direkt olarak
kullanabilecei elerin tmn salar. Ayrca, tretilmi snfn kendi bana uygulamas
gereken metotlar da tanmlar. Bu, tretilmi snfa kendi metotlarn tanmlama esneklii
BLM 11: KALITIM

HERKES N C#
321
sunarken, ayn zamanda tutarl bir arayz de mecbur klmay srdrr. Bylece, kaltm devre
d braklan metotlarla birletirerek bir temel snf, tm tretilmi snflar tarafndan
kullanlacak olan metotlarn genel yapsn tanmlayabilir.
Sanal Metotlar Uygulamak
Sanal metotlarn gcn daha iyi kavramak iin bu metotlar TwoDShape snfna
uygulayacaz. nceki rneklerde, TwoDShapeten tretilen her snf, area() adnda bir
metot tanmlamaktayd. Bu kullanm bize bir fikir verir: area()y TwoDShape snfnn bir
sanal metodu yapmak ok daha iyi olabilir. Bu sayede, tretilmi snflarn her biri area()y
devre d brakabilir ve snf iinde belirtilen eklin alannn nasl hesaplandn da
tanmlayabilir. Aadaki program bunu gerekletirir. Kolaylk salamak iin TwoDShapee
ayrca bir de isim zellii eklenmektedir. (Bu, snflar gstermeyi kolaylatrr.)
// Sanal metotlar ve cokbicimlilik kullanir.

using System;

class TwoDShape {
double pri_width; // private
double pri_height; // private
string pri_name; // private

// Varsayilan yapilandirici.
public TwoDShape() {
width = height = 0.0;
name = null;
}

// Parametreli yapilandirici
public TwoDShape(double w, double h, string n) {
width = w;
height = h;
name = n;
}

// Esit width ve height degerine sahip bir nesne yapilandir.
public TwoDShape(double x, string n) {
width = height = x;
name = n;
}

// Bir nesneden bir baska nesne yapilandir.
public TwoDShape(TwoDShape ob) {
width = ob.width;
height = ob.height;
name = ob.name;
}

// width, height ve name icin ozellikler
public double width {

HERKES N C#
KISIM I C# DL

322
get { return pri_width; }
set { pri_width = value; }
}

public double height {
get { return pri_height; }
set { pri height = value; }
}

public string name {
get { return pri_name; }
set { pri_name = value; }
}

public void showDim() {
Console.WriteLine(Width and height are + width +
and + height);
}

public virtual double area() {
Console.WriteLine(area() must be overridden);
return 0.0;
}
}

// Ucgenler icin TwoDShapeten turetilen bir sinif.
class Triangle : TwoDShape {
string style; // ozel

// Varsayilan yapilandirici.
public Triangle() {
style = null;
}

// Triangle icin yapilandirici.
public Triangle(string s, double w, double h) :
base(w, h, triangle) {
style = s;
}

// ikizkenar bir ucgen yapilandir.
public Triangle(double x) : base(x, triangle) {
style = isosceles;
}

// Bir nesneden baska bir nesne yapilandir.
public Triangle(Triangle ob) : base(ob) {
style = ob.style;
}

// Triangle icin area()yi devre disi birak.
public override double area() {
return width * height / 2;
}

BLM 11: KALITIM

HERKES N C#
323
// Ucgenin seklini goster.
public void showStyle() {
Console.WriteLine(Triangle is + style);
}
}

// Dikdortgenler icin TwoDShapeten turetilmis bir sinif.
class Rectangle : TwoDShape {
// Rectangle icin yapilandirici.
public Rectangle(double w, double h) :
base(w, h, rectangle}{ }

// Bir kare yapilandir.
public Rectangle(double x) : base(x, rectangle) { }

// Bir nesneden bir baska nesne yapilandir.
public Rectangle(Rectangle ob) : base(ob) { }

// Dikdortgen bir kareyse true dondur.
public bool isSquare() {
if(width == height) return true;
return false;
}

// Rectangle icin area()yi devre disi birak.
public override double area() {
return width * height;
}
}

class DynShapes {
public static void Main() {
TwoDShape[] shapes = new TwoDShape[5];

shapes[0] = new Triangle(right, 8.0, 12.0);
shapes[1] = new Rectangle(10);
shapes[2] = new Rectangle(10, 4);
shapes[3] = new.Triangle(7.0);
shapes[4] = new TwoDShape(10, 20, generic);

for(int i = 0; i < shapes.Length; i++) {
Console.WriteLine(object is + shapes[i].name);
Console.WriteLine(Area is + shapes[i].area());

Console.WriteLine();
}
}
}
Programn kts aadaki gibidir:
object is triangle
Area is 48

object is rectangle

HERKES N C#
KISIM I C# DL

324
Area is 100

object is rectangle
Area is 40

object is triangle
Area is 24.5

object is generic
area() must be overridden
Area is 0
Gelin, bu program yakndan inceleyelim. ncelikle, daha nce akland gibi, area()
metodu TwoDShape iinde virtual olarak deklare edilir ve Triangle ve Rectangle
tarafndan devre d braklr. TwoDShape iinde area(), kullancya bu metodun bir
tretilmi snf tarafndan devre d braklmas gerektii bilgisini veren bir yer tutucu grevini
grr. area()nn her devre d braklnda tretilmi snf iine paketlenmi nesnenin tipine
uygun bir uygulama gerekletirilir. Yani, rnein bir elips snfn uyguluyor olsaydnz,
area() elipsin alann hesaplamak durumunda olurdu.
Yukardaki programda bir baka nemli zellik daha mevcuttur. Dikkat ederseniz, Main()
iinde shapes, TwoDShape nesnelerinden oluan bir dizi olarak deklare edilir. Ancak, bu
dizinin elemanlarna Triangle, Rectangle ve TwoDShape referanslar atanr. Bu geerli bir
kullanmdr, nk bir temel snf referans bir tretilmi snf nesnesine referansta bulunabilir.
Program daha sonra dizi zerinde ilerler ve nesnelerin her biriyle ilgili bilgileri ekranda
gsterir. Olduka basit olmasna karn bu program, hem kaltmn, hem de metotlar devre d
brakma zelliinin gcn ortaya koyar. Temel snf referans deikeninde saklanan nesnenin
tipi, programn almas srasnda belirlenir ve buna gre hareket edilir.
Eer TwoDShapeten bir nesne tretilmise, bu nesnenin alan area() arlarak elde
edilebilir. Ne tr bir ekil kullanlrsa kullanlsn bu ilemin arayz ayndr.

zet Snflarn Kullanm
Bazen, yle bir temel snf oluturmak istersiniz: O snf sadece kendisinden tretilmi
snflarn genelletirilmi bir ekli olmal, detaylar her bir tretilmi snf tarafndan
doldurulmaldr. Bu tr bir snf, tretilmi snflarn uygulamalar gereken metotlarn zn
belirler, fakat bu metotlardan biri ya da daha fazlas iin kendisi bir uygulama salamaz. Temel
snf, anlaml bir metot uygulamas oluturamad zaman byle bir durumla karlalabilir.
TwoDShapein yukardaki rnekte kullanlan versiyonunda bu tr bir durum sz konusudur.
area()nn tanm yalnzca bir yer belirteci olmaktan ibarettir. area(), hibir nesne tipinin
alann hesaplayp, ekranda gstermez.
Kendi snf ktphanelerinizi oluturduka greceksiniz ki, bir metodun kendi temel snf
kapsamnda anlaml bir tanmnn olmamas yaygn bir kullanm deildir. Bu durumu iki
BLM 11: KALITIM

HERKES N C#
325
ekilde kontrol altna alabilirsiniz. Birincisi, nceki rnekte gsterildii gibi, metodun bir uyar
mesaj vermesi yeterlidir. Bu yntem belirli durumlarda -rnein, hata ayklama srasnda-
yararl olsa da, bu yntemi kullanmak genellikle uygun deildir. Tretilmi snfn bir anlam
tamas iin tretilmi snf tarafndan devre d braklmas gereken metotlara sahip
olabilirsiniz. Triangle snfn ele aln. area() tanmlanmazsa bu snfn bir anlam kalmaz.
Bu durumda, tretilmi snfn gerekten gerekli metotlarn tmn devre d brakmasn
garanti edecek bir zme ihtiyacnz olur. Bu probleme C#n getirdii zm zet metot
kullanmdr.
zet metot abstract tip niteleyicisi kullanlarak oluturulur. zet metodun gvdesi
yoktur; bu nedenle, zet metotlar temel snf tarafndan gereklenmez. Yani, tretilmi snf,
zet snf devre d brakmaldr, temel snf iinde tanmlanm olan versiyonunu kullanamaz.
Byk olaslkla siz de tahmin etmisinizdir; zet metotlar otomatik olarak sanaldr ve
virtual niteleyicisini kullanmaya gerek yoktur. Aslnda, virtual ve abstract
niteleyicilerini birlikte kullanmak hataldr.
zet metotlar deklare etmek iin aadaki genel yapy kullann:
abstract tip isim(parametre-listesi);
Grdnz gibi, metot gvdesi mevcut deildir. abstract niteleyicisi yalnzca normal
metotlarla kullanlabilir. static metotlara uygulanamaz. zellikler de zet olabilir.
Bir veya daha fazla zet metot ieren bir snf da zet olarak deklare edilmelidir. Bunun
iin class deklarasyonundan nce abstract belirleyicisini kullanmalsnz. zet bir snf
komple bir uygulama tanmlamadndan dolay, zet bir snfa ait nesneler mevcut olamaz.
Bylece, new kullanlarak zet bir snfa ait bir nesne oluturmaya almak derleme srasnda
hatayla karlamaya neden olur.
Bir zet snf kaltm yoluyla bir tretilmi snfa aktarlnca, sz konusu tretilmi snf
temel snf iinde yer alan zet metotlarn tmn uygulamak zorundadr. Eger uygulamazsa,
tretilmi snf da ayrca abstract olarak belirtilmelidir. Bylece; abstract nitelii, zet
metotlarn tm tamamen uygulanana kadar kaltm yoluyla aktarlr.
zet snf kullanarak TwoDShape snfn gelitirebilirsiniz. Tanmlanmam iki boyutlu
bir eklin alann ifade etmek iin, anlaml bir kavram mevcut deildir. Bu nedenle, nceki
programn aadaki versiyonunda area(), TwoDShape iinde abstract olarak deklare
edilmektedir. TwoDshape de abstract olarak deklare edilir. Bu, kukusuz, TwoDShapeten
tretilen tm snflarn area()y devre d brakmas gerektii anlamna gelmektedir.
// Ozet bir sinif olustur.

using System;

abstract class TwoDShape {
double pri_width; // private
double pri_height; // private

HERKES N C#
KISIM I C# DL

326
string pri_name; // private

// Varsayilan yapilandirici.
public TwoDShape() {
width = height = 0.0;
name = null;
}

// Parametreli yapilandirici.
public TwoDShape(double w, double h, string n) {
width = w;
height = h;
name = n;
}

// Esit width ve height degerlerine sahip bir nesne yapilandir.
public TwoDShape(double x, string n) {
width = height = x;
name = n;
}

// Bir nesneden baska bir nesne yapilandir.
public TwoDShape(TwoDShape ob) {
width = ob.width;
height = ob.height;
name = ob.name;
}

// width, height ve name icin ozellikler.
public double width {
get { return pri_width; }
set { pri_width = value; }
}

public double height {
get { return pri_height; }
set { pri height = value; }
}

public string name {
get { return pri_name; }
set { pri_name = value; }
}

public void showDim() {
Console.WriteLine(Width and height are + width +
and + height);
}

// Artik area() ozettir.
public abstract double area();
}

// Ucgenler icin TwoDShapeten turetilen bir sinif.
class Triangle : TwoDShape {
BLM 11: KALITIM

HERKES N C#
327
string style; // ozel

// Varsayilan yapilandirici.
public Triangle() {
style = null;
}

// Triangle icin yapilandirici.
public Triangle(string s, double w, double h) :
base(w, h, triangle) {
style = s;
}

// Bir ikizkenar ucgen yapilandir.
public Triangle(double x) : base(x, triangle) {
style = isosceles;
}

// Bir nesneden baska bir nesne yapilandir.
public Triangle(Triangle ob) : base(ob) {
style = ob.style;
}

// Triangle icin area()yi devre disi birak.
public override double area() {
return width * height / 2;
}

// Ucgenin seklini goster.
public void showStyle() {
Console.WriteLine(Triangle is + style);
}
}

// Dortgenler icin TwoDShapeten turetilen bir sinif.
class Rectangle : TwoDShape {
// Rectangle icin yapilandirici.
public Rectangle(douhle w, double h) :
base(w, h, rectangle){ }

// Bir kare yapilandir.
public Rectangle(double x) : base(x, rectangle) { }

// Bir nesneden baska bir nesne yapilandir.
public Rectangle(Rectangle ob) : base(ob) { }

// Dikdortgen kare ise true dondur.
public bool isSquare() {
if(width == height) return true;
return false;
}

// Rectangle icin area()yi devre disi birak.
public override double area() {
return width * height;

HERKES N C#
KISIM I C# DL

328
}
}

class AbsShape {
public static void Main() {
TwoDShape[] shapes = new TwoDShape[4];

shapes[0] = new Triangle(right, 8.0, 12.0);
shapes[1] = new Rectangle(10);
shapes[2] = new Rectangle(10, 4);
shapes[3] = new Triangle(7.0);

for(int i = 0; i < shapes.Length; i++) {
Console.WriteLine(object is + shapes[i].name);
Console.WriteLine(Area is + shapes[i].area());

Console.WriteLine();
}
}
}
Programdan grld zere, tm tretilmi snflarn area()y devre d brakmalar
gerekmektedir (veya abstract olarak da deklare edilebilirler). Bunu kendi kendinize
ispatlamanz iin area()y devre d brakmayan bir tretilmi snf oluturmay deneyin. Bu
durumda derleyici hatas ile karlarsnz. Elbette, TwoDShape tipinde bir nesne referans
oluturmak hala mmkndr. Programda da byle yaplmtr. Ancak, TwoDShape tipinde
nesne deklare etmek artk mmkn deildir. Bundan dolay, Main()de shapes dizisi 4
elemandan oluacak ekilde ksaltlmtr ve genel bir TwoDShape nesnesi artk oluturulmaz.
Bir dier husus: Buna ramen TwoDShapein iinde showDim() metodunun yer aldna
ve abstract ile nitelenmediine dikkat edin. Bir zet snf, tretilmi bir snfn olduu gibi
kullanmakta serbest olduu somut metotlar ierebilir. Bu, tamamen kabul edilebilir, hatta,
olduka da yaygn bir kullanmdr. Yalnzca abstract olarak deklare edilen snflar tretilmi
snflar tarafndan devre d braklmaldr.
Kaltm nlemek in sealed Kullanmak
Kaltm her ne kadar gl ve kullanl olsa da kimi zaman bunu nlemek isteyeceksiniz.
rnein, zelletirilmi bir donanm aygtnn, soz gelii bir tbbi monitrn ilk kullanma
hazrlanmas ile ilgili admlar bir araya getiren bir snfnz olabilir. Byle bir durumda,
snfnz kullanan kullanclarn monitrn ilk kullanma hazrlanma eklini
deitirebilmelerini istemezsiniz. Bu, aygtn byk olaslkla hatal olarak hazrlanmasna
neden olacaktr. Sebep ne olursa olsun C#ta sealed anahtar kelimesi kullanlarak bir snfn
kaltm yoluyla aktarlmas kolaylkla nlenir.
Bir snfn kaltm yoluyla aktarlmasn nlemek iin sz konusu snfn deklarasyonunun
nne sealed anahtar kelimesini yerletirmelisiniz. Tahmin edebileceiniz gibi, bir snf hem
BLM 11: KALITIM

HERKES N C#
329
abstract hem de sealed olarak deklare etmek kurallara aykrdr; nk zet snf kendi
bana tam deildir, tam olarak uygulanabilmek iin kendisinden tretilen snflara gvenir.
te, bir sealed snf rnei:
sealed class A {
// ...
}

// Asagidaki sinif kurallara aykiridir.
class B : A { // HATA! A sinifindan bir sinif turetemezsiniz.
// ...
}
Aklamalarda da ifade edildii gibi, Ann kaltm yoluyla Bye aktarlmas kurallara
aykrdr, nk A, sealed olarak deklare edilmitir.
object Snf
C#ta object olarak adlandrlan zel bir snf tanmldr. object, tm dier snflar ve
tm dier tipler (deer tipleri de dahil olmak zere) iin kapal bir temel snf grevini grr.
Bir baka deyile, tm dier tipler objectten tretilir. Bu, object tipindeki bir referans
deikeninin dier herhangi tipteki bir nesneye referansta bulunabilmesi anlamna gelir. Ayrca,
diziler de snf olarak gereklendikleri iin, object tipindeki bir deiken herhangi bir diziye
de referansta bulunabilir. Teknik olarak, C#taki object ismi aslnda .NET Framework snf
ktphanesinin bir paras olan System.Object iin verilen bir baka isimdir.
object snf Tablo 11.1de gsterilen metotlar tanmlar. Yani, bu metotlar her nesne iin
kullanma hazrdr.
Bu metotlardan birkan biraz daha aklamak gereklidir. Equals(object) metodu,
kendisini aran nesnenin, ona aktarlan argmanla ayn nesneye referansta bulunup
bulunmadn saptar. (Bir baka ifade ile, iki referansn ayn olup olmadn kontrol eder.) Bu
metodu, kendi oluturduunuz snflarda devre d brakabilirsiniz. Bu sayede, eitliin bir
snfta ne anlama geldiini kendinize gre tanmlama olana bulursunuz. rnein,
Equals(object)i, iki nesneyi ierik bakmndan karlatracak biimde tanmlayabilirsiniz.
Equals(object,object) metodu, sonucu hesaplamak iin Equals(object)i kullanr.
GetHashCode() metodu, aran nesneyle ilikili hash kodunu dndrr. Bu kod,
depolanm nesnelere erimek iin hashing ynteminden yararlanan herhangi bir algoritma
tarafndan kullanlabilir.
Blm 9da bahsedildii gibi, == operatrn ar yklerseniz, Equals(object) ve
GetHashCode()u devre d brakmanz gerekecektir, nk ou zaman == operatr ile
Equals(object)in ayn sonucu vermesini isteyeceksinizdir. Equals() devre d
brakldnda iki metodun uyumlu olabilmesi iin GetHashCode()un da devre d
braklmas gerekir.

HERKES N C#
KISIM I C# DL

330
TABLO 11.1: Object Snfnn Metotlar


Metot Ama
public virtual bool Equals(object ob)
Metodu aran nesne ile ob tarafndan
referansta bulunan nesnenin ayn olup
olmadn belirler.
public static bool Equals(object ob1,
object ob2)
ob1in ob2 ile ayn olup olmadn
belirler.
protected Finalize() Anlamsz verilerin toplanmas ileminden
nce tm faaliyetleri sonlandrr. C#ta
Finalize() bir yok edici araclyla
eriilir.
public virtual int GetHashCode() Metodu aran nesne ile ilikili hash
kodunu dndrr.
public Type GetType() Programn almas srasnda bir nesnenin
tipini elde eder.
protected object MemberwiseClone() Nesnenin s kopyasn oluturur. (yeler
kopyalanr ama yelerin referansta
bulunduu nesneler kopyalanmaz.)
public static bool ReferenceEquals(object
ob1, object ob2)
ob1 ve ob2nin ayn olup olmadn
belirler.
public virtual string ToString() Nesneyi tarif eden bir karakter katar
dndrr.

ToString() metodu, zerinden arld nesnenin tanmn ieren bir karakter katar
dndrr. Bu metot ayn zamanda, bir nesne WriteLine() ile yazldnda da otomatik olarak
arlr. Pek ok snf, bu metodu devre d brakr. Bu sayede, bir snf, oluturduklar nesne
tiplerine spesifik olarak uydurma olana bulurlar. rnein:
// ToString()i tanitir.

using System;

class MyClass {
static int count = 0;
int id;

public MyClass() {
id = count;
count++;
}

public override string ToString() {
return MyClass object # + id;
}
}
BLM 11: KALITIM

HERKES N C#
331

class Test {
public static void Main() {
MyClass ob1 = new MyClass();
MyClass ob2 = new MyClass();
MyClass ob3 = new MyClass();

Console.WriteLine(ob1);
Console.WriteLine(ob2);
Console.WriteLine(ob3);
}
}
Programn kls u ekildedir:
MyClass object #0
MyClass object #1
MyClass object #2
Kutulama ve Kutudan karma
Daha nce de akladmz gibi; deer tipleri de dahil olmak zere tm C# tipleri
objectten tretilirler. Bu nedenle, object tipine yaplan bir referans, deer tipleri dahil
olmak zere tm tiplere referansta bulunmak zere kullanlabilir. Bir object referans bir
deer tipine referansta bulunduunda kutulama (boxing) denilen bir sre iler. Kutulama, bir
deer tipinin deerinin bir nesne rneinde depolanmasna neden olur. Dolaysyla, bir deer
tipi bir nesnenin iine kutulanr. Bu nesne, dier herhangi bir nesne gibi kullanlabilir.
Kutulama her zaman otomatik olarak yaplr. Sizin tek yapmanz gereken bir object
referansna bir deer atamaktr. Gerisini C# halleder.
Kutudan karma (unboxing) ise bir nesneden bir deer okuma ilemidir. Bu ilem,
object referansndan istenen deer tipine bir tip atamas kullanlarak gerekletirilir.
Kutulama ve kutudan karma ilemlerini gsteren bir rnek aada verilmitir.
// Basit bir kutulama/kutudan cikarma ornegi.

using System;

class BoxinqDemo {
public static void Main() {
int x;
object obj;

x = 10;
obj = x; // xi bir nesneye kutula

int y = (int)obj; // obji kutudan cikararak bir inte ata
Console.WriteLine(y);
}
}

HERKES N C#
KISIM I C# DL

332
Bu program, 10 deerini ekrana getirir. Dikkat ederseniz, x deeri sadece onu bir object
referans olan obja atayarak kutulanmtr, objdan inte tip atamas kullanlarak objdaki
tamsay deer geri alnmtr.
Gelin imdi de kutulamann bir dier ve daha ilgin rneine bakalm. Bu rnekte int, bir
object parametresi kullanan sqr() metoduna argman olarak aktarlmaktadr.
//Kutulama, deger aktarilirken de meydana gelir.

using System;

class BoxingDemo {
public static void Main() {
int x;

x = 10;
Console.WriteLine(Here is x: + x);

// X, sqr()e aktarildiginda otomatik olarak kutulanir.
x = BoxingDemo.sqr(x);
Console.WriteLine(Here is x squared: + x);
}

static int sqr(object o) {
return (int)o * (int)o;
}
}
Programn kts aadadr:
Here is x: 10
Here is x squared: 100
Burada xin deeri sqr()e aktarldnda otomatik olarak kutulanmaktadr.
Kutulama ve kutudan karma ilemleri, C#n tip sisteminin tmyle tek standarda uyma-
sn salar. Tm tipler objectten tretilir. Herhangi bir tipe yaplacak bir referansa bir
object referans atanabilir. Kutulama/kutudan karma, bu iin deer tipleriyle ilgili ksmn
otomatik olarak halleder. Daha da tesi, tm tipler objectten tretildikleri iin, tiplerin tm
objectin metotlarna eriebilir. rnein, aada verdiimiz biraz artc programa bakalm:
// Kutulama, metotlari bir deger uzerinden cagirmaya olanak verir!

using System;

class MethOnValue {
public static void Main() {
Console.WriteLine(10.ToString());
}
}
BLM 11: KALITIM

HERKES N C#
333
Bu program, 10 deerini ekrana getirir, nk ToString() metodu, zerinden arld
nesnenin karakter katar cinsinden ifade edilmi biimini dndrr. Bu durumda 10un karakter
cinsinden ifadesi 10dur.
object Genel Bir Veri Tipi midir?
object tm dier tiplerin temel snf olduu ve kutulama/kutudan karma ilemleri
deer tipleri iin otomatik olarak iledii iin, objecti genel bir veri tipi olarak kullanmak
mmkndr. rnek olarak, bir object dizisi oluturan ve eitli dier tiplerden verileri bu
dizinin elemanlarna atayan aadaki program inceleyelim:
// Genel bir dizi olusturmak icin objectin kullanimi.

using System;

class GenericDemo {
public static void Main() {
object[] ga = new object[10];

// intleri depola
for(int i = 0; i 3; i++)
ga[i] = i;

// doublelari depola
for(int i = 3; i 6; i++)
ga[i] = (double) i / 2;

// iki string, bir bool bir de char depola
ga[6] = Generic Array;
ga[7] = true;
ga[8] = X;
ga[9] = end;

for(int i = 0; i ga.Length; i++)
Console.WriteLine(ga[ + i + ]: + ga[i] + );
}
}
Programn kts yledir:
ga[0]: 0
ga[1]: 1
ga[2]: 2
ga[3]: 1.5
ga[4]: 2
ga[5]: 2.5
ga(6]: Generic Array
ga[7]: True
ga[8]: X
ga[9]: end

HERKES N C#
KISIM I C# DL

334
Bu programdan grld zere, bir object referansn herhangi bir veri tipine referansta
bulunmak iin kullanmak mmkndr. Dolaysyla, bu programn kulland trden bir
object dizisine herhangi bir veri trnden deer atanabilir. Bu, object dizisinin esasen genel
bir liste olduu anlamna gelir. Kavram geniletirsek, rnein, object referanslarnn
tutulduu bir yn snf oluturmann ne kadar kolay olduu anlalr. Bu sayede ynda her
trl veri tipinden eleman tutulabilir.
objectin genel tip olmas gl bir zelliktir ve baz durumlarda gayet etkin biimde
kullanlabilir. Ancak objecti C#n dier durumlarda gl olan tip kontrollerini amann bir
yolu olarak grmeniz hata olur. Genel olarak, bir int tutmanz gerekiyorsa, bir int deikeni
kullann. Karakter katar depolamak iin bir string referansndan yararlann. Dier tipler iin
de benzer ekilde davrann. objectin genel olma niteliini sadece zel durumlarda kullann.



O N K N C B L M

ARAYZLER, YAPILAR VE
NUMARALANDIRMALAR





















12

HERKES N C#
KISIM I C# DL

336
Bu blmde C#n en nemli zelliklerinden biri olan arayzler ele alnmaktadr. Arayz,
(interface) bir snf tarafndan uygulanacak olan bir grup metodu tanmlar. Arayzn kendisi
herhangi bir metodu uygulamaz. Yani; arayz, uygulamay gerekli klmadan ilevsellii tarif
eden tamamen mantksal bir zelliktir.
Ayrca, C#n iki veri tipi daha bu blmde ele alnmaktadr: Yaplar ve
numaralandrmalar. Yap (structure), snfa benzer. Tek fark yaplarn referans tipi yerine deer
tipi olarak ele alnmasdr. Numaralandrmalar (enumerations), isimlendirilmi tamsay
sabitlerden oluan listelerdir. Yaplar ve numaralandrmalar, C#n programlama ortamnn
zenginliine katkda bulunurlar.
Arayzler
Nesne ynelimli programlamada bir snfn ne yapmas gerektiini tanmlamak, fakat bunu
nasl yapacan tanmlamamak kimi zaman yararl olabilir. Bunun bir rneini grmtnz:
zet metot. zet metot, bir metot iin bir imza tanmlar, ama sz konusu metodun nasl
uygulanacan tarif etmez. Tretilmi metot, kendi temel snf tarafndan tanmlanan zet me-
totlarn her biri iin kendi uygulamasn salamaldr. Bylece; zet metot, metot iin gerekli
arayz belirtirken metodun nasl uygulanacann hakknda bilgi vermez. zet snflar ve
metotlar kullanl olmakla birlikte, bu kavram bir adm daha ileriye tamak mmkndr.
C#ta interface anahtar kelimesini kullanarak bir snfn arayz ile uygulamasn
birbirinden tamamen ayrabilirsiniz.
Arayzler sz dizimsel olarak zet snflara benzerler. Ancak, bir arayz iindeki
metotlarn hibirinin gvdesi yoktur. Yani, bir arayz hi bir ekilde bir uygulama salamaz.
Arayz, ne yaplmas gerektiini belirtir ama, nasl yaplacan belirtmez, Arayz bir kez
tanmlandktan sonra, herhangi bir sayda snf bunu uygulayabilir. Ayrca, bir snf da herhangi
bir sayda arayz uygulayabilir.
Bir smf, bir arayz uygulamak amacyla, arayz tarafndan tarif edilen metotlar iin
gvdeler (uygulamalar) salamaldr. Her snf kendi uygulamas ile ilgili ayrntlar
belirlemekte zgrdr. Bylece, iki snf ayn metot grubunu destekliyor olmalarna ramen,
ayn arayz farkl yollardan uygulayabilir. Bu yzden, arayz hakknda bilgi sahibi olan kod,
her iki snfn nesnelerini de kullanabilir, nk bu nesneler iin arayz ayndr. Arayz
kavramn salamakla C#, ok biimliliin tek arayz, birden fazla metot zelliinden tam
olarak yararlanmanza olanak tanr.
Arayzler interface anahtar kelimesi kullanlarak deklare edilirler. Arayz
deklarasyonunun sadeletirilmi bir versiyonu u ekildedir:
interface isim {
dn-tipi metot-ismi1(param-listesi);
dn-tipi metot-ismi2(param-listesi);
// ...
dn-tipi metot-ismiN(param-listesi);
}
BLM 12: ARAYZLER, YAPILAR VE NUMARALANDIRMALAR

HERKES N C#
337
Arayzn ismi isim ile belirtilir. Metotlar yalnzca dn tipleri ve imzalar kullanlarak
deklare edilirler. Bunlar zellikle zet metotlardr. Daha nce akland gibi, bir interface
iindeki metotlarn hibiri bir uygulama iermez. Bylece, bir interface ieren snflarn her
biri metotlarn tmn uygulamaldr. Bir arayz iindeki metotlar kapal olarak publictir;
aka bir eriim belirleyicisinin kullanlmasna izin verilmez.
te bir interface rnei. Bu rnekte, bir say serisi reten bir snfa bir arayz
belirtilmektedir.
public interface ISeries {
int getNext(); // seri icindeki bir sonraki sayiyi dondur
void reset(); // yeniden basla
void setStart(int x); // baslangic degerini ayarla
}
Bu arayzn ad Iseriestir. I neki gerekli olmasa da, programclarn birou
arayzleri snflardan ayrmak iin arayzleri nekli olarak kullanrlar. Iseries, public
olarak deklare edilmektedir, bylece herhangi bir program iindeki herhangi bir snf tarafndan
uygulanabilecektir.
Metot imzalarna ek olarak arayzler; zellikler, indeksleyiciler ve olaylar iin de imza
deklare edebilirler. Olaylar Blm 15te anlatlacaktr; bu blmde yalnzca metotlar, zellikler
ve indeksleyicilerle ilgileneceiz. Arayzler, veri yeleri ieremezler. Ayrca, yaplandrc,
yok edici veya operatr metotlarn da tanmlayamazlar. stelik, yelerinin hibiri static
olarak deklare edilemez.
Arayzleri Uygulamak
Bir interface bir kez tanmlandktan sonra, bir ya da daha fazla snf bu arayz
uygulayabilir. Bir arayz uygulamak iin snf isminden sonra, aynen temel snf belirtilir gibi
arayzn ismi belirtilir. Bir arayz uygulayan bir snfn genel ekli aadaki gibidir:
class snf-ismi : arayz-ismi {
// snf gvdesi
}
Uygulanmakta olan arayzn ismi, arayz-ismi iinde belirtilmektedir.
Bir snf bir arayz uygularken arayzn btnn uygulamaldr. rnein, hangi
ksmlarn uygulanacan seip alamaz.
Snflarda birden fazla arayz uygulanabilir. Birden fazla arayz uygulamak iin, arayzler
virgl ile birbirinden ayrlr. Temel snf kaltm yoluyla bir snfa aktarlabilir ve sz konusu
snf da bir veya daha fazla arayz uygulayabilir. Bu durumda, temel snfn ismi virgl ile
ayrlan listenin en banda yer almaldr.
Bir arayz uygulayan metotlar, public olarak deklare edilmelidir. Bunun nedeni udur:
Bir arayz iindeki metotlar kapal olarak publictir; bundan dolay, bu metotlarn

HERKES N C#
KISIM I C# DL

338
uygulamalar da public olmaldr. Ayrca, uygulamay gerekletirmekte olan metodun tip
imzas da arayzn tanmnda belirtilen tip imzas ile birebir elenmelidir.
te, daha nce gsterilen ISeries arayznn uyguland bir rnek. Bu programda
ByTwos adnda bir snf oluturulmaktadr. ByTwos, her biri bir ncekinden iki byk deere
sahip bir say serisi retir.
// Iseries uygulanir.
class ByTwos : ISeries {
int start;
int val;

public ByTwos() {
start = 0;
val = 0;
}

public int getNext() {
val += 2;
return val;
}

public void reset() {
val = start;
}

public void setStart(int x) {
start = x;
val = start;
}
}
Grdnz gibi; ByTwos, ISeries tarafndan tanmlanan metodu da uygular.
nceden akland zere, bu gereklidir. nk bir snf, bir arayz ksmen uygulayamaz.
te. ByTwosu gsteren bir snf:
// ByTwos arayuzunu goster.

using System;

class SeriesDemo {
public static void Main() {
ByTwos ob = new ByTwos();

for(int i = 0; i < 5; i++)
Console.WriteLine(Next value is + ob.getNext());

Console.WriteLine(\nResetting);
ob.reset();
for(int i = 0; i < 5; i++)
Console.WriteLine(Next value is + ob.getNext());

Console.WriteLine(\nStarting at 100);
BLM 12: ARAYZLER, YAPILAR VE NUMARALANDIRMALAR

HERKES N C#
339
ob.setStart(100);
for (int i = 0; i < 5; i++)
Console.WriteLine(Next value is + ob.getNext());
}
}
SeriesDemoyu derlemek iin ISeries, ByTwos ve SeriesDemoyu ieren dosyalar
derlemeye dahil etmelisiniz. Derleyici, altrlabilir nihai dosyay oluturmak iin bu
dosyay otomatik olarak derleyecektir. Sz gelii, bu dosyalara Iseries.cs, ByTwos.cs ve
SeriesDemo.cs isimlerini vermiseniz, aadaki komut satr sorunsuz derlenecektir:
csc SeriesDemo.cs ISeries.cs ByTwos.cs
Visual Studio IDEyi kullanyorsanz, bu dosyann tmn C# projenizin iine eklemek
yeterlidir. Bir dier husus da udur: Bu snf ayn dosya iine koymak da tamamen geerli
bir yntemdir.
Bu programn kts aada gsterilmitir:
Next value is 2
Next value is 4
Next value is 6
Next valua is 8
Next value is 10

Resetting
Next value is 2
Next value is 4
Next value is 6
Next value is 8
Next value is 10

Starting at 100
Next value is 102
Next value is 104
Next value is 106
Next value is 108
Next value is 110
Snflarn kendilerine ait ek yeler tanmlamak iin arayzleri uygulamalar hem izin
verilen hem de yaygn bir yaklamdr. rnein, ByTwosun aadaki versiyonu, nceki deeri
dndren getPrevious() adnda bir metot ekler:
// ISeriesi uygular ve getPrevious() metodunu ekler.
class ByTwos : ISeries {
int start;
int val;
int prev;

public ByTwos() {
start = 0;
val = 0;
prev = -2;

HERKES N C#
KISIM I C# DL

340
}

public int getNext() {
prev = val;
val += 2;
return val;
}

public void reset() {
val = start;
prev = start - 2;
}

public void setStart(int x) {
start = x;
val = start;
prev = val 2;
}

// ISeries tarafindan belirtilmeyen bir metot.
public int getPrevious() {
return prev;
}
}
Dikkat ederseniz, getPrevious() eklemek, ISeries tarafndan tanmlanan metotlarn
uygulamalarnda bir deiiklik yapmay gerektirir. Ancak, bu metotlarn arayz deimeden
kald iin yaplan deiiklik problem karmaz ve nceden mevcut olan kodun kmesine
neden olmaz. Bu, arayzlerin salad avantajlardan biridir.
nceden akland gibi, bir interface herhangi bir sayda snf tarafndan
uygulanabilir. rnein, ite size, bir asal say serisi reten Primes adnda bir snf. Bu
rnekteki ISeries uygulamasnn ByTwos tarafndan salanan uygulamaktan esasen farkl
olduuna dikkat edin.
// Bir asal sayi serisi uygulamak icin ISeries kullanir.
class Primes : ISeries {
int start;
int val;

public Primes() {
start = 2;
val = 2;
}

public int getNext() {
int i, j;
bool isprime;

val++;
for(i = val; i < 1000000; i++) {
isprime = true;
for(j = 2; j < (i/j + 1); j++) {
BLM 12: ARAYZLER, YAPILAR VE NUMARALANDIRMALAR

HERKES N C#
341
if((i%j == 0) {
isprime = false;
break;
}
}
if(isprime) {
val = i;
break;
}
}
return val;
}

public void reset() {
val = start;
}

public void setstart(int x) {
start = x;
val = start;
}
}
Buradaki kilit nokta udur: ByTwos ve Primes tamamen ilgisiz say dizileri retiyor olsa
bile, her ikisi de ISeriesi uygulamaktadr. nceden akland gibi bir arayz, uygulama
hakknda bilgi vermez. Bu yzden her snf, arayz kendi kullanmna uygun bir biimde
uygulamakta serbesttir.
Arayz Referanslarnn Kullanm
Arayz tipinde bir referans deikeni deklare edebildiinizi renince olduka
arabilirsiniz. Bir baka deyile, arayz referans deikeni oluturabilirsiniz. Bu tr bir
deiken kendi arayzn uygulayan herhangi bir nesneye referansta bulunabilir. Bir arayz
referans araclyla, bir nesne zerinden bir metot ardnzda aslnda, sz konusu nesne
tarafndan uygulanan metot arlm olur. Bu sre, Blm 11de anlatlan, tretilmi bir snf
nesnesine erimek iin bir temel snf referans kullanmaya benzer.
Aadaki rnek bir arayz referansnn kullanmn gstermektedir. Bu rnekte, ByTwos
ve Primesn her ikisinin de nesneleri zerinden metot arlar yapmak iin ayn arayz
referans deikeni kullanlmaktadr.
// Arayuz referanslarini gosterir.

using System;

// Arayuzu tanimla.
public interface ISeries {
int getNext(); // serideki bir sonraki sayiyi dondur
void reset(); // yeniden basla
void setStart(int x); // baslangic degerini ayarla
}

HERKES N C#
KISIM I C# DL

342

// Cift sayilar serisi uretmek icin ISeries kullan.
class ByTwos : ISeries {
int start;
int val;

public ByTwos() {
start = 0;
val = 0;
}

public int getNext() {
val += 2;
return val;
}

public void reset() {
val = start;
}

public void setStart(int x) {
start = x;
val = start ;
}
}

// Asal sayilar serisi uretmek icin ISeries kullan.
class Primes : ISeries {
int start;
int val;

public Primes() {
start = 2;
val = 2;
}

public int getNext() {
int i, j;
bool isprime;

val++;
for(i = val; i < 1000000; i++) {
isprime = true;
for(j = 2; j < (i/j + 1); j++) {
if((i%j) == 0) {
isprime = false;
break;
}
}
if(isprime) {
val = i;
break;
}
}
return val;
BLM 12: ARAYZLER, YAPILAR VE NUMARALANDIRMALAR

HERKES N C#
343

}

public void reset() {
val = start;
}

public void setStart(int x) {
start = x;
val = start;
}
}

class SeriesDemo2 {
public static void Main() {
ByTwos twoOb = new ByTwos();
Primes primeOb = new Primes();
ISeries ob;

for(int i = 0; i < 5; i++) {
ob = twoOb;
Console.WriteLine(Next ByTwos value is +
ob.getNext());
ob = primeOb;
Console.WriteLine(Next prime number is +
Ob.getNext());
}
}
}
Program kts aada gsterilmitir:
Next ByTwos value is 2
Next prime number is 3
Next ByTwos value is 4
Next prime number is 5
Next ByTwos value is 6
Next prime number is 7
Next ByTwos value is 8
Next prime number is 11
Next ByTwos value is 10
Next prime number is 13
Main()de ob, ISeries arayzne bir referans olarak deklare edilmektedir. Bunun
anlam udur: ISeriesi uygulayan herhangi bir nesneye atfta bulunan referanslar saklamak
iin ob kullanlabilir. Bu rnekte ob, her ikisi de ISeriesi uygulayan ve srasyla ByTwos ve
Primes tipinde nesneler olan twoOb ve primeOba referansta bulunmak iin kullanlmaktadr.
Bir dier husus: Bir arayz referans deikeni, yalnzca kendi arayz deklarasyonunda
deklare edilen metotlar hakknda bilgi sahibidir. Bu nedenle, sz konusu nesne tarafndan
desteklenme ihtimali olan dier deiken ve metotlara erimek iin arayz referans
kullanlamaz.

HERKES N C#
KISIM I C# DL

344
Arayz zellikleri
Tpk metotlar gibi, zellikler de bir arayz iinde gvdesiz olarak belirtilebilir. zellikler
genel olarak u ekilde belirtilir:
// arayz zellii
tip isim {
get;
set;
}
Kukusuz, salt okunur veya salt yazlr zellikler iin srasyla, yalnzca get veya set
mevcut olacaktr.
ISeries arayznn ve ByTwos snfnn, seri iindeki bir sonraki eleman elde etmek ve
ayarlamak iin bir zellik kullanlarak yeniden yazlm versiyonlar aadaki gibidir:
// Bir arayuz icinde bir ozellik kullan.

using System;

public interface ISeries {
// bir arayuz ozelligi
int next {
get; // seri icindeki bir sonraki sayiyi dondur
set; // bir sonraki sayiyi ayarla
}
}

// ISeriesi uygula.
class ByTwos : ISeries {
int val;

public ByTwos() {
val = 0;
}

// degeri al veya ayarla
public int next {
get {
val += 2;
return val;
}
set {
val = value;
}
}
}

// Bir arayuz ozelligi goster.
class SeriesDemn3 {
public static void Main() {
ByTwos ob = new ByTwos();
BLM 12: ARAYZLER, YAPILAR VE NUMARALANDIRMALAR

HERKES N C#
345

// seriye bir ozellik araciligiyla eris
for(int i = 0; i < 5; i++)
Console.WriteLine(Next value is + ob.next);

Console.WriteLine(\nStarting at 21);
ob.next = 21;
for(int i = 0; i < 5; i++)
Console.WriteLine(Next value is + ob.next);
}
}
Bu programn kts aada gsterilmitir:
Next value is 2
Next value is 4
Next value is 6
Next value is 8
Next value is 10

Starting at 21
Next value is 23
Next value is 25
Next value is 27
Next value is 29
Next value is 31
Arayz ndeksleyiciler
Bir arayz, bir indeksleyici belirtebilir. Bir arayz iinde deklare edilen bir indeksleyici
genel olarak u ekildedir:
// arayz indeksleyicisi
eleman-tipi this[int indeks] {
get;
set;
}
nceki gibi, salt okunur veya salt yazlr indeksleyiciler iin yalnzca get veya set
mevcut olacaktr.
te, ISeriesin bir baka versiyonu daha. ISeriese bu kez, seri iindeki inci eleman
dndren salt okunur bir indeksleyici eklenmektedir.
// Bir arayuze bir indeksleyici ekle.

using System;

public interface ISeries {
// arayuz ozelligi
int next {
get; // seri icindeki bir sonraki sayiyi dondur
set; // bir sonraki sayiyi ayarla

HERKES N C#
KISIM I C# DL

346
}

// arayuz indeksleyicisi
int this[int index] {
get; // seri icinde belirtilen sayiyi dondur
}
}

// ISeriesi uygula.
class ByTwos : ISeries {
int val;

public ByTwos() {
val = 0;
}

// ozellik kullanarak degeri al ya da ayarla.
public int next {
get {
val += 2;
return val;
}
set {
val = value;
}
}

// indeks kullanarak bir deger al
public int this[int index] {
get {
val = 0;
for(int i = 0; i < index; i++)
val += 2;
return val;
}
}
}

// Bir arayuz indeksleyicisi goster.
class SeriesDemo4 {
public static void Main() {
ByTwos ob = new ByTwos();

// ozellik araciligiyla seriye eris
for(int i = 0; i < 5; i++)
Console.WriteLine(Next value is + ob.next);

Console.WriteLine(\nStarting at 21);
ob.next = 21;
for(int i = 0; i < 5; i++)
Console.WriteLine(Next value is + ob.next);

Console.WriteLine(\nResetting to 0);
ob.next = 0;

BLM 12: ARAYZLER, YAPILAR VE NUMARALANDIRMALAR

HERKES N C#
347
// indeksleyici araciligiyla seriye eris.
for(int i = 0; i < 5; i++)
Console.WriteLine(Next value is + ob[i]);
}
}
Bu programdan elde edilen kt aadaki gibidir:
Next value is 2
Next value is 4
Next value is 6
Next value is 8
Next value is 10

Starting at 21
Next value is 23
Next value is 25
Next value is 27
Next value is 29
Next value is 31

Resetting to 0
Next value is 0
Next value is 2
Next value is 4
Next value is 6
Next value is 8
Arayzler Kaltm Yoluyla Aktarlabilir
Bir arayz kaltm yoluyla bir bakasna aktarlabilir. Sz dizimi kaltmn aktarld
snflar iin ayndr. Bir arayz kaltm yoluyla bir baka arayze aktarlyorsa, bu arayz
uygulayan bir snf, arayz kaltm zinciri iinde tanmlanan tm yeler iin gerekli
uygulamalar da salamaldr. Aada bunun bir rnei yer alyor:
// Bir arayuz kalitim yoluyla bir baskasina aktarilabilir.

using System;

public interface A {
void meth1();
void meth2();
}

// B artk meth1() ve meth2()yi icerir .. meth3()u ekler.
public interface B : A {
void meth3();
}

// Bu sinif, A ve Bnin tumunu uygulamalidir.
class MyClass : B {
public void meth1() {
Console.WriteLine(Implement meth1().);

HERKES N C#
KISIM I C# DL

348
}

public void meth2() {
Console.WriteLine(Implement meth2().);
}

public void meth3() {
Console.WriteLine(Implement meth3().);
}
}

class IFExtend {
public static void Main() {
MyClass ob = new MyClass();

ob.meth1();
ob.meth2();
ob.meth3();
}
}
Deneysel amala MyClassn iindeki meth1() ile ilgili uygulamay kaldrmay denemek
isteyebilirsiniz. Fakat bu, derleme hatasna neden olacaktr. nceden de bildirildii gibi,
herhangi bir arayz uygulamakta olan bir snf, dier arayzlerden kaltm yoluyla aktarlanlar
da dahil olmak zere, sz konusu arayz tarafndan tanmlanan metotlarn tmn
uygulamaldr.
Arayz Kaltm le Birlikte sim Gizleme
Kaltm yoluyla bir arayz bir dierine aktarlrken, tretilmi arayz iinde temel arayz
tarafndan tanmlanm bir yeyi gizleyen bir baka ye deklare etmek mmkndr. Bu durum,
tretilmi arayz iindeki ye, temel arayz iindekiyle ayn imzaya sahip olduu zaman sz
konusu olur. Tretilmi arayz iindeki yeyi new kullanarak deitirmediiniz srece bu du-
rum bir uyar mesajna neden olacaktr.
Ak Uygulamalar
Bir arayze ait bir yeyi uygularken yenin ismini arayzn ismi ile birlikte tam olarak
belirtmek mmkndr. Bu ekilde davranmak bir ak arayz ye uygulamasna (explicit
interface member implementation) ya da ksaca ak uygulamaya (explicit implementation)
neden olur. rnein, aadaki kod parasnn verildiini varsayarak:
interface IMyIF {
int myMeth(int x);
}
aada gsterilen IMyIFi uygulamak kurallara uygundur:
class MyClass : IMyIF {
int IMyIF.myMeth(int x) {
BLM 12: ARAYZLER, YAPILAR VE NUMARALANDIRMALAR

HERKES N C#
349
return x / 3;
}
}
Grdnz gibi, IMyiFin myMeth() yesi uygulanrken yenin tam ismi, yenin
arayznn ismi ile birlikte belirtilir.
Bir arayz yesi iin ak bir uygulama oluturmak iin iki sebebiniz olabilir. Birincisi; bir
metodu, tam olarak belirtilmi bir isim kullanarak uyguladnzda; snfn dnda kalan kod
tarafndan aka grlmeyen, zel bir uygulama olarak nitelendirebileceimiz bir uygulama
salyorsunuz demektir. kincisi; bir snfn, iinde isimleri ve tip imzalar ayn olan metotlarn
deklare edildii iki arayz uygulamas mmkndr. simleri tam olarak belirtmek bu
durumdaki belirsizlii ortadan kaldrr. Gelin imdi her ikisini de birer rnekte grelim.
zel Bir Uygulama Gelitirmek
Aadaki program IEven adnda bir arayz iermekledir. IEven, bir saynn tek ya da
ift olup olmadn belirleyen isEven() ve isOdd() adnda iki metot tanmlar. Daha sonra
MyClass, IEven uygular. Bunu gerekletirdikten sonra ise isOdd()u ak olarak uygular.
// Bir arayuz uyesinin acik olarak uygulanmasi.

using System;

interface IEven {
bool isOdd(int x);
bool isEven(int x);
}

class MyClass : IEven {
// acik uygulama
bool IEven.isOdd(int x) {
if((x%2) != 0) return true;
else return false;
}

// normal uygulama
public bool isEven(int x) {
IEven o = this; // cagiran nesneye referans

return !o.isOdd(x);
}
}

class Demo {
public static void Main() {
MyClass ob = new MyClass();
bool result;

result = ob.isEven(4);
if(result) Console.WriteLine(4 is even.);
else Console.WriteLine(3 is odd.);

HERKES N C#
KISIM I C# DL

350

// result = ob.isOdd(); // Hata. Metot acikca ortada degildir!
}
}
isOdd() aka uyguland iin MyClassn dnda kullanlamaz. Bu, isOdd()un
uygulann etkin biimde zel klmaktadr. MyClass iinde isOdd() yalnzca bir arayz
referans araclyla eriilebilir. isEven()in uygulan srasnda o araclyla arlmasnn
sebebi de budur.
Belirsizlii Ortadan Kaldrmak in Ak Uygulamalarn
Kullanm
imdi de, iki arayz uygulamas ieren ve her iki arayz iinde meth() adnda bir metot
deklare edilen bir rnei inceleyelim. Bu duruma zg belirsizlii ortadan kaldrmak iin bu r-
nekte ak uygulama kullanlyor.
// Belirsizligi ortadan kaldirmak icin acik uygulama kullan.

using System;

interface IMyIF_A {
int meth(int x);
}

interface IMyIF_B {
int meth(int x);
}

// MyClass her iki arayuzu de uygular.
class MyClass : IMyIF_A, IMyIF_B {

// iki meth()i de acikca uygula
int IMyIF_A.meth(int x) {
return x + x;
}

int IMyIF_B.meth(int x) {
return x * x;
}

// meth()i bir arayuz referansi araciligiyla cagir
public int methA(int x) {
IMyIF_A a_ob;
a_ob = this;
return a_ob.meth(x); // IMyIF_Ayi cagirir
}

public int methB(int x} {
IMyIF_B b_ob;
b_ob = this;
return b_ob.meth(x); // IMyIF_Byi cagirir
BLM 12: ARAYZLER, YAPILAR VE NUMARALANDIRMALAR

HERKES N C#
351
}
}

class FQIFNames {
public static void Main() {
MyClass ob = new MyClass();

Console.Write(Calling IMyIF_A.meth(): );
Console.WriteLine(ob.methA(3));

Console.Write(Calling IMyIF_B.meth(): );
Console.WriteLine(ob.methB(3));
}
}
Bu programn kts aadaki gibidir:
Calling IMyIF_A.meth(): 6
Calling IMyIF_B.meth(): 9
Programa bakarak ncelikle meth()in imzasnn hem IMyIF_Ada hem de IMyIF_Bde
ayn olduuna dikkat edin. Bylece, MyClass bu iki arayz uygularken, her birinin ismini bu
ilem srasnda tam olarak belirterek her birini ayr ayr ak olarak uygulamaldr. Ak olarak
uygulanan bir metot yalnzca bir arayz referans zerinden arlabilir. Bu nedenle; methA(),
IMyIF_A iin; methB() ise IMyIF_B iin bir referans oluturmaktadr. Metotlar daha sonra bu
referanslar araclyla meth()i arrlar; bu sayede, belirsizlii de ortadan kaldrm olurlar.
Bir Arayz ve zet Snf Arasnda Tercihte Bulunmak
C# programlamann daha zorlayc blmlerinden biri, uygulamay deil de ilevsellii
tarif etmek istediinizde bir arayz tanmlayacanz ya da bir zel snf kullanacanz yeri ve
zaman bilmenizdir. Genel kural udur: Eer bir kavram nasl yapar? sorusuna yant aramaya
gerek kalmadan ne yapar? sorusuna verilecek yant ile tam olarak tarif edebiliyorsanz bir
arayz kullanmalsnz. Eer biraz uygulama ayrntlarn da eklemeniz gerekiyorsa, bu
durumda kavramnz bir zet snf ile simgelemeniz gerekecektir.
.NET Standart Arayzleri
.NET Framework, bir C# programnn kullanabilecei ok sayda arayz tanmlamaktadr.
rnein, nesneler arasnda bir sralama ilikisi gerekince nesnelerin karlatrlmasn salayan
CompareTo() metodu System.IComparable tarafndan tanmlanr. Arayzler ayrca
gruplar halindeki nesneler iin eitli depolama tipleri (sz gelii, ynlar ve kuyruklar)
salayan Collections snflarnn da nemli bir blmn olutururlar. rnein,
Systems.Collections.ICollection tm koleksiyonlarda ortak olan ilevsellii tanmlar.
Systems.Collections.Enumerator ise bir koleksiyon iindeki elemanlarn zerinde art
arda gezinmek iin bir yntem sunmaktadr. Bunlara ve dier arayzlere Ksm IIde gz
atacaz.

HERKES N C#
KISIM I C# DL

352
Arayzlerle lgili Bir rnek alma
Daha da ilerlemeden nce bir arayz kullanan bir baka rnek zerinde almak yararl
olacaktr. Bu blmde ICipher adnda bir arayz oluturacaz. ICiphern iinde ifreleme
iin kullanlan karakter katarlarn destekleyen metotlar belirtilecektir. Bu ama iin bir arayz
kullanmak akla yatkndr, nk ifrelemenin ne ile ilgili ksmn nasl ile ilgili ksmndan
tam olarak ayrmak mmkndr.
ICipher arayz aada gsterilmitir:
// Bir sifreleme arayuzu.
public interface ICipher {
string encode(string str);
string decode(string str);
}
ICipher arayznde iki metot belirtilmektedir: encode(), bir karakter katarm
ifrelemek iin kullanr ve decode(), bir karakter katarnn ifresini zmek iin kullanlr.
Dier hibir ayrnt belirtilmez. Bu, bu metotlar uygulayan snflarn ifreleme iin herhangi
bir yntemi kullanmakta zgr olduklar anlamn tar. rnein; bir snf, kullanc tarafndan
belirtilen bir anahtar baz alarak bir karakter katarn ifreleyebilir, kinci bir snf ifre
korumas (password protection) kullanabilir. ncs, bitleri maniple etme esasna dayanan
bir ifreleme yntemini tercih edebilir; bir dieri ise basit bir ekilde karakterlerin yerlerini
deitiren bir kod kullanabilir. ifreleme iin hangi yaklam kullanlrsa kullanlsn, bir
karakter katarn ifrelemek ve ifre zmek iin kullanlan arayz ayndr. ifreleme ile ilgili
uygulamann herhangi bir blmn belirtmeye gerek yoktur. Bu nedenle, arayz bunu
simgeleyen mantksal bir seenektir.
imdi de ICipher uygulayan iki snfa gz atalm. lki, her karakteri bir konum yukarya
kaydrarak bir karakter katarn ifreleyen SimpleCipherdr. rnein; A, B olur; B, C olur vs.
kicisi ise; bir anahtar gibi davranan 16 bitlik bir deer ile her karaktere XOR uygulayarak bir
karakter katarn ifreleyen BitCipherdr.
/* Her karakteri 1 konum yukariya kaydirarak
bir mesaji sifreleyen ICipherin basit bir uygulamasi.
Bylece; A, B olur vs. */

class SimpleCipher : ICipher {

// Orijinal metin verilince sifrelenmis karakter katarini dondurur.
public string encode(string str) {
string ciphertext = ;

for(int i = 0; i < str.Length; i++)
ciphertext = ciphertext + (char) (str[i] + 1);

return ciphertext;
}

BLM 12: ARAYZLER, YAPILAR VE NUMARALANDIRMALAR

HERKES N C#
353

/* Sifrelenmis metin verilince sifresi cozulmus karakter
katarini dondurur. */
public string decode(string str) {
string plaintext = ;

for(int i = 0; i < str.Length; i++)
plaintext = plaintext + (char) (str[i] - 1);

return plaintext;
}
}

/* ICipherin bu uygulamasi bit manipulasyonu ve anahtar
kullanir. */
class BitCipher : ICipher {
ushort key;

// BitCiphersi kurarken bir anahtar belirt.
public BitCipher (ushort k) {
key = k;
}

// Orijinal metin verilince sifrelenmi karakter katarini dondur.
public string encode(strins str) {
string ciphertext = ;

for(int i = 0; i < str,Length; i++)
ciphertext = ciphertext + (char) (&tr[i] ^ key);

return ciphertext;
}

/* Sifrelenmi metin verilince sifresi cozulmus karakter
katarini dondur. */
public string decode(string str} {
string plaintext = ;

for(int i = 0; i < str.Length; i++)
plaintext = plaintext + (char) (str[il ^ key);

return plaintext;
}
}
Grdnz gibi, SimpleCipher ve BitCipher uygulamada farkllk gsteriyor olsa da,
her ikisi de ICipher arayzn uygulamaktalar. Aadaki program SimpleCipher ve
BitCipher gstermektedir:
// ICipheri gosterir.

using System;

class ICipherDemo {

HERKES N C#
KISIM I C# DL

354
public static void Main() {
ICipher ciphRef;
BitCipher bit = new BitCipher(27);
SimpleCipher sc = new SimpleCipher();

string plain;
string coded;

// oncelikle ciphRef, basit sifreleyiciye referansta bulunur
ciphRef = sc;

Console.WriteLine(Using simple cipher.);

plain = testing;
coded = ciphRef.encode(plain);
Console.WriteLine(Cipher text: + coded);

plain = ciphRef.decode(coded);
Console.WriteLine(Plain text: + plain);

/* artik, ciphRefin bit tabanli sifrelemeye referansta
bulunmasina izin ver */
ciphRef = bit;
Console.WriteLine(\nUsing bitwise cipher.);

plain = testing;
coded = ciphRef.encode(plain);
Console.WriteLine(Cipher text: + coded);

plain = ciphRef.decode(coded);
Console.WriteLine(Plain text: + plain);
}
}
kt aada gsterilmitir:
Using simple cipher.
Cipher text: uftujoh
Plain text: testing

Using bitwise cipher.
Cipher text: o-horu|
Plain text: testing
ifreleme arayz oluturmann bir avantaj, ifreleme ne ekilde uygulanrsa uygulansn,
arayz uygulayan snflarn her birinin ayn ekilde eriilmeleridir. rnein, aadaki
program ele aln. Bu programda, listelenmemi telefon numaralarn ifreli biimde saklayan
UnlistedPhone adnda bir snf yer almaktadr. simlerin ve numaralarn ifreleri gerektiinde
otomatik olarak zlr.
// ICipher kullanir.

using System;

BLM 12: ARAYZLER, YAPILAR VE NUMARALANDIRMALAR

HERKES N C#
355
// Listelenmemis telefon numaralarini saklamak icin bir sinif.
class UnlistedPhone {
string pri_name; // isim ozelligini destekler
string pri_number; // numara ozelligini destekler

ICipher crypt; // sifreleme nesnesine referans

public UnlistedPhone(string name, string number, ICipher c)
{
crypt = c; // sifrelame nesnesini sakla

pri_name = crypt.encode(name);
pri_number = crypt.encode(number);
}

public string Name {
get {
return crypt.decode(pri_name);
}
set {
pri name = crypt.encode(value);
}
}

public string Number {
get {
return crypt.decode(pri_number);
}
set {
pri_number = crypt.encode(value);
}
}
}

// UnlistedPhone goster
class UnlistedDemo {
public static void Main() {
UnlistedPhone phone1 =
new UnlistedPhone(Tom, 555-3456, new BitCipher(27));
UnlistedPhone phone2 =
new UnlistedPhone(Mary, 555-8391, new BitCipher(9));

Console.WriteLine(Unlisted number for + phone1.Name +
is + phone1.Number);

Console.WriteLine(Unlisted number for + phone2.Name +
is + phone2.Number);
}
}
Bu programn kts aada gsterilmitir:
Unlisted number for Tom is 555-3456
Unlisted number for Mary is 555-8891

HERKES N C#
KISIM I C# DL

356
UnlistedPhoneun nasl uygulandna yakndan bakn. Dikkat ederseniz,
UnlistedPhone alan ierir. lk ikisi, isim ve telefon numaralarn saklayan zel
deikenlerdir. ncs ise ICipher nesnesine bir referanstr. Bir UnlistedPhone nesnesi
kurulunca bu referans bu nesneye aktarlr. lk ikisi, isim ve telefon numarasn tutan
karakter katarlarna referanstr. ncs, isim ve numaray ifrelemek iin kullanlan
ifreleme nesnesine referanstr. ifreleme nesnesinin referanslar crypt iinde saklanr.
ICipher arayzn uygulad srece her tipten ifreleme nesnesi kabul edilebilir. Bu rnekte
BitCipher kullanlmtr. Bylece; UnlistedPhone, crypt referans araclyla bir
BitCipher nesnesi zerinde encode() ve decode() metotlarn arabilir.
imdi de, Name ve Number zelliklerinin nasl altna dikkat edin. set ilemi
gereklenirken crypt nesnesi zerinde encode() arlarak isim veya numara otomatik
olarak ifrelenir. get ilemi gerceklenirken ise, decode() arlarak isim ve numara otomatik
olarak zlr. Ne Name, ne de Number, altta yatan ifreleme metodu hakknda spesifik bir
bilgiye sahip deildir. Bunlar yalnzca ifreleme metodunun ilevselliine, ifreleme
metodunun arayz araclyla eriirler.
ifreleme arayz ICipher tarafndan standardize edildii iin UnlistedPhoneun
kodunun iindeki almalarn hibirini deitirmeden ifreleme nesnesini deitirmek
mmkndr. rnein, aadaki program UnlistedPhone nesnelerini yaplandrrken
BitCipher yerine SimpleCipher kullanr. Sz konusu tek deiiklik, UnlistedPhone iin
yaplandrcya aktarlan ifreleme nesnesindedir.
// Bu versiyon SimpleCipher kullanir.

using System;

class UnlistedDemo {
public static void Main() {

// simdi, BitCipher yerine SimpleCipher kullan
UnlistedPhone phone1 =
new unlistedPhone(Tom, 555-3456, new SimpleCipher());
UnlistedPhone phone2 =
new UnlistedPhone(Mary, 555-8891, new SimpleCipher());

Console.WriteLine(Unlisted number for + phone1.Name +
is + phone1.Number);

Console.WriteLine(Unlisted number for + phone2.Name +
is + phone2.Number);
}
}
Bu programn da gsterdii gibi, BitCipher ve SimpleCiphern her ikisi de
ICipheri uyguladklar iin UnlistedPhone nesnelerini kurarken ikisinden biri
kullanlabilir.
BLM 12: ARAYZLER, YAPILAR VE NUMARALANDIRMALAR

HERKES N C#
357
Son bir husus: UnlistedPhoneun uygulamas, bir arayz referans araclyla arayzleri
uygulayan nesnelere erimenin gcn de gstermektedir. ifreleme nesnesine ICipher
referans deikeni araclyla referansta bulunulduu iin ICipher arayzn uygulayan
herhangi bir nesne bu amala kullanlabilir. Bu durum, UnlistedPhoneun kodunun hibir
blmnn deitirilmesine neden olmadan spesifik ifreleme uygulamasnn problemsiz ve
gvenli olarak deitirilmesini mmkn klar. Eer UnlistedPhone bunun yerine belirli tipte
bir ifreleme nesnesini crypt tipindeki veriler iin donanmsal olarak kodlam olsayd, sz
gelii BitCipher gibi, bu durumda farkl bir ifreleme yntemi istendiinde
UnlistedPhoneun kodunun deitirilmesi gerekecekti.
Yaplar
Bildiiniz gibi snflar, referans tipidir. Bunun anlam udur: Snf nesneleri bir referans
araclyla eriilirler. Bu durum, dorudan eriilen deer tiplerinden farkllk gsterir. Yine de,
kimi zaman bir nesnenin, deer tiplerine eriir ekilde dorudan eriilebilir olmas yararl
olacaktr. Bunun nedenlerinden biri verimliliktir. Snf nesnelerine bir referans araclyla
erimek her eriime ilave yk bindirir. Ayrca bellek alan da harcar. ok kk nesneler iin
bu ekstra alan nemli olabilir. Bu sorunlar dile getirmek iin C#, yaplar nermektedir. Yap
(structure), snf ile ayndr. Tek fark, yapnn bir referans tipi yerine bir deer tipinde
olmasdr.
Yaplar struct anahtar kelimesi kullanlarak deklare edilir ve sz dizimsel olarak
snflara benzer. Bir struct genel olarak u ekildedir;
struct isim : arayzler {
// ye deklarasyonlar
}
Yapnn ismi isim ile belirtilir.
Yaplar, dier yaplar veya snflar kaltm yoluyla aktaramaz ya da dier yaplar veya
snflar iin temel snf olarak kullanlamazlar. (Dier tm C# tiplerinde olduu gibi yaplar da
kukusuz objecti kaltm yoluyla aktarrlar.) Bununla birlikte, bir yap bir ya da daha fazla
arayz uygulayabilir. Bu arayzler, yapnn isminden sonra virgl ile ayrlm bir liste halinde
belirtilir. Tpk snflar gibi, yap yeleri de metot, alan, indeksleyici, zellik, operatr
metotlarn ve olaylar kapsar. Yaplar ayrca yaplandrclar da tanmlar, fakat yok ediciler,
yaplarda tanmlanmaz. Ancak, bir yap iin varsaylan (parametresiz) yaplandrc
tanmlayamazsnz. Bunun nedeni, varsaylan yaplandrcnn tm yaplar iin otomatik olarak
tanml olmasdr; bu varsaylan yaplandrc deitirilemez. Yaplar kaltm desteklemedikleri
iin yap yeleri abstract, virtual ya da protected olarak belirtilemezler.
Bir yap nesnesi, bir snf nesnesi ile ayn ekilde new kullanlarak oluturulabilir; fakat bu
gerekli deildir. new kullanlnca belirtilen yaplandrc arlr. new kullanlmyorsa nesne bu
durumda da oluturulur fakat nesneye ilk deer atanmaz. Bylece, ilk deer atama ilemlerini
elle gerekletirmeniz gerekecektir.

HERKES N C#
KISIM I C# DL

358
te bir rnek, bu rnekte bir kitap hakknda bilgileri tutmak iin bir yap kullanlmaktadr:
// Bir yapi goster.

using System;

// Bir yapi tanimla.
struct Book {
public string author;
public string title;
public int copyright;

public Book(string a, string t, int c) {
author = a;
copyright = c;
}
}

// Book yapisini goster.
class StructDemo {
public static void Main() {
Book book1 = new Book(Saim Mehmet Ozturk,
C# A Beginners Guide, 2001);
// acik yapilandirici
Book book2 = new Book(); // varsayilan yapilandirici
Book book3; // yapilandirici yok

Console.WriteLine(book1.title + by + book1.author +
, (c) + book1.copyright);
Console.WriteLine();

if(book2.title == null)
Console.WriteLine(book2.title is null.);
// simdi book2ye biraz bilgi ver
book2.title = Brave New World;
book2.author = Aldous Huxley;
book2.copyright = 1932;
Console.Write(book2 now contains: );
Console.WriteLine(book2,title + by + book2.author +
, (c) + book2.copyright);

Console.WriteLine();

// Console.WriteLine(book3.title); // hata, once ilk deger atamali
book3.title = Red Storm Rising;

Console.WriteLine(book3.title); // simdi oldu
}
}
Bu programn kts aadaki gibidir:
C# A Beginners Guide by Saim Mehmet Ozturk, (c) 2001

book2.title is null.
BLM 12: ARAYZLER, YAPILAR VE NUMARALANDIRMALAR

HERKES N C#
359
book2 now contains: Brave New World by Aldous Huxley, (c) 1932

Red Storm Rising
Programdan grld gibi, bir yapya iki ekilde ilk deer atanabilir: Bir yaplandrc
armak amacyla new kullanlr ya da basite bir nesne deklare ederek bu ilem
gerekletirilir. new kullanlrsa yapnn alanlarna ilk deerleri atanacaktr. Bunun iin, tm
alanlara ilk deer olarak, alanlarn varsaylan deerlerini atayan bir varsaylan yaplandrc
kullanlabilir ya da kullanc tarafndan tanmlanan bir yaplandrc da kullanlabilir. book3te
sz konusu olduu gibi eer new kullanlmazsa, bu durumda nesneye ilk deer atanmaz;
nesnenin alanlar nesnenin kullanmndan nce ayarlanmaldr.
Bir yapy bir dierine atarken sz konusu nesnenin kopyas kartlr. Bu, yaplar
snflardan ayran nemli bir zelliktir. Elinizdeki kitabn daha nceki sayfalarnda akland
gibi, bir snf referansn bir dierine atarken atama operatrnn sol tarafnda bulunan
referansn referansta bulunduu nesneyi deitirmeniz yeterlidir. Bir yap deikenini bir
bakasna atarken ise atama operatrnn sandaki nesnenin kopyasn kartrsnz. rnein,
aadaki program ele aln:
// Bir structi kopyala.

using System;

// Bir yapi tanimla.
struct MyStruct {
public int x;
}

// Yapinin atanisini goster.
class StructAssignment {
public static void Main() {
MyStruct a;
MyStruct b;

a.x = 10;
b.x = 20;

Console.WriteLine(a.x {0}, b.x {1}, a.x, b.x);
a = b;
b.x = 30;

Console.WriteLine(a.x {0}, b.x {1}, a.x, b.x);
}
}
kt aada gsterilmitir:
a.x 10, b.x 20
a.x 20, b.x 30
ktdan da grld zere, aadaki atama ileminden sonra birer yap deikeni olan a
ve b halen ayr ve farkldr:

HERKES N C#
KISIM I C# DL

360
a = b;
Yani; a, bnin deerinin bir kopyasna referansta bulunmaktan baka hibir ekilde b ile
ilikili deildir ya da bye baka hibir ekilde referansta bulunamaz, a ve b snf referanslar
olmu olsalard, byle bir durum sz konusu olmayacakt. rnein, yukardaki programn
snfl versiyonu u ekildedir:
// Bir sinif kopyala.

using System;

// Bir yapi tanmla.
class MyClass {
public int x;
}

// Simdi bir sinif nesnesine atama yapilisini goster.
class ClassAssignment {
public static void Main() {
MyClass a = new MyClass();
MyClass b = new MyClass();

a.x = 10;
b.x = 20;

Console.WriteLine(a.x {0}, b.x {1}, a.x, b,x);

a = b;
b.x = 30;

Console.WriteLine(a.x {0}, b.x {1}, a.x, b.x);
}
}
Bu versiyondan elde edilen kt yledir:
a.x 10, b.x 20
a.x 30, b.x 30
Grdnz gibi, bnin aya atanmasndan sonra her iki deiken de ayn nesneye
balangta b tarafndan referansta bulunan nesneye referansta bulunmaktalar.
Yaplara Neden Gerek Vardr?
Bu noktada, structun C#ta neden yer aldn merak ediyor olabilirsiniz. yle ya;
struct, classn daha az yetenekli bir versiyonu gibi grnyor. Bunun yantn verimlilik
ve performansta aramalsnz. Yaplar bir deer tipi olduklar iin, bir referans araclyla deil
de dorudan kendi zerlerinde ilem grrler. Bylece, bir struct ayr bir referans deikeni
gerektirmez. Bu, baz durumlarda daha az bellek kullanld anlamna gelir. stelik, bir
struct dorudan eriilebildii iin, snf nesnelerinin eriimlerine zg performans kaybna
da maruz kalmaz. Snflar bir referans tipidir. Bu nedenle, snf nesnelerine yaplan tm
BLM 12: ARAYZLER, YAPILAR VE NUMARALANDIRMALAR

HERKES N C#
361
eriimler bir referans araclyla olmaldr. Bu tr bir dolayl eriim, eriimlerin her birine ek
bir yk bindirir. Yaplar byle bir ykn altna girmezler. Genel olarak, birbiriyle balantl
kk bir veri grubunu saklamak istiyorsanz, fakat kaltma ihtiyacnz yoksa ya da referans
tiplerinin salad dier avantajlardan yararlanmak istemiyorsanz, struct sizin iin ok daha
uygun bir tercih olacaktr.
Bir yapnn uygulamada nasl kullanlabileceini gsteren ite bir baka rnek. Aadaki
program bir e-ticaret ilem kaydn canlandrmaktadr. Her ilem, paketin numarasn ve
uzunluunu ieren bir paket balna sahiptir. Bunun peinden hesap numaras ve ilem
yaplacak miktar gelir. Paket bal kendi kendisini ieren bilgi birimi olduu iin bir yap ola-
rak organize edilmitir. Bu yap daha sonra bir ilem kaydn ya da bir baka tipte bilgi paketini
oluturmak amacyla kullanlabilir.
// Verileri gruplamak icin yapilar uygundur.

using System;

// Bir paket yapisi tanimla.
struct PacketHeader {
public uint packNum; // paket numarasi
public ushort packLen; // paketin uzunlugu
}

// PacketHeaderi kullanarak bir e-ticaret islem kaydi olustur.
class Transaction {
static uint transacNum = 0;

PacketHeader ph; // PacketHeaderi Transactiona dahil et
string accountNum;
double amount;

public Transaction(string acc, double val) {
// paket basligi olustur
ph.packNum = transacNum++;
ph.packLen = 512; // keyfi bir uzunluk
accountNum = acc;
amount = val;
}

// Islemi simule et.
public void sendTransaction() {
Console.WriteLine(Packet #: + ph.packNum +
, Length: + ph.packLen +
,\n Account #: + accountNum +
, Amount: {0:C}\n, amount);
}
}

// Paketi goster.
class PacketDemo {
public static void Main() {
Transaction t = new Transaction(31243, -100.12);

HERKES N C#
KISIM I C# DL

362
Transaction t2 = new Transaction(AB4655, 345.25);
Transaction t3 = new Transaction(8475-09, 9800.00);

t.sendTransaction();
t2.sendTransaction();
t3.sendTransaction();
}
}
Programn kts aada gsterilmitir:
Packet #: 0, Length: 512,
Account #: 31243, Amount: (S100.12)

Packet #: 1, Length: 512,
Account #: AB4655, Amount: S345.25

Packet #: 2, Length: 512,
Account #: 8475-09, Amount: S9,800.00
PacketHeader, struct iin iyi bir tercihtir, nk kk miktarda veri iermektedir,
stelik kaltm ve hatta metot bile kullanmamaktadr. Bir yap olarak PacketHeader, bir
referansn getirdii ek ykn altna girmez. Oysa bir snf bu yk tamak zorundadr. Yani,
herhangi bir tipte ilem kayd, PacketHeaderi verimliliini etkilemeden kullanabilir.
lgin bir nokta, C++n da yaplar iermesi ve struct anahtar kelimesini kullanmasdr.
Ancak, C# ve C++ yaplar ayn deildir. C++ta struct bir snf tipi tanmlar. Bu nedenle,
C++ta struct ve class hemen hemen edeerdir. (Aradaki fark, her ikisinin yelerinin
varsaylan eriimlerinden kaynaklanmaktadr. class iin varsaylan ye eriimi privatetr,
struct iin ise publictir.) C#ta ise struct bir deer tipi tanmlar; class ise bir referans
tipi tanmlar.
Numaralandrmalar
Numaralandrma (enumeration), isimlendirilmi tamsay sabitlerinden oluan bir kmedir.
enum anahtar kelimesi bir numaralandrlm tip deklare eder. Numaralandrmann ekli genel
olarak yledir:
enum isim { numaralandrma listesi };
Burada, numaralandrmaya verilen tip ismi isim ile belirtilir. numaralandrma
listesi, virglle ayrlan tanmlayclarn bir listesidir.
te bir rnek; aadaki kod paras, eitli elma tiplerini numaralandran apple adnda
bir numaralandrma tanmlamaktadr:
enum apple { Jonathan, GoldenDel, RedDel, Winsap,
Cortland, McIntosh };
Numaralandrmay anlamak iin en nemli hususlardan biri udur: Her sembol bir tamsay
deere karlk gelir ve her sembole kendisinden hemen nce gelen semboln deerinden bir
BLM 12: ARAYZLER, YAPILAR VE NUMARALANDIRMALAR

HERKES N C#
363
fazla deer verilir. lk numaralandrma sembolnn varsaylan deeri 0dr. Bylece,
Jonathann deeri 0, GoldenDelin deeri 1dir vs.
Bir tamsaynn kullanlabilecei her yerde bir numaralandrma sabiti de kullanlabilir. An-
cak, bir enum tipi ile standart tamsay tipler arasnda kapal dnmler tanml deildir. Bu ne-
denle, ak tip atamalar kullanlmaldr. Ayrca, iki numaralandrma tipi arasnda dnm ger-
ekletirirken bir tip atamas kullanlmaldr.
Bir numaralandrmann yeleri, nokta operatr zerinden yelerin tip isimleri araclyla
eriilir. rnein, u ifade
Console.WriteLine(apple.RedDel + has the value +
(int)apple.RedDel);
aadaki kty gsterir:
RedDel has the value 2
ktdan grld gibi, numaralandrlm bir deer ekranda gsterilirken bu deerin ismi
kullanlr. Bunun tamsay deerini elde etmek iin ise inte dnm salayan bir tip atamas
kullanlmaldr. (Bu davran C#n ilk versiyonlarna gre farkllk gsterir. lk versiyonlarda,
numaralandrlm bir deerin ismi yerine tamsay karlklar ekranda gsterilirdi.)
te size applen numaralandrln gsteren bir program:
// Bir numaralandirma gosterir.

using System;

class EnumDemo {
enum apple { Jonathan, GoldenDel, RedDel, Winsap,
Cortland, McIntosh };

public static void Main() {
string[] color = {
Red,
Yellow,
Red,
Red,
Red,
Reddish Green
};

apple i; // bir enum degiskeni deklare et

// enum uzerinde gezinmek icin i kullan
for(i = apple.Jonathan; i <= apple.McIntosh; i++)
Console.WriteLine(i + has value of + (int)i);

Console.WriteLine();

// bir diziyi indekslemek icin numaralandirma kullan

HERKES N C#
KISIM I C# DL

364
for(i = apple.Jonathan; i <= apple.McIntosh; i++)
Console.WriteLine(Color of + i + is +
color[(int)i]);
}
}
Programn kts aada gsterilmitir:
Jonathan has value of 0
GoldenDel has value of 1
RedDel has value of 2
Winsap has value of 3
Cortland has value of 4
McIntosh has value of 5

Color of Jonathan is Red
Color of GoldenDel is Yellow
Color of RedDel is Red
Color of Winsap is Red
Color of Cortland is Red
Color of McIntosh is Reddish Green
for dnglerinin apple tipinde bir deiken tarafndan nasl kontrol edildiine dikkat
edin. Numaralandrma tamsay tipinde olduu iin, bir numaralandrma deeri bir tamsaynn
kullanlabilecei her yerde kullanlabilir. apple iindeki numaralandrlm deerler sfrdan
baladndan tr, bu deerler elmann rengini elde etmek amacyla coloru indekslemek
iin kullanlabilir. Numaralandrma deeri color dizisini indekslemek iin kullanlnca bir tip
dnmne gerek olduuna dikkat edin. nceden de bahsedildii gibi, tamsaylar ve numara-
landrma tipleri arasnda kapal bir dnm tanml deildir. Aka bir tip atamas gereklidir.
Bir dier husus da udur: Numaralandrlm deerler birer tamsay olduklar iin, bir
switch ifadesini kontrol etmek amacyla bir numaralandrlm tip kullanabilirsiniz. Bunun bir
rneini az sonra greceksiniz.
Bir Numaralandrmaya lk Deer Atamak
Bir ilk deer atamas kullanarak bir ya da daha fazla semboln deerini belirtebilirsiniz.
Bunun iin semboln peinden eittir iareti ve bir tamsay deer kullann. lk deer
atamalarnn peinden gelen sembollere bir nceki atanan deerden daha byk deerler atanr.
rnein, aadaki kod, RedDele 10 deerini atar:
enum apple { Jonathan, GoldenDel, RedDel = 10, Winsap,
Cortland, McIntosh };
imdi bu simgelerin deerleri aadaki gibidir:
Jonathan 0
GoldenDel 1
RedDel 10
Winsap 11
Cortland 12
BLM 12: ARAYZLER, YAPILAR VE NUMARALANDIRMALAR

HERKES N C#
365
McIntosh 13
Bir Numaralandrmann Temel Tipini Belirtmek
Numaralandrmalarn varsaylan tipi inttir, fakat char tipi haricinde herhangi bir
tamsay tipinde bir numaralandrma oluturabilirsiniz. int dnda bir tip belirtmek iin temel
tipi numaralandrma isminden sonra yazn ve bu ikisini, iki nokta iareti ile birbirinden ayrn.
rnein, aadaki ifade apple, byte temel alan bir numaralandrma haline sokmaktadr:
enum apple : byte { Jonathan, GoldenDel, RedDel, Winsap,
Cortland, McIntosh };
Artk, rnein apple.Winsap, byte cinsinden bir niceliktir.
Numaralandrmalarn Kullanm
lk bakta numaralandrmalar C#n ilgin ancak nispeten nemsiz bir paras olarak
dnebilirsiniz. Fakat bu, sz konusu deildir. Programnz bir ya da daha fazla zelletirilmi
sembole gerek duyduunda numaralandrmalar ok kullanldr. rnein, bir fabrikadaki ta-
ma bandn kontrol eden bir program yazdnz hayal edin. u komutlar parametre olarak
kabul eden conveyor() adnda bir metot oluturabilirsiniz: bala, dur, ileri ve geri.
conveyor()a, mesela bala iin 1, dur iin 2 gibi tamsay deerler aktarmak yerine - ki, bu
hataya ak bir yaklamdr - bu deerlere birer szck atayan bir numaralandrma
oluturabilirsiniz. Bu yaklamn bir rnei u ekildedir:
// Bir tasima bandni canlandirir.

using System;

class ConveyorControl {
// tasima bandi komutlarini numaralandir
public enum action { start, stop, forward, reverse };

public void conveyor(action com) {
switch(com) {
case action.start:
Console.WriteLine(Starting conveyor.);
break;
case action.stop:
Console.WriteLine(Stopping conveyor.);
break;
case action.forward:
Console.WriteLine(Moving forward.);
break;
case action.reverse:
Console.WriteLine(Moving backward.);
break;
}
}
}

HERKES N C#
KISIM I C# DL

366

class ConveyorDemo {
public static void Main() {
ConveyorControl c = new ConveyorControl();

c.conveyor(ConveyorControl.action.start);
c.conveyor(ConveyorControl.action.forward);
c.conveyor(ConveyorControl.action.reverse);
c.conveyor(ConveyorControl.action.stop);
}
}
Programn kts aada gsterilmitir:
Starting conveyor.
Moving forward.
Moving Backward.
Stopping conveyor.
conveyor(), action tipinde bir argman ald iin, yalnzca action tarafndan
tanmlanan deerler bu metoda aktarlabilir. rnein aada, conveyor()a 22 deerini
aktarmak iin bir giriimde bulunulmaktadr:
c.conveyor(22); // Hata!
Bu ifade derlenmeyecektir, nk intten actiona nceden tanmlanm bir dnm
sz konusu deildir. Bu durum, conveyor()a geersiz komutlarn aktarlmasna engel olur.
Kukusuz, tip atamas yoluyla dnm zorlayabilirsiniz, fakat bu nceden tasarlanm bir
hareket olmaldr ve kazara hatal kullanmlara yol amamaldr. Ayrca, komutlar numara
yerine isim ile belirtildikleri iin, conveyor()u kullananlarn kazara yanl bir deer
aktarmalar pek de olas bir durum deildir.
Bu rnekle ilgili dikkat ekmemiz gereken bir baka husus daha vardr: switch ifadesini
kontrol etmek amacyla bir numaralandrlm tip kullanldna dikkat edin. nceden de
bahsedildii gibi, numaralandrmalar tamsay tipler olarak ele alndklarndan dolay, switch
ifadesinde kullanlmak zere tamamen uygundurlar.



O N N C B L M

KURAL DII DURUM
YNETM





















13

HERKES N C#
KISIM I C# DL

368
Kural d durum (exception), programn almas srasnda ortaya kan bir hatadr. C#n
kural d durum ynetimi alt sistemini kullanarak programn almas srasnda ortaya kan
hatalar yapsal ve kontroll bir ekilde ele alabilirsiniz. Kural d durum ynetimi iin C#n
uygulad yaklam, C++ ve Java tarafndan kullanlan metotlarn bir harmandr ve bu
metotlar zerine bir ilerlemedir. Yani bu konu, bu dillerden herhangi biriyle ilgili bilgisi olan
okuyuculara tandk gelecektir. C#n kural d durum ynetimini esiz klan, kural d durum
yneliminin temiz ve anlalr olarak uygulanmasdr.
Kural d durum ynetiminin balca avantaj, daha nce byk programlara elle
girilmek zorunda olan hata ynetimi kodunun byk bir ksmn otomatize etmesidir. rnein,
kural d durum ynetimi mevcut olmayan bir bilgisayar dilinde, bir metot baarsz olduunda
hata kodlar dndrlmelidir ve metodun her arlnda bu deerler elle kontrol edilmelidir.
Bu yaklam hem skc hem de hataya aktr. Kural d durum ynetimi, programnzda bir
hata ortaya ktnda otomatik olarak altrlan kural d durum yneticisi (exception
handler) adnda bir kod blou tanmlamanza imkan vererek hata ynetimi verimliliini artrr.
Spesifik ilemlerin ya da metot arlarnn baarl ya da baarsz olduunu elle kontrol
etmeye gerek yoktur. Eer bir hata meydana gelmise sz konusu hata, kural d durum
yneticisi tarafndan ileme alnacaktr.
Kural d durum ynetiminin nemli olmasnn bir baka sebebi, yaygn program hatalar
iin C#ta standart kural d durumlar tanmlanm olmasdr. Sfra blme ya da deer aral
dna kan indeks, yaygn programlama hatalar arasnda yer almaktadr. Bu tr hatalara yant
vermek iin programnz bu tr kural d durumlar gzlemeli ve kontrol altna almaldr.
Son tahlilde, baarl bir C# programcs olmak iin, C#n kural d durum ynetim alt
sistemini ynlendirmeyi tam anlamyla becerebiliyor olmalsnz.
System.Exception Snf
C#ta kural d durumlar snflarla simgelenir. Tm kural d durum snflar, System
isim uzaynn bir paras olan standart Exception snfndan tretilmelidir. Bylece, tm kural
d durumlar Exceptionn birer alt snfdr.
SystemException ve ApplicationException, Exceptiondan tretilir. Bunlar
C#ta tanml olan iki genel kategoriyi desteklerler: C#n alma zaman sistemi (yani,
Common Language Runtime) tarafndan retilenler ve uygulama programlar tarafndan
retilenler. Ne SystemException ne de ApplicationException, Exceptiona bir ey
eklemez. Bunlar sadece, iki farkl kural d durum hiyerariisinin en stnde yer alan
durumlar tanmlarlar.
C#ta, SystemExceptiondan tretilen birka standart kural d durum tanmlanmtr.
rnein, sfra blme denemesinde bulunulduunda DivideByzeroException olarak bilinen
bir kural d durum retilir. Bu blmde daha sonra greceiniz gibi, kendi kural d durum
snfnz ApplicationExceptiondan treterek kendiniz oluturabilirsiniz.
BLM 13: KURAL DII DURUM YNETM

HERKES N C#
369
Kural D Durum Ynetimiyle lgili Esaslar
C#ta kural d durum ynetimi drt anahtar kelime araclyla gerekletirilir: try,
catch, throw ve finally. Bu anahtar kelimeler, birinin kullanmnn dierinin kullanmn
gerektirdii birbiriyle balantl bir alt sistem olutururlar. Bu blm boyunca bu anahtar
kelimelerin biri ayrntlaryla incelenecektir. Ancak, incelemeye balamadan nce, bunlarn her
birinin kural d durum ynetiminde nasl bir rol stlendii hakknda genel bilgi sahibi olmak
yararldr. imdi bunlarn nasl altklarna ksaca bir gz atalm.
Kural d durumlar izlemek istediiniz program ifadeleri bir try blou iinde yer alr.
Eer bir try blou iinde bir kural d durum meydana gelirse, sz konusu kural d durum
frlatlm olur. Kodunuz bu kural d durumu catch kullanarak yakalayabilir ve bunu
mantkl bir ekilde kontrol altna alr. Sistem tarafndan retilen kural d durumlar, otomatik
olarak C# alma zaman sistemi tarafndan frlatlr. Kural d bir durumu elle frlatmak iin
throw anahtar kelimesini kullann. try bloundan ktktan sonra kesinlikle altrlmas
gereken bir kod finally blouna yerletirilir.
try ve catchin Kullanm
Kural d durum ynetiminin znde try ve catch yer almaktadr. Bu anahtar kelimeler
birlikte alrlar; catch olmadan try tek bana kullanamazsnz; trysz da catch olmaz.
try/catch kural d durum ynetim bloklarnn genel yaps u ekildedir:
try {
// hatalar izleyen kod blou
}
catch (KuralDTip1 exOb) {
// KuralDTip1 iin ynetici
}
catch (KuralDTip2 exOb) {
// KuralDTip2 iin ynetici
}
.
.
.
Burada KuralDTip, meydana gelen kural d durumun tipidir. Kural d bir durum
frlatldnda, karlk gelen catch ifadesi tarafndan yakalanr; sz konusu catch ifadesi
kural d durumu iler. Genel yapdan da grld gibi, bir try ile ilikili birden fazla catch
ifadesi olabilir. Hangi catch ifadesinin altrlacan kural d durumun tipi belirler. Yani,
catch ifadesinde belirtilen kural d durum tipi, kural d durum ile eleirse, sz konusu
catch ifadesi altrlr (dierlerinin tm atlanr). Kural d bir durum yakalandnda exOb
bunun deerini alacaktr.
Aslnda exObu belirtmek istee baldr. Eer kural d durum yneticisinin kural d
durum nesnesine erimesi gerekmiyorsa (ki, bu ska rastlanlan bir durumdur), exObu

HERKES N C#
KISIM I C# DL

370
belirtmeye gerek yoktur. Bu nedenle, bu blmdeki rneklerin birounda exOb
belirtilmeyecektir.
te nemli bir husus: Eer hi kural d durum frlatlmamsa, try blou normal olarak
sona erer ve tm catch ifadeleri de pas geilir. Program, son catch ifadesinin peinden gelen
ifade ile devam eder. Yani, catch ifadeleri yalnzca bir kural d durum frlatldnda
altrlrlar.
Basit Bir Kural D Durum rnei
Aada, bir kural d durumun nasl izleneceini ve yakalanacan gsteren bir rnek yer
almaktadr. Bildiiniz gibi, bir diziyi snrlar dnda indekslemeye almak hatal bir
durumdur. Byle bir durum meydana gelince, C# alma zaman sistemi C#ta tanml,
standart bir kural d durum olan IndexOutOfRangeException frlatr. Aadaki
program kastl olarak bu tr bir kural d durum oluturur ve sonra da onu yakalar:
//Kural disi durum yonetimini gosterir.

using System;

class ExcDemo1 {
public static void Main() {
int[] nums = new int[4];

try {
Console.WriteLine(Before exception is generated.);

/* Indeksin sinir disinda oldugunu gosteren bir kural
disi durum uret */
for(int i = 0; i < 10; i++) {
nums[i] = i;
Console.WriteLine(nums[{0}]: {1}, i, nums[i]);
}

Console.WriteLine(this won't be displayed);
}
catch (IndexOutOfRangeException) {
// kural disi durumu yakala
Console.WriteLine(Index out-of-bounds!);
}
Console.WriteLine(After catch statement.);
}
}
Bu program aadaki kty ekranda gsterir:
Before exception is generated.
nums[0]: 0
nums[1]: 1
nums[2]: 2
nums[3]: 3
Index out-of-bounds!
BLM 13: KURAL DII DURUM YNETM

HERKES N C#
371
After catch statement.
Dikkat ederseniz, nums drt elemandan oluan bir int dizisidir. Ancak, for dngs
nums 0dan 9a kadar indekslemeye almaktadr. Bu durum, indeks deeri olarak 4e
eriilmeye alldnda IndexOutOfRangeExceptionn meydana gelmesine neden olur.
Olduka ksa bir program olmasna ramen yukardaki program, kural d durum
ynetimiyle ilgili birka nemli noktaya k tutmaktadr. ncelikle, hata durumu olup
olmadn izlemek istediiniz kod, bir try blou iine yerletirilir. kincisi, bir kural d
durum ortaya ktnda (bu rnekte, for dngs iinde nums snrlar dna taacak ekilde
indekslemeye almak kural d duruma neden olur), sz konusu kural d durum try
bloundan frlatlr ve catch ifadesi tarafndan yakalanr. Bu aamada kontrol catche
aktarlr ve try blou sona erer. Yani, catch arlmaz. Bunun yerine, programn almas
catchten itibaren devam eder. Bylece, indeks snr dna tatktan sonra, takip eden
WriteLine() ifadesi asla altrlmayacaktr. catch ifadesi altrldktan sonra program
kontrol catchi takip eden ifadelerle srecektir. Yani, programn almasnn normal olarak
devam edebilmesi iin kural d duruma neden olan problemi zme grevi, kural d durum
yneticisine aittir.
catch ifadesinde hi parametre belirtilmediine dikkat edin. Daha nce bahsedildii gibi,
yalnzca kural d durum nesnesine eriim gerekli olduunda bir parametreye ihtiya duyulur.
Baz durumlarda kural d durum nesnesinin deeri, hata hakknda ek bilgi elde etmek
amacyla kural d durum yneticisi tarafndan kullanlabilir Fakat, birok durumda yalnzca
kural d bir durumun meydana geldiini bilmek yeterlidir. Bu nedenle, yukardaki programda
olduu kural d durum yneticisinde catcth parametresinin eksik oluu, olaand bir du-
rum deildir.
Daha nce akland gibi, try blou tarafndan hi kural d bir durum frlatlmamsa,
catch ifadelerinden hibiri altrlmayacaktr ve program kontrol catch ifadesinin
peinden devam edecektir. Bunu dorulamak iin yukardaki rnekteki for dngsn u
halden
for(int i = 0; i < 10; i++) {
una deitirin:
for(int i = 0; i < nums.Length; i++) {
Artk dng hibir zaman numsn snrlar dna kmaz. Bylece, hi kural d bir
durum ortaya kmaz ve catch blou altrlmaz.
kinci Bir Kural D Durum rnei
try blou iinde altrlan kodun tmnn kural d durumlar asndan izlendiini
kavramak nemlidir. try blou iinden arlan bir metot tarafndan retilebilecek kural d
durumlar da buna dahildir. try blou iinden arlan bir metot tarafndan frlatlan bir kural

HERKES N C#
KISIM I C# DL

372
d durum sz konusu try blou tarafndan yakalanabilir. Elbette burada, metodun kendisinin
bu kural d durumu yakalamadn varsayyoruz. rnein, u geerli bir programdr:
/* Kural disi bir durum bir metot tarafindan uretilebilir ve
bir baska metot tarafindan yakalanabilir. */

using System;

class ExcTest {
// Kural disi bir durum uret.
public static void genException() {
int[] nums = new int[4];

Console.WriteLine(Before exception is generated.);

/* indeksin sinir disinda oldugunu gosteren
bir kural disi durum uret. */
for(int i = 0; i 10; i++) {
nums[i] = i;
Console.WriteLine(nums[{0}]: {1}, i, nums[i]);
}

Console.WriteLine(this wont be displayed);
}
}

class ExcDemo2 {
public static void Main() {
try {
ExcTest.genException();
}
catch (IndexOutOfRangeException) {
// kural disi durumu yakala
Console.WriteLine(Index out-of-bounds!);
}
Console.WriteLine(After catch statement.);
}
}
Bu program aadaki kty retir. Bu kt, daha nce gsterilen, programn ilk
versiyonundan elde edilen ktnn aynsdr:
Before exception is generated.
nums[0]: 0
nums[1): 1
nums[2]: 2
nums[3]: 3
Index out-of-bounds!
After catch statement.
genException(), try blou iinden arld iin bunun rettii (ve yakalamad)
kural d durum Main() iindeki catch tarafndan yakalanr. Ancak, genException() eer
kural d durumu yakalam olsayd, Main()e tekrar geri aktarlmayacakt. Bunu kavrayn.
BLM 13: KURAL DII DURUM YNETM

HERKES N C#
373
Yakalanmayan Kural D Durumlarn Sonular
nceki programda olduu gibi, C#n standart kural d durumlarndan birini yakalamann
salad bir yan fayda da vardr: Bu durum, programn normal d olarak sona ermesini nler.
Kural d bir durum frlatldnda bir yerlerdeki bir para kod tarafndan bu kural d durum
yakalanmaldr. Genel olarak, eer programnz kural d bir durumu yakalamazsa, bu kural
d durum C# alma zaman sistemi tarafndan yakalanacaktr. Buradaki sorun, alma za-
man sisteminin hatay rapor edecek ve program sonlandracak olmasdr. Sz gelii, bu r-
nekte indeksin snr dna tamasndan kaynaklanan kural d durum program tarafndan
yakalanmamaktadr:
// Birakin C# calisma zaman sistemi hatayi kontrol altina alsin.

using System;

class NotHandled {
public static void Main() {
int[] nums = new int[4];

Console.WriteLine(Before exception is generated.);

/* Indeksin sinir disinda oldugunu gosteren
bir kural disi durum uret. */
for(int i = 0; i < 10; i++) {
nums[il = i;
Console.WriteLine(nums[{0}]: {1}, i, nums[i]);
}
}
}
Dizi indeks hatas meydana gelince, programn almas durdurulur ve aadaki hata me-
saj ekranda gsterilir:
Unhandled Exception: System.IndexOutOfRangeException:
Index was outside the bounds of the array.
at NotHandled.Main()
Hatalar ayklarken bu tr bir mesajn sizin iin yararl olmasnn yan sra, bu en azndan,
bakalarnn grmesini istemediiniz bir mesaj da olabilir. Programnzn kural d durumlar
kendisinin kontrol altna almas ite bu sebepten nemlidir.
Daha nce bahsedildii gibi, kural d durumun tipi catch ifadesinde belirtilen tip ile
elenmelidir. Eer elenmiyorsa, kural d durum yakalanmayacaktr. rnein, aadaki
program DivideByZeroException (C#n standart kural d durumlarndan bir bakas)
bir catch ifadesinde kullanarak bir dizinin snr hatalarn yakalamaya almaktadr. Dizinin
snr ald zaman IndexOutOfRangeException retilir, fakat bu, catch ifadesi
tarafndan yakalanmayacaktr. Bu durum, programn normal olmayan biimde sona ermesiyle
sonulanr.
// Bu calismayacaktir!

HERKES N C#
KISIM I C# DL

374

using System;

class ExcTypeMismatch {
public static void Main() {
int[] nums = new int[4];

try {
Console.WriteLine(Before exception is generated.);

/* Indeksin sinir disinda oldugunu gosteren
bir kural disi durum uret. */
for(int i = 0; i < 10; i++) {
nums[i] = i;
Console.WriteLine(nums[{0}]: {1}, i, nums[i]);
}
Console.WriteLine(this won't be displayed);
}
/* DivideByZeroException ile bir dizinin sinir hatalarini
yakalayamassiniz. */
catch(DivideByZeroException) {
// kural disi durumu yakala
Console.WriteLine(Index out-of-bounds!);
}
Console.WriteLine(After catch statement.);
}
}
kt aada gsterilmitir:
Before exception is generated.
nums[0]: 0
nums[1]: 1
nums[2]: 2
nums[3]: 3

Unhandled Exception: System.IndexOutOfRangeException:
Index was outside the bounds of the array.
at ExcTypeMismatch.Main()
ktnn da gsterdii gibi, DivideByZeroException iin kullanlan bir catch ifadesi
IndexOutOfRange kural d durumunu yakalamayacaktr.
Kural D Durumlar, Hatalar Zarife Kontrol Altna
Almanza Olanak Tanr
Kural d durum ynetiminin salad kilit avantajlardan biri, programnzn hatalara
tepki vermesini ve daha sonra almasn srdrmesini mmkn klmasdr. rnein, bir
dizinin elemanlarn bir baka dizinin elemanlarna blen aadaki rnei ele aln. Eer sfra
blme meydana gelirse DivideByZeroException retilir. Programda bu kural d durum,
hatann rapor edilmesi ve ardndan almann srdrlmesiyle kontrol altna alnr. Bylece,
BLM 13: KURAL DII DURUM YNETM

HERKES N C#
375
sfra blme giriimi, programn almas srasnda beklenmedik ekilde ortaya kan ve
programn sona ermesiyle sonulanan bir hataya neden olmaz. Bunun yerine, hata zarife
kontrol altna alnr ve bu sayede programn almasn srdrmesine olanak tannm olur.
// Hatay zarifce kontrol altna alir ve calsmayi surdurur.

using System;

class ExcDemo3 {
public static void Main() {
int[] numer = { 4, 8, 16, 32, 64, 128 };
int[] denom = { 2, 0, 4, 4, 0, 8 };

for(int i = 0; i < numer.Length; i++) {
try {
Console.WriteLine(numer[i] + / +
denom[i] + is +
numer[i] / denom[i]);
}
catch (DivideByZeroException) {
// kural disi durumu yakala.
Console.WriteLine(Cant divide by Zero!);
}
}
}
}
Programn kts aada gsterilmitir:
4 / 2 is 2
Cant divide by Zero!
16 / 4 is 4
32 / 4 is 8
Cant divide by Zero!
128 / 8 is 16
Bu rnek bir baka nemli hususa iaret ediyor: Bir kural d durum bir kez kontrol altna
alndktan sonra sistemden dar karlr. Bu yzden, programda, dngnn her tekrarnda
try blouna yeniden girilir, nk nceki kural d durumlarn her biri kontrol altna
alnmtr. Bu sayede, programnzn tekrarlanan hatalar kontrol altna almas mmkn olur.
Birden Fazla catch fadesinin Kullanm
Bir try blou ile birden fazla catch ifadesini ilikilendirebilirsiniz. Aslnda bu yaygn bir
yaklamdr. Ancak, her bir catch, farkl tipte bir kural d durumu yakalamaldr. rnein,
aada gsterilen program hem dizi snrlarndan kaynaklanan hatalar, hem de sfra blme
hatalarn yakalar:
// Birden fazla catch ifadesi kullanir.

using System;


HERKES N C#
KISIM I C# DL

376
class ExcDemo4 {
public static void Main() {
// Bu ornekte numer, denomdan daha uzundur.
int[] numer = { 4, 8, 16, 32, 64, 128, 256, 512 };
int[] denom = { 2, 0, 4, 4, 0, 8 };

for(int i = 0; i < numer.Length; i++) {
try {
Console.WriteLine(numer[i] + / +
denom[i] + is +
numer[i] / denom[i]);
}
catch (DivideByZeroException) {
// kural disi durumu yakala
Console.WriteLine(Can't divide by Zero!);
}
catch (IndexOutOfRangeException) {
// kural disi durumu yakala
Console.WriteLine(No matching element found.);
}
}
}
}
Bu program aadaki kty retir:
4 / 2 is 2
Cant divide by Zero!
16 / 4 is 4
32 / 4 is 8
Cant divide by Zero!
128 / 8 is 16
No matching element found.
No matching element found.
ktnn da dorulad gibi, catch ifadelerinin her biri kendisine karlk gelen kural d
durum tipine tepki verir.
catch deyimleri genel olarak programda yer aldklar sra ile kontrol edilirler. Yalnzca
elenen ifade gereklenir. Dier catch bloklarnn hi biri dikkate alnmaz.
Kural D Durumlarn Tmn Yakalamak
Bazen hangi tipte olursa olsun kural d durumlarn tmn yakalamak isteyeceksiniz,
Bunu gerekletirmek iin parametresi belirtilmeyen bir catch ifadesi kullann. Bu, bir
tmn yakala yneticisi oluturacaktr. Bu tr bir ynetici, kural d durumlarn tmnn
programnz tarafndan kontrol altna alndn garanti etmek istediinizde kullanl olur.
rnein, aadaki programda tek catch ifadesi tmn yakala trndendir. Bu ifade,
program tarafndan retilen IndexOutOfRangeException ve DivideByZeroExceptionn
her ikisini de yakalar.
// Tumunu yakala catch ifadesi kullanir.
BLM 13: KURAL DII DURUM YNETM

HERKES N C#
377

using System;

class ExcDemo5 {
public static void Main() {
// Bu ornekte numer, denomdan daha uzundur.
int[] numer = { 4, 8, 16, 32, 64, 128, 256, 512 };
int[] denom = { 2, 0, 4, 4, 0, 8 };

for(int i = 0; i < numer.Length; i++) {
try {
Console.WriteLine(numer[i] + / +
denom[i] + is +
numer[i] / denom[i]);
}
catch {
Console.WriteLine(Some exception occurred.);
}
}
}
}
kt aada gsterilmitir:
4 / 2 is 2
Some exception occurred.
16 / 4 is 4
32 / 4 is 8
Some exception occurred.
128 / 8 is 16
Some exception occurred.
Some exception occurred.
Tmn yakalayan bir catch kullanrken bir konunun hatrda tutulmas gereklidir: Bu
tr bir catch, catch sekans iindeki son catch ifadesi olmaldr.
try Bloklarn Kmelemek
Bir try blou bir bakasnn iine yerletirilip, kmelenebilir. teki try blou tarafndan
retilen ancak bu try ile ilikili bir catch tarafndan yakalanmayan bir kural d durum,
dtaki try blouna aktarlr. rnein, aadaki programda IndexOutOfRangeException,
iteki try blou tarafndan deil, dtaki try blou tarafndan yakalanmaktadr:
// Ic ice kumelenmis try blogu kullanir.

using System;

class NestTrys {
public static vold Main() {
// Bu ornekte numer, denomdan daha uzundur.

int[] numer = { 4, 8, 16, 32, 64, 128, 256, 512 };
int[] denom = { 2, 0, 4, 4, 0, 8 };

HERKES N C#
KISIM I C# DL

378

try {
// distaki try
for(int i = 0; i < numer.Length; i++) {
try { // kumelenmis try
Console.WriteLine(numer[i] + / +
denom[i] + is +
numer[i] / denom[i]);
}
catch (DivideByZeroException) {
// kural disi durumu yakala
Console.WriteLine(Cant divide by Zero!);
}
}
}
catch (IndexOutOfRangeException) {
// kural disi durumu yakala

Console.WriteLine(No matching element found.);
Console.WriteLine(Fatal error -- program terminated.);
}
}
}
Programdan elde edilen kt aadaki gibidir:
4 / 2 is 2
Cant divide by Zero!
16 / 4 is 4
32 / 4 is 8
Cant divide by Zero!
128 / 8 is 16
No matching element found.
Fatal error -- program terminated.
Bu rnekte, iteki try tarafndan kontrol altna alnabilecek bir kural d durum - sfra
blme hatas - programn almasna imkan verir. Ancak, dtaki try tarafndan dizi
snrlaryla ilgili bir hata yakalanr ve bu, programn sonlandrlmasna neden olur.
Yukardaki program nemli bir noktaya k tutmaktadr, ki bu durum genelletirilebilir.
Genellikle kmelenmi try bloklar, farkl hata kategorilerinin farkl ekillerde kontrol altna
alnmalarna olanak tanmak iin kullanlr. Baz hata tipleri bir faciadr; stelik bu tr hatalar
dzeltilemeyebilir. Bazlar ise nemsizdir ve annda kontrol altna alnabilir. Programclarn
birou en iddetli hatalar yakalamak iin dtaki try blounu kullanrlar; bylece, iteki try
bloklarnn daha az neme sahip hatalar kontrol altna almalarna imkan vermi olurlar. Dtaki
try blounu ayrca, iteki blok tarafndan kontrol altna alnmayan hatalar iin tmn ya-
kalayan bir blok olarak da kullanabilirsiniz.


BLM 13: KURAL DII DURUM YNETM

HERKES N C#
379
Bir Kural D Durum Frlatmak
nceki rnekler C# tarafndan otomatik olarak retilen kural d durumlar
yakalamlard. Ancak, throw ifadesini kullanarak bir kural d durumu elle frlatmak da
mmkndr. Bunun genel yaps aada gsterilmitir:
throw exceptOb;
exceptOb, Exception snfndan tretilmi bir kural d durum snrna ait bir nesne
olmaldr.
te, DivideByZeroExceptionn elle frlatarak throw ifadesini gsteren bir rnek:
// Bir kural disi durumu elle firlatmak.

using System;

class ThrowDemo {
public static void Main() {
try {
Console.WriteLine(Before throw.);
throw new DivideByZeroException();
}

catch (DivideByZeroException) {
// kural disi durumu yakala
Console.WriteLine(Exception caught.);
}

Console.WriteLine(After try/catch block.);
}
}
Programn kts aadaki gibidir:
Before throw.
Exception caught.
After try/catch block.
throw ifadesi iinde new kullanlarak DivideByZeroException'n nasl
oluturulduuna dikkat edin. throwun bir nesne frlattn hatrnzdan karmayn. Bu
nedenle, throwun frlatmas iin bir nesne oluturmalsnz - yani, yalnzca bir tip
frlatamazsnz. Bu rnekte bir DivideByZeroException nesnesi oluturmak iin varsaylan
yaplandrc kullanlmaktadr, fakat dier yaplandrclar da kural d durumlar iin
kullanlmak zere hazrdr.
ounlukla frlatacanz kural d durumlar, sizin oluturduunuz kural d durum
snflarnn rnekleri olacaktr. Bu blmn ileriki sayfalarnda greceiniz gibi, kendi kural
d durum snflarnz oluturmak kodunuz iindeki hatalar, programnzn genel kural d
durum ynetim stratejisinin bir paras olarak kontrol altna almanza imkan verir.

HERKES N C#
KISIM I C# DL

380
Kural D Durumu Yeniden Frlatmak
Bir catch ifadesi tarafndan yakalanan bir kural d durum, dtaki catch tarafndan da
yakalanabilsin diye yeniden frlatlabilir. Kural d bir durumu yeniden frlatmann en olas
nedeni, birden fazla kural d durum yneticisinin sz konusu kural d duruma erimesine
imkan vermektir. Sz gelii, bir kural d durum yneticisi bir kural d durumun belki bir
ynn idare etmektedir; ikinci bir ynetici ise bir dier ynyle ilgilenmektedir. Bir kural d
durumu yeniden frlatmak iin, aka bir kural d durumu belirtmeden yalnzca throwu
belirtmeniz yeterlidir. Yani, throwun u eklini kullanrsnz:
throw ;
Hatrlarsanz, bir kural d durumu yeniden frladnzda bu durum ayn catch ifadesi
tarafndan yeniden yakalanmayacaktr; bir sonraki catch ifadesine kayacaktr.
Aadaki program, bir kural d durumu yeniden frlatmay rneklemektedir. Bu kez
program, IndexOutOfRangeExceptionn yeniden frlatmaktadr.
// Kural disi bir durumu yeniden firlat.

using System;

class Rethrow {
public static void genException() {
// Bu ornekte numer, denomdan daha uzundur.
int[] numer ={ 4, 8, 16, 32, 64, 128, 256, 512 };
int[] denom ={ 2, 0, 4, 4, 0, 8 };

for(int i = 0; i < numer.Length; i++) {
try {
Console.WriteLine(numer[i] + / +
denom[i] + is +
numer[i] / denom[i]);
}
catch (DivideByZeroException) {
// kural disi durumu yakala
Console.WriteLine(Cant divide by Zero!);
}
catch (IndexOutOfRangeException) {
// kural disi durumu yakala
Console.WriteLine(No matching element found.);
throw; // kural disi durumu yeniden firlat

}
}
}
}

class RethrowDemo {
public static void Main() {
try {
Rethrow.genException();
BLM 13: KURAL DII DURUM YNETM

HERKES N C#
381
}
catch(IndexOutOfRangeException) {
// kural disi durumu yeniden yakala
Console.WriteLine(Fatal error +
program terminated.);
}
}
}
Bu programda sfra blme hatalar yerel olarak genException() tarafndan kontrol
altna alnmaktadr, fakat dizi snrlaryla ilgili bir hata yeniden frlatlmtr. Bu rnekte
IndexOutOfRangeException, Main() tarafndan kontrol altna alnmtr.
finallynin Kullanm
Kimi zaman try/catch bloundan ktktan sanra altrlmak zere bir kod blou
tanmlamak isteyeceksiniz. rnein, bir kural d durum, mevcut metodun vaktinden nce
dnmesine neden olarak metodu sona erdiren bir hataya yol aabilir. Ancak, sz konusu metot
kapatlmas gereken bir dosya ya da a balants am olabilir. Bu tr durumlara
programlamada ska rastlanr. C# bu tr durumlar kontrol alma almak iin kullanl bir
yntem sunmaktadr: finally.
Btr try/catch bloundan ktktan sonra altrlacak kod blounu belirtmek iin
try/catch sekansnn sonuna bir finally blou yerletirin. finally ieren bir
try/catch blounun genel ekli aadaki gibidir:
try {
// hatalar izleyen kod blou
}
catch (KuralDTip1 exOb) {
// KuralDTip1 iin ynetici
}
catch (KuralDTip2 exOb) {
// KuralDTip2 iin ynetici
}
.
.
.
finally {
// finally kodu
}
finally blou, program kontrol try/catch blounu terk eder etmez, bu duruma hangi
artlar neden olursa olsun gereklenecektir. Yani, try blou normal biimde sona erse de ya da
buna bir kural d durum neden olsa da, altrlacak en son kod finally tarafndan
tanmlanandr. Ayrca, try blou iindeki herhangi bir kod ya da buna karlk gelen catch
ifadelerinden herhangi biri sz konusu metottan dnyorsa finally blou gereklenir.
te bir finally rnei:

HERKES N C#
KISIM I C# DL

382
// finally kullanir.

using System;

class UseFinally {
public static void genException(int what} {
int t;
int[] nums = new int[2];

Console.WriteLine(Receiving + what);
try {
switch(what) {
case 0:
t = 10 / what; // sifira bolme hatasi uret
break;
case 1:
nums[4] = 4; // dizi indeks hatasi uret.
break;
case 2:
return; // try blogundan don.
}
}
catch (DivideByZeroException) {
// kural disi durumu yakala
Console.WriteLine(Cant divide by Zero!);
return; // return from catch
}
catch (IndexOutOfRangeException) {
// kural disi durumu yakala
Console.WriteLine(No matching element found.);
}
finally {
Console.WriteLine(Leaving try.);
}
}
}

class FinallyDemo {
public static void Main() {
for(int i = 0; i < 3; i++) {
UseFinally.genException(i);
Console.WriteLine();
}
}
}
te, programn rettii kt:
Receiving 0
Cant divide by Zero!
Leaving try.

Receiving 1
No matching element found.
Leaving try.
BLM 13: KURAL DII DURUM YNETM

HERKES N C#
383

Receiving 2
Leaving try.
ktdan da grld gibi, try blou ne ekilde terk edilirse edilsin finally blou her
koulda gereklenmektedir.
Kural D Durumlara Yakndan Bir Bak
imdiye kadar kural d durumlar yakalamaktayz, fakat kural d durum nesnesinin
kendisi ile ilgili henz hi bir ey yapmadk. nceden de bahsedildii gibi, catch ifadesi bir
kural d durum tipi ve parametresi belirtmenize imkan vermektedir. Sz konusu parametre
kural d durum nesnesini alr. Tm kural d durumlar Exceptiondan tretildigi iin tm
kural d durumlar Exceptionn tanmlad yeleri desteklerler. Bu blmde
Exceptionn en yararl yelerinden ve yaplandrclarndan birkan inceleyeceiz ve
catch parametresinin uygun bir kullanmn greceiz.
Exceptionda birka zellik tanmldr. Bunlardan en ilgin Message, StackTrace
ve TargetSitedr. Bunlarn tm salt okunurdur. Message, hatann zn tarif eden bir
karakter katar ierir. StackTrace, kural d duruma yol aan arlarn ynn (stack) tutan
bir karakter katar ierir. TargetSite ise kural d durumun hangi metot tarafndan
retildiini belirten bir nesne alr.
Exceptionda ayrca birka metot da tanmldr. Bunlarn iinde en sk kullanacanz
metot, sz konusu kural d durumu tarif eden bir karakter katar dndren ToString()dir.
Bir kural d durum WriteLine() zerinden gsterilince ToString() otomatik olarak
arlr, rnein.
Aadaki program bu zellikleri ve metotlar gstermektedir:
// Exception uyelerinin kullanimi.

using System;

class ExcTest {
public static void genException() {
int[] nums = new int[4];

Console.WriteLine(Before exception is generated.);

/* Indeksin sinir disinda oldugunu gosteren
bir kural disi durum ret. */
for(int i = 0; i < 10; i++) {
nums[i] = i;
Console.WriteLine(nums[{0}]: {1}, i, nums[i]);
}

Console.WriteLine(this wont be displayed);
}

HERKES N C#
KISIM I C# DL

384
}

class UseExcept {
public static void Main() {

try {
ExcTest.genException();
}
catch (IndexOutOfRangeException exc) {
// kural disi durumu yakala
Console.WriteLine(Standard message is: );
Console.WriteLine(exc); // ToString()i cagirir
Console.WriteLine(stack trace: + exc.StackTrace);
Console.WriteLine(Message: + exc.Message);
Console.WriteLine(TargetSite: + exc.TargetSite);
}
Console.WriteLine(After catch statement.);
}
}
Bu programn kts aada gsterilmitir:
Before exception is generated.
nums[0]: 0
nums[1]: 1
nums[2]: 2
nums[3]: 3
Standard message is:
System.IndexOutOfRangeException: Index was outside the bounds of
the array.
at ExcTest.genException()
at UseExcept.Main()
Stack trace: at ExcTest.genException()
at UseExcept.Main()
Message: Index was outside the bounds of the array.
TargetSite: Void genException()
After catch statement.
Exceptionda drt yaplandrc tanmldr. Bunlardan en sk kullanlan ikisi aada
gsterilmitir:
Exception()
Exception(string str)
lki varsaylan yaplandrcdr. kincisi ise, sz konusu kural d durumla ilikili Message
zelliini belirtir. Kendi kural d snflarnz olutururken bu yaplandrclarn her ikisini de
uygulamalsnz.
Ska Kullanlan Kural D Durumlar
System isim uzaynda birka tane standart, derleyiciyle birlikle gelen kural d durum
tanmldr. Bunlarn tm SystemExceptiondan tretilmitir, nk alma zamannda
hatalar ortaya knca bu kural d durumlar Common Language Runtime tarafndan retilirler,
BLM 13: KURAL DII DURUM YNETM

HERKES N C#
385
C#ta tanml standart kural d durumlarn daha ska kullanlanlarndan birka Tablo 13.1de
gsterilmektedir.

TABLO 13.1: System sim Uzaynda Tanml, Ska Kullanlan Kural D Durumlar


Kural D Durum Anlam
ArrayTypeMismatchException Depolanmakta olan deerin tipi, dizinin tipiyle uyumsuzdur.
DivideByZeroException Sfra blme giriimi.
IndexOutOfRangeException Dizi indeksi snr dna tamtr.
InvalidCastException Programn almas srasnda bir tip atamas geerli deildir.
OutOfMemoryException Yeterince serbest bellek olmad iin new ars baarsz
olmutur.
OverflowException Aritmetik tama meydana gelmitir.
NullReferenceException Null referans yani, bir nesneye atfta bulunmayan bir
referans zerinde ilem yaplmaya allmtr.
StackOverflowException Yn tamtr.
Tablo 13.1deki kural d durumlarn birou kendi kendilerini aklayacak kadar nettir.
Yalnz, bunun tek istisnas NullReferenceException olabilir. Bu kural d durum, bir null
referans sanki bir nesneye referansta bulunuyormu gibi kullanlmaya alldnda frlatlr -
sz gelii, bir null referans zerinden bir metodu armay denediinizde... Null referans,
herhangi bir nesneye iaret etmeyen bir referanstr. Null referans oluturmann bir yolu, sz
konusu referansa null anahtar kelimesini kullanarak aka bir deer atamaktr. Null
referanslar daha az belli olan dier yntemlerle de ortaya kabilir. te,
NullReferenceException gsteren bir program:
// NullReferenceExceptioni kullanir.

using System;

class X {
int x;
public X(int a) {
x = a;
}

public int add(X o) {
return x + o.x;
}
}

// NullReferenceExceptioni goster.
class NREDemo {

HERKES N C#
KISIM I C# DL

386
public static void Main() {
X p = new X(10);
X q = null; // qya acikca null degeri ataniyor
int val;

try {
val = p.add(q); // bu, kural disi bir duruma yol acacaktir
}
catch (NullReferenceException) {
Console.WriteLine(NullReferenceException!);
Console.WriteLine(fixing...\n);

// simdi, bunu duzelt
q = new X(9);
val = p.add(q);
}

Console.WriteLine(val is {O}, val);
}
}
Programn kts aadaki gibidir:
NullReferenceException!
fixing...

val is 19
Programda X adnda bir snf oluturulur, Xin iinde x adnda bir ye ve add() metodu
tanmlanr. add(), kendisini aran nesnenin xini, parametre olarak aktarlan nesnenin xi ile
toplar. Main()de iki X nesnesi oluturulur. Bunlardan ilkine, yani pye ilk deer atanr. kinci-
sine, yani qya ilk deer atanmaz. Bunun yerine, qya aka null deeri atanr. Sonra, q
argman olacak ekilde p.meth() arlr. q bir nesneye referansta bulunmad iin q.x
deerini elde etmeye ynelik bir giriimde bulunulunca NullReferenceException retilir.
Enteresan bir kural d durum ise, sistem ynnda tama meydana geldiinde frlatlan
StackOverflowExceptiondr. Byle bir durum, yinelenen bir metot kontrolden ktnda
ortaya kabilir. Yinelenmeyi fazlasyla kullanan bir program bu kural d durumu iz1emek
isteyebilir, bylece bu tr bir kural d durum meydana geldiinde uygun davranta
bulunabilir. Yine de dikkatli olun. Bu kural d durum frlatldnda sistem yn tamamen
tketilmi olduundan tr, yinelenen arlardan geri dnmeye balamak genellikle
yaplacak en iyi harekettir.
Kural D Durum Snflarn Tretmek
C#ta tanml standart kural d durumlar ska rastlanan hatalarn birounu kontrol altna
alyor olsa da, C#n kural d durum ynetim mekanizmas yalnzca bu hatalarla snrl
deildir. Aslnda, kural d durumlara ynelik C#n sahip olduu gcn bir paras, sizin
oluturduunuz kural d durumlar kontrol altna alma becerisinden kaynaklanmaktadr. Kendi
kodunuzdaki hatalar kontrol altna almak iin kendi oluturduunuz kural d durumlar
BLM 13: KURAL DII DURUM YNETM

HERKES N C#
387
kullanabilirsiniz. Kural d bir durum oluturmak kolaydr. Yapmanz gereken yalnzca
Exception snfndan tretilen bir snf tanmlamaktr. Genel bir kural olarak, sizin
tarafnzdan tanmlanan kural d durumlar ApplicationExceptiondan tretilmelidir,
nk uygulamayla balantl kural d durumlar iin ayrlm hiyerari budur. Tretilmi
snflarnzn gerekte bir eyler uygulamas gerekmez - bunlar kural d durum olarak
kullanmanza imkan veren bu kural d durumlarn tip sistemi iinde var olmalardr.
Sizin oluturduunuz kural d durum snflar, Exception tarafndan tanmlanan ve sizin
oluturduunuz snflarn kullanmna sunulan zelliklere ve metotlara otomatik olarak sahip
olacaktr. Kukusuz bu yelerin birini ya da daha fazlasn kendi oluturduunuz kural d du-
rum snflarnda devre d brakabilirsiniz.
te size, kendi oluturduumuz bir kural d durum tipinden yararlanan bir rnek. Blm
10un sonunda RangeArray adnda bir dizi snf gelitirilmiti. Hatrlayacanz gibi
RangeArray, balang ve biti indeksleri kullanc tarafndan belirtilen tek boyutlu int
dizilerini destekler. Sz gelii, -5 ile 27 arasnda uzanan bir dizi RangeArray iin kusursuz
uygunluktadr. Blm 10da eer indeks snr dna tamsa, RangeArray tarafndan tanmla-
nan zel bir hata deikeninin deeri ayarlanyordu. Bu, sz konusu hata deikeninin her
ilemden sonra RangeArrayi kullanan kod tarafndan kontrol edilmesi gerektii anlamna
geliyordu. Bu tr bir yaklam elbette hatalara ak ve biimsizdir. ok daha iyi bir tasarm, bir
aralk hatas ortaya ktnda RangeArrayin kendi oluturduumuz bir kural d durum
frlatmasn salamaktr. RangeArreyin aadaki versiyonda gerekletirilen tamamen
budur:
// RangeArray hatalari icin ismarlama Exception kullanir.

using System;

// RangeArray icin kural disi bir durum olustur.
class RangeArrayException : ApplicationException {
// Standard yapilandiricilari uygula
public RangeArrayException() : base() { }
public RangeArrayException(string str) : base(str) { }

// RangeArrayException icin ToStringi devre disi birak.
public override string ToString() {
return Message;
}
}

// RangeArrayin gelistirilmis bir versiyonu.
class RangeArray {
// private veriler
int[] a; // temel olusturan diziye referans
int lowerBound; // en kucuk indeks
int upperBOund; // en buyuk indeks

int len; // Length ozelligi icin temel olarak kullanlan degisken
// Buyuklugu verilen diziyi kur.

HERKES N C#
KISIM I C# DL

388
public RangeArray(int low, int high) {
high++;
if(high <= low) [
throw new RangeArrayException(Low index not less
than high.);
}
a = new int[high - low|;
len = high - low;

lowerBound = low;
upperBound = --high;
}

// Salt okunur Length ozelligi.
public int Length {
get {
return len;
}
}

// Bu, RangeArray icin indeksleyicidir.
public int this[int index] {
// Bu, get erisimcisidir.
get {
if(ok(index)) {
return a[index - lowerBound];
} else {
throw new RangeArrayExceptionf(Range Error.);
}
}

// Bu, set erisimcisidir.
set {
if(ok(index)) {
a[index lowerBound] = value;
}
else throw new RangeArrayException(Range Error.);
}
}

// Indeks sinirlar icindeyse true dondur.
private bool ok(int index) {
if(index >= lowerBound & index <= upperBound) return true;
return false;
}
}

// Indeks-aralik dizisini goster.
class RangeArrayDemo {
public static void Main() {
try {
RangeArray ra = new RangeArray(-5, 5);
RangeArray ra2 = new RangeArray(1, 10);

// rayi goster
BLM 13: KURAL DII DURUM YNETM

HERKES N C#
389
Console.WriteLine(Length of ra: + ra.Length);

for(int i = -5; i <= 5; i++)
ra[i] = i;

Console.Write(Contents of ra: );
for(int i = -5; i <= 5; i++)
Console.Write(ra[i] + );

Console.WriteLine(\n);

// ra2yi goster
Console.WriteLine(Length of ra2: + ra2.Length);

for(int i = 1; i <= 10; i++)
ra2[i] = i;

Console.Write(Contents of ra2: );
for(int i = 1; i <= 10; i++)
Console.Write(ra2[i] + );

Console.WriteLine(\n);

} catch (RangeArrayException exc) {
Console.WriteLine(exc);
}

// Simdi birkac hata goster.
Console.WriteLine(Now generate some range errors.);

// Gecersiz bir yapilandirici kullan.
try {
RangeArray ra3 = new RangeArray(100, -10); // Hata

} catch (RangeArrayException exc) {
Console.WriteLine(exc);
}

// Gecersiz bir indeks kullan.
try {
RangeArray ra3 = new RangeArray(-2, 2);

for(int i = -2; i <= 2; i++)
ra3[i] = i;

Console.Write(Contents of ra3: );
for(int i = -2; i <= 10; i++) // aralik hatasi olustur
Console.Write(ra3[i] + );

} catch (RangeArrayException exc) {
Console.WriteLine(exc);
}
}
}

HERKES N C#
KISIM I C# DL

390
Programn kts aada gsterilmitir:
Length of ra: 11
Contents of ra: -5 -4 -3 -2 -1 0 1 2 3 4 5

Length of ra2: 10
Contents of ra2: 1 2 3 4 5 6 7 8 9 10

Now generate some range errors.
Low index not less than high.
Contents of ra3: -2 -1 0 1 2 Range Error.
Bir aralk hatas ortaya ktnda RangeArray, RangeArrayException tipinde bir
nesne frlatr. Bu snf ApplicetionExceptiondan tretilmitir. nceden akland gibi,
sizin oluturduunuz bir kural d durum snf normal olarak ApplicationExceptiondan
tretilmelidir. Bir RangeArrayin yaplandrlmas srasnda aralk hatasnn ortaya
kabileceine dikkat edin. Bu tr kural d durumlar yakalamak, programda da gsterildii
gibi RangeArray nesnelerinin try blou iinde kurulmalarn gerektirir. RangeArray,
hatalar rapor etmek iin bir kural d durum kullanarak artk tpk C#n standart tiplerinden
biri gibi davranmaktadr; bu nedenle, programn kural d durum ynetim mekanizmasna tam
olarak entegre edilebilir.
Biraz daha ilerlemeden nce, bu program biraz daha denemek isteyebilirsiniz. rnein,
ToString()in devre d brakld ifadeyi aklama haline brndrerek programdan
karmay deneyin ve sonular gzleyin. Ayrca, varsaylan yaplandrcy kullanarak bir kural
d durum oluturmaya aln ve C#n rettii varsaylan mesaj gzlemleyin.
Tretilmi Snflarla lgili Kural D Durumlar
Yakalamak
Temel ve tretilmi snflar ieren kural d durum tiplerini yakalamaya alrken catch
ifadelerini nasl sraladnza dikkat etmeniz gerekir, nk bir temel snfa karlk gelen bir
catch ifadesi ayn zamanda temel snftan tretilmi herhangi bir snf ile de elenecektir.
rnein, tm kural d durumlarn temel snf Exception olduu iin Exception
yakalamak tm olas kural d durumlar da yakalamak demektir. Elbette, catchi argmansz
kullanmak, daha nceden de bahsedildii gibi kural d durumlarn tmn yakalamak iin
daha net bir yntemdir. Bununla birlikte, tretilmi snflarla ilgili kural d durumlar
yakalamak dier balamlarda, zellikle kendi kural d durumlarnz oluturduunuzda ok
nemli olmaktadr.
Eer hem temel snf tipindeki hem de tretilmi snf tipindeki kural d durumlar
yakalamak istiyorsanz, catch sekans iine nce tretilmi snf yerletirin. Bu ekilde
yapmazsanz, temel snf ayrca tretilmi snflarn tmn yakalayacaktr. Bu kural
uygulatmak iin sizin bir eyler yapmanza gerek yoktur, kural kendiliinden uygulanr; nk,
nce temel snf yerletirmek, tretilmi snfa karlk gelen catch ifadesi asla
BLM 13: KURAL DII DURUM YNETM

HERKES N C#
391
gereklenemeyecei iin eriilemeyecek kodun olumasna neden olabilir. C#ta eriilemeyen
catch ifadesi bir hatadr.
Aadaki program ExceptA ve ExceptB adnda iki kural d durum snf
oluturmaktadr. ExceptA, ApplicationExceptiondan tretilmektedir. ExceptB ise
ExceptAdan tretilmektedir. Program daha sonra her iki tipte bir kural d durum
frlatmaktadr.
// Turetilmis kural disi durumlar temel sinifla ilgili kural disi
// durumlardan once gelmelidir.

using System;

// Kural disi bir durum olutur.
class ExceptA : ApplicationException {
public ExceptA() : base() { }
public ExceptA(string str) : base(str) { }

public override string ToString() {
return Message;
}
}

// ExceptAdan turetilen kural disi bir durum olustur
class ExceptB : ExceptA {
public ExceptB() : base() { }
public ExceptB(string str) : base(str) { }

public override string ToString() {
return Message;
}
}

class OrderMatters {
public static void Main() {
for(int x = 0; x < 3; x++) {
try {
if(x == 0) throw new ExceptA(Caught an
ExceptA exception);
else if(x == l) throw new ExceptB(Caught an ExceptB
exception);
else throw new Exception();
}
catch (ExceptB exc) {
// kural disi durumu yakala
Console.WriteLine(exc);
}
catch (ExceptA exc) {
// kural disi durumu yakala
Console.WriteLine(exc);
}
catch (Exception exc) {
Console.WriteLine(exc);

HERKES N C#
KISIM I C# DL

392
}
}
}
}
Programn kts aada gsterilmitir:
Caught an ExceptA exception
Caught an ExceptB exception
System.Exception: Exception of type System.Exception was thrown.
at OrderMatters.Main()
catch ifadelerinin srasna dikkat edin. Bu ifadeler yalnzca bu ekilde sralanabilir.
ExceptB, ExceptAdan tretildii iin ExceptB iin catch ifadesi ExceptAya karlk
gelenden nce gelmelidir. Ayn ekilde, Exception (tm kural d durumlarn temel snf)
iin catch de en son olarak yer almaldr. Bunu kendi kendinize kantlamak iin catch
ifadelerini yeniden dzenlemeyi deneyin. Bu ekilde davranmak derleme hatasyla
sonulanacaktr.
Kural d durumlar kategorisini btnyle yakalamak, temel snfa ait catch ifadesinin
uygun kullanmlarndan biridir. rnein, diyelim ki bir aygt iin birtakm kural d durumlar
oluturuyorsunuz. Eer kural d durumlarn tmn ortak bir temel snftan tretirseniz, ne tr
bir problemin ortaya ktn tam olarak bilmeleri gerekmeyen uygulamalarn temel snfla
ilgili kural d durumu yakalamalar yeterlidir. Bylece kodun gereksiz yere tekrarlanmas
nlenmi olur.
checked ve unchecked Kullanm
C#ta ekstra bir zellik, aritmetik hesaplamalarda tama ile ilgili kural d durumlarn
retilmesiyle balantldr. Bildiiniz gibi, baz aritmetik hesaplama trlerinde hesaplamaya
katlan veri tiplerinin araln aan bir sonucun retilmesi mmkndr. Byle bir durum ortaya
knca sonucun tat (overflow) sylenir. rnein, aadaki sekans ele aln:
byte a, b, result;
a = 127;
b = 127;

result = (byte)(a * b);
Burada a ve bnin arpm byte deerinin menzilini aar. Bylece sonu, sonucun tipini
amaktadr.
C#, checked ve unchecked anahtar kelimelerini kullanarak tama durumunda
kodunuzun kural d bir durum frlatp frlatmayacan belirlemenize imkan verir. Bir deyimin
tamaya kar kontrol edileceini belirtmek iin checked kullann. Tamann dikkate
alnmayacan belirtmek iin unchecked kullann. Bu rnekte sonu, deyimin hedef tipine
sacak ekilde kesiliyor.
BLM 13: KURAL DII DURUM YNETM

HERKES N C#
393
checked anahtar kelimesi aada gsterilen iki genel yapya sahiptir. Bunlardan biri
belirli bir deyimi kontrol eder ve buna checkedin operatr formu denir, Dieri ise bir ifade
blounu kontrol eder.
checked (deyim)

checked {
// kontrol edilecek ifadeler
}
Burada deyim kontrol edilmekte olan deyimdir. Eer kontrol edilen bir deyim taarsa bir
OverflowException frlatlr.
unchecked anahtar kelimesinin de aadaki gibi iki genel yaps mevcuttur. Bunlardan
biri, belirli bir deyimin tamasn dikkate almayan operatr formudur. Dieri ise, bir ifade
blounun tamasn dikkate almaz.
unchecked (deyim)

unchecked {
// tamann dikkate alnmayaca ifadeler
}
Burada deyim, tama durumu kontrol edilmemekte olan deyimdir. Eer kontrol edilmeyen
bir deyim taarsa, taan ksmn kesilmesi sz konusu olacaktr. te, checked ve unchecked
birlikte gsteren bir program:
// checked ve unchecked kullanir.

using System;

class CheckedDemo {
public static void Main() {
byte a, b;
byte result;

a = 127;
b = 127;

try {
result = unchecked((byte)(a * b));
Console.WriteLine(Unchecked result: + result);

result = checked((byte)(a*b));
// Bu, kural disi duruma neden olur
Console.WriteLine(Checked result: + result);
}
catch (OverflowException exc) {
// kural disi durumu yakala
Console.WriteLine(exc);
}
}
}

HERKES N C#
KISIM I C# DL

394
Programn kts aada gsterilmitir:
Unchecked result: 1
System.OverflowException: Arithmetic operation resulted in an
overflow.
at CheckedDemo.Main()
Apak grld zere, kontrol edilmeyen deyim sonucun kesilmesine neden olmutur.
Kontrol edilen deyimi ise bir kural d duruma yol amtr.
Yukardaki program tek bir deyim iin checked ve uncheckedin kullanmn
gstermitir. Aadaki program ise checked ve uncheckedin bir ifade blou ile nasl
kullanldn gstermektedir.
// checked ve uncheckedin ifade bloklaryla birlikte kullanimi.

using System;

class CheckedBlocks {
public static void Main() {
byte a, b;
byte result;

a = 127;
b = 127;

try {
unchecked {
a = 127;
b = 127;
result = unchecked((byte)(a * b));
Console.WriteLine(Unchecked result: + result);

a = 125;
b = 5;
result = unchecked((byte)(a * b));
Console.WriteLine(Unchecked result: + result);
}
checked {
a = 2;
b = 7;
result = checked((byte)(a * b)); // bu, tamam
Console.WriteLine(Checked result: + result);

a = 127;
b = 127;
result = checked((byte)(a * b));
// bu, kural disi duruma neden olur
Console.WriteLine(Checked result: + result);
}
}
catch (OverflowException exc) {
// kural disi durumu yakala
Console.WriteLine(exc);
BLM 13: KURAL DII DURUM YNETM

HERKES N C#
395
}
}
}
Programn kts aadaki gibidir:
Unchecked result: 1
Unchecked result: 113
Checked result: 14
System.OverflowException: Arithmetic operation resulted in an overflow.
at CheckedBlocks.Main()
Grdnz gibi; kontrol edilmeyen blok, sonucun kesilmesine neden olan bir tamayla
sonulanmaktadr. Kontrol edilen blok iinde bir tama meydana gelince kural d bir durum
ortaya tkmtr.
checked veya unchecked kullanmaya gerek duyabilecek olmanzn bir nedeni udur;
Tamann kontroll ya da kontrolsz olmas durumu, bir derleyici seenei ayarlanarak ve
programn alma ortamnn kendisi tarafndan belirlenir. Bu nedenle, baz program trleri iin
en iyisi, tama kontrol durumunu aka belirtmektir.



O N D R D N C B L M

I/O KULLANIMI























14
BLM 14: I/O KULLANIMI

HERKES N C#
397
Elinizdeki kitabn ilk blmlerinde C# I/O (giri/k) sisteminin baz paralar, sz gelii
Console.WriteLine() kullanlmt; fakat, bu blmlerde pek fazla zel aklama
salanmamt. C# I/O sistemi snf hiyerarisi zerine kurulduu iin ncelikle snflar,
kaltm ve kural d durumlar ele almadan C# I/O sistemini teorisi ve ayrntlaryla sunmak
mmkn olmayacakt. imdi C#n I/Oya ynelik yaklamn ayrntlaryla incelemenin vakti
geldi. C#, .NET Framework tarafndan tanmlanan I/O sistemini ve ilgili snflar
kullandndan dolay, I/Onun C# bnyesinde ele alnmas ayn zamanda .NET I/O sisteminin
de genel olarak ele alnmas demektir.
Bu blmde C#n hem konsol I/O, hem de dosya I/Osu ile ilgili yaklamlar
incelenmektedir. C#n I/O sisteminin olduka byk olduu konusunda sizi nceden uyaralm.
Bu blmde en nemli ve en ok kullanlan zellikler anlatlmaktadr.
C#n I/O Sistemi, Aklar zerine Kurulmutur
C# programlar I/Oyu aklar araclyla gerekletirirler. Ak (stream), bir bilgi reten
ya da tketen bir soyutlamadr. Bir ak, C# I/O sistemi tarafndan fiziksel bir aygta balanr.
Tm aklar, bal olduklar fiziksel cihazlar farkllk gsterse dahi, ayn ekilde davranmaldr.
Bylece, I/O snflar ve metotlar pek ok tipte cihaza uygulanabilir. rnein, konsola bir
eyler yazdrmak iin kullandnz metotlarn aynlar, disk dosyasna yazdrmak iin de
kullanlabilir.
Byte Aklar ve Karakter Aklar
En alt dzeyde, tm C# I/O Sistemleri bytelar zerinde ilem grr. Bu akla yatkndr,
nk I/O ilemleri asndan dnldnde aygtlarn birou byte tabanldr. Yine de, biz
insanolu iletiim iin karakterleri kullanmay ska tercih ederiz. C#ta char tipinin 16 bit,
byte tipinin ise 8 byte olduunu hatrlayn, Eer ASCII karakter setini kullanyorsanz char
ve byte arasnda kolaylkla dnm yapabilirsiniz; char deerinin st (high-order) byten
dikkate almamanz yeterlidir. Fakat bu yaklam geriye kalan Unicode karakterleri iin ie
yaramaz, nk bu karakterler iin her iki byte da gereklidir. Bu nedenle, byte aklar
karakter tabanl I/O ilemlerini kontrol altna almak iin tam olarak uygun deildir. Bu
problemi zmek amacyla C#ta bir byte akn, karakter akna dntren birka snf
tanmldr. Bu snflar, bytetan char'a ve chardan bytea dnmleri sizin adnza
otomatik olarak ele alrlar.
nceden Tanml Aklar
System isim uzayn kullanan programlarn tmnn kullanmna hazr olan, nceden
tanml ak mevcuttur. Bu aklar Console.In, Console.Out ve Console.Error
adndaki zellikler araclyla ortaya kar. Console.Out standart kt akyla ilgilidir.
Varsaylan kt ak konsoldur. Console.WriteLine() ardnzda rnein,
enformasyon otomatik olarak Console.Outa gnderilir. Console.In, standart giri ile

HERKES N C#
KISIM I C# DL

398
ilgilidir. Varsaylan standart giri, klavyedir. Console.Error, standart hata ak ile ilgilidir.
Bunun iin de varsaylan ak konsoldur. Ancak, bu aklar, uyumlu herhangi bir I/O cihazna
ynlendirilebilirler. Standart aklar karakter aklardr. Bu sayede; bu aklar, karakterleri
okur ve yazarlar.
Ak Snflar
C#ta hem byte ak hem de karakter ak snflar tanmldr. Bununla birlikte, karakter
ak snflar gerekte, altta yatan byte akn bir karakter akna dntren ve dnmleri
otomatik olarak ele alan bir ambalajdan ibarettir. Bu nedenle, karakter aklar mantksal olarak
ayr olmakla birlikte byte aklar zerine kurulurlar.
Tm ak snflar System.IO isim uzay iinde tanmldr. Bu snflar kullanmak iin
aadaki ifadeyi genellikle programnzn en stne yakn bir yerlere yerletireceksiniz:
using System.10;
Konsol giri ve klar iin System.IOyu belirtmek zorunda olmamanzn nedeni
Console snfnn System isim uzay iinde tanml olmasdr.
Stream Snf
C# aklarnn znde System.IO.Stream yer alr. Stream, byte akn simgeler, ayrca
tm dier ak snflar iin temel snf ilevini grr. Stream ayn zamanda zettir; yani, bir
Stream nesnesi rnekleyemezsiniz. Stream, birtakm standart ak ilemleri tanmlar. Tablo
14.1de Stream tarafndan tanmlanm ska kullanlan birka metot gsterilmektedir.

TABLO 14.1: Stream Tarafndan Tanmlanan Metotlardan Bazlar


Metot Aklama
void Close() Ak kapatr.
void Flush() Akn ieriini fiziksel cihaza yazar.
int ReadByte() Girdinin bir sonraki uygun bytenn tamsay gsterimi
dndrr. Dosyann sonuna ulalnca -1 dndrr.
int Read(byte[] tampon, int
teleme, int byteSays)
tampon[teleme]den balayarak tampona
byteSays kadar byte okumaya alr; baaryla
okunan byte saysn dndrr.
long seek(long teleme,
SeekOrigin orijin)
Ak iindeki mevcut konumu, belirtilen orijinden
belirtilen teleme kadar ileriye ayarlar.
void WriteByte(byte b) Bir kt akna tek bir byte yazar.
void Write(byte[] tampon,
int teleme, int byteSays)
tampon[teleme]den balayarak tampon dizisinden
byteSays kadar bytetan oluan bir alt aral yazar.
BLM 14: I/O KULLANIMI

HERKES N C#
399
Genel olarak, eer bir I/O hatas meydana gelirse, Tablo 14.1de gsterilen metotlar bir
IOException frlatacaklardr. Eer geersiz bir ilem gerekletirilmeye allyorsa, rnein
salt okunur bir aka yazmaya almak gibi, bir NotSupportedExtception frlatlr.
Stream tarafndan verileri okumak ve yazmak iin metotlar tanmlandna dikkat edin.
Ancak, aklarn tm bu ilemlerin her ikisini de desteklemeyeceklerdir, nk salt okunur ya
da salt yazlr aklar amak mmkndr. Ayrca, Seek() zerinden konum talepleri de
aklarn tm tarafndan desteklenmeyecektir. Bir akn becerilerini belirlemek iin Stream
zelliklerinden bir veya daha fazlasn kullanacaksnz. Bu zellikler Tablo 4.2de
gsterilmitir. Akn uzunluunu ve mevcut konumunu ieren Length ve Position
zellikleri de ayrca gsterilmitir.
Byte Stream Snflar
Streamden tretilen somut byte ak snf aada gsterilmitir:


Ak Snf Aklama
BufferedStream Bir byte akn sarar ve tampon bellek ekler. Tampon bellek birok durumda
performans art salar.
FileStream Dosya I/O ilemleri iin tasarlanm bir byte ak.
MemoryStream Depolama iin bellek kullanan bir byte ak.

Kendi ak snflarnz tretmeniz de mmkndr. Yine de, uygulamalarn byk
ounluu iin standart aklar yeterli olacaktr.

TABLO 14.2: Stream Tarafndan Tanmlanan zellikler


Metot Aklama
bool CanRead Eer ak okunabiliyorsa bu zellik doru deerine sahiptir. Bu salt okunur
bir zelliktir.
bool CanSeek Eer ak, konum taleplerini destekliyorsa bu zellik doru deerine sahiptir.
Bu salt okunur bir zelliktir.
bool CanWrite Eer ak yazlabiliyorsa bu zellik doru deerine sahiptir. Bu salt okunur
bir zelliktir.
long Length Bu zellik, akn uzunluunu ierir. Bu salt okunur bir zelliktir.
long Position Bu zellik, akn mevcut konumunu simgeler. Bu okunur/yazlr bir
zelliktir.


HERKES N C#
KISIM I C# DL

400

Karakter Akn Saran Snflar
Bir karakter ak oluturmak iin bir byte akn C#n karakter ak ambalajlarndan
birinin iine sarn. Karakter ak hiyerarisinin en stnde birer zet snf olan TextReader
ve TextWriter yer almaktadr. TextReader girdiyi; TextWriter ise kty ele alr. Bu iki
zet snf tarafndan tanmlanan metotlar, bu snflarn tm alt snflarnn kullanmna hazrdr.
Bylece bu snflar, tm karakter aklarnn sahip olaca minimal bir I/O fonksiyon kmesi
oluturmu olurlar.
TextReader iindeki girdi metotlar Tablo14.3te gsterilmitir. Genel olarak, bu metotlar
hata durumunda bir IOException frlatabilirler. (Bazlar dier trde kural d durumlar da
frlatabilirler.) Bir metin satrn btnyle okuyan ve bunu bir string olarak dndren
ReadLine() zellikle ilgintir. Bu metot, iinde gml boluklar olan girdileri okurken ie
yarar.

TABLO 14.3: TextReader Tarafndan Tanmlanan Girdi Metotlar


Metot Aklama
void Close() Girdi kaynan kapatr.
int Peek() Girdi aknda bir sonraki karakteri alr fakat karakteri
girdiden karmaz. Eer hi karakter mevcut deilse -1
dndrr.
int Read() Metodu aran girdi akndaki bir sonraki uygun
karakterin tamsay gsterimini dndrr. Akn sonuna
ulalnca -1 dndrr.
int Read(char[] tampon, int
teleme, int karakterSays)
tampon[teleme]den balayarak tampona
karakterSays kadar karakter okumaya alr;
baaryla okunan karakter saysn dndrr.
int ReadBlock(char[] tampon, int
teleme, int karakterSays)
tampon[ofset]ten balayarak tampona
karakterSays kadar karakter okumaya alr;
baaryla okunan karakter saysn dndrr.
string ReadLine() Bir sonraki metin satrn okur ve bunu bir karakter katar
olarak dndrr. Dosya sonundan okumaya
alldnda null dndrlr.
string ReadToEnd() Bir akta geriye kalan karakterlerin tmn okur ve
bunlar bir karakter katar olarak dndrr.
TextReader, tm standart tiplerin ktlarn alan Write() ve WriteLine()n eitli
versiyonlarn tanmlamaktadr. rnein, bunlarn ar yklenmi birka versiyonu yledir:

BLM 14: I/O KULLANIMI

HERKES N C#
401



Metot Aklama
void Write(int deer)
Bir int yaz.
void Write(double deer)
Bir double yaz.
void Write(bool deer)
Bir bool yaz.
void WriteLine(string deer)
Ardndan yeni bir satr gelen bir string yaz.
void WriteLine(uint deer)
Ardndan yeni bir satr gelen bir uint yaz.
void WriteLine(char deer)
Ardndan yeni bir satr gelen bir karakter yaz.
Write() ve WriteLine()a ek olarak TextWriter ayrca aada gsterilen Close()
ve Flush() metotlarn da tanmlamaktadr:
virtual void Close( )
virtual void Flush( )
Flush(), kt tamponunda kalan verilerin fiziksel ortama yazlmasna neden olur.
Close() ak kapatr.
TextReader ve TextWriter snflar, aadaki tabloda gsterilenler de dahil karakter
tabanl birka ak snf tarafndan uygulanr. Bylece, bu aklar TextReader ve
TextWriter tarafndan belirtilen metotlar ve zellikleri salam olurlar.


Ak Snf Aklama
StreamReader
Bir byte akndan karakterleri okur. Bu snf, bir byte girdi akn sarar.
StreamWriter Bir byte akna karakterleri yazar. Bu snf, bir byte kt akn sarar.
StringReader Bir karakter katarndan karakterleri okur.
StringWriter
Bir karakter katarna karakterleri yazar.
kili Aklar
Byte aklarna ve karakter aklarna ek olarak C#ta ikili verileri dorudan okumak ve
yazmak iin kullanlabilecek iki adet ikili ak snf da tanmldr. Bu aklar BinaryReader
ve BinaryWriter olarak adlandrlr. Bu blmn ileriki sayfalarnda ikili dosyalarn I/O
ilemleri ele alnrken bunlar daha yakndan inceleyeceiz.
Artk C# I/O sisteminin genel yapsn kavradnza gre, blmn geri kalannda konsol
I/O ilemlerinden balayarak C# I/O sisteminin eitli paralarn ayrntl olarak inceleyeceiz.


HERKES N C#
KISIM I C# DL

402
Konsol I/O
Konsol I/O; Console.In, Console.Out ve Console.Error standart aklar
araclyla gerekletirilir. Konsol I/Oyu Blm 2den beri kullanmaktasnz; bu nedenle,
buna zaten ainasnz. Konsol I/Onun ilave baz becerilere sahip olduunu daha sonra
greceksiniz.
Konuya balamadan nce bu kilapta daha nce bahsedilen bir hususu vurgulamak
nemlidir: C#n gerek uygulamalarnn birou, metin tabanl konsol proyramlar
olmayacaktr. Bunun yerine; bu uygulamalar, grafik tabanl programlardan oluacak ya da
kullanc ile etkileim iin pencereli bir arayz temel alan bileenler ierecektir. Bu nedenle,
C#n konsol girdi ve ktsna dayanan I/O sistemi yaygn olarak kullanlmaz. Metin tabanl
programlar, ksa yardmc programlar ve baz bileen tipleri iin retici rnekler olarak
kusursuz olsalar da, gerek dnyaya ait uygulamalarn pek ou iin uygun deildirler.
Konsol Girdisini Okumak
Console.In, TextReaderin bir rneidir; buna erimek iin TextReader tarafndan
tanmlanan metotlar ve zellikleri kullanabilirsiniz. Bununla birlikte, genellikle,
Console.Inden otomatik olarak okuyan ve Console tarafndan salanan metotlar
kullanacaksnz. Consoleda iki girdi metodu tanmldr: Read() ve ReadLine().
Tek bir karakter okumak iin Read() metodunu kullann:
static int Read()
Read(), konsoldan okunan bir sonraki karakteri dndrr. Read(), kullanc bir tua
basana kadar bekler ve sonra sonucu dndrr. Karakter int olarak dndrlr; bu deer, tip
atamas yoluyla chara dntrlmelidir. Hata durumunda Read(), -1 dndrr. Bu metot,
baarszlk durumunda bir IOException frlatacaktr. Konsol girdileri, satr satr tampona
yklenir; bu nedenle, tuladnz herhangi bir karakterin programnza gnderilmesinden nce
ENTER tuuna basmalsnz.
te, Read() kullanarak klavyeden bir karakter okuyan bir program:
// Klavyeden bir karakter okur.

using System;

class KbIn {
public static void Main() {
char ch;

Console.Write(Press a key followed by ENTER: );

ch = (char) Console.Read(); // bir karakter al

Console.WriteLine(Your key is: + ch);
BLM 14: I/O KULLANIMI

HERKES N C#
403
}
}
te, programn almasna bir rnek:
Press a key followed by ENTER: t
Your Key is: t
Read()in satr satr tampona okumas kimi zaman sinir bozucu da olabilir. ENTER
tuuna bastnzda carriage return ve linefeed sekans girdi akna eklenir. stelik, bu
karakterler, siz onlar okuyana kadar girdi tamponunda asl kalrlar. Bu nedenle, baz
uygulamalarda bir sonraki girdi ileminden nce bunlar (okuyarak) karmanz gerekebilir.
Bir karakter katarn okumak iin ReadLine() metodunu kullann. Metot u ekildedir:
static string ReadLine()
ReadLine(), siz ENTER tuuna basana kadar karakterleri okur ve okunan karakterleri bir
string nesnesi olarak dndrr. Baarszlk durumunda bu metot bir IOException
frlatacaktr.
te, ReadLine() kullanarak Console.Inden bir karakter katar okumay gsteren bir
program:
// ReadLine() kullanarak konsoldan girdi al.

using. System;

class ReadString {
public static void Main() {
string str;

Console.WriteLine(Enter some characters.);
str = Console.ReadLine();
Console.WriteLine(You entered: + str);
}
}
te, programn almasna bir rnek:
Enter some characters.
This is a test.
You entered: This is a test.
Console metotlar Console.Inden okumann en kolay yolu olmalarna ramen, altta
yatan TextReader zerinden de metotlar arabilirsiniz. rnein, ite yukardaki programn
TextReader tarafndan tanmlanm metotlar kullanlarak yeniden yazlm versiyonu:
// Dogrudan Console.In kullanarak klavyeden bir karakter katari oku.

using System;

class ReadChars2 {

HERKES N C#
KISIM I C# DL

404
public static void Main() {
string str;

Console.WriteLine(Enter some characters.);
str = Console.In.ReadLine();

Console.WriteLine(You entered: + str);
}
}
ReadLine()n imdi dorudan Console.In zerinden nasl arldna dikkat edin.
Buradaki temel nokta udur: Console.Inin altnda yatan TextReader tarafndan
tanmlanm metotlara erimeniz gerekiyorsa, bu metotlar bu rnekte gsterildii gibi
aracaksnz.
Konsol kts Yazmak
Console.Out ve Console.Error, TextWriter tipinde nesnelerdir. Konsol kts en
kolay ekilde, sizin nceden aina olduunuz Write() ve WriteLine() ile gerekletirilir.
Standart tiplerin her birinin ktsn almak iin bu metotlarn versiyonlar mevcuttur. Console,
Write() ve WriteLine()n kendi versiyonlarn tanmlar; bylece bu metotlar, bu kitapta
bandan beri yapmakta olduunuz gibi, dorudan Console zerinden arlabilir. Yine de,
tercih ederseniz Console.Out ve Console.Errorn altnda yatan TextWriter zerinden
de bu metotlar (ve dierlerini) arabilirsiniz.
te, Console.Out ve Console.Errora yazmay gsteren bir program:
// Console.Out ve Console.Errora yaz.

using System;

class ErrOut {
public static void Main() {
int a = 10, b = 0;
int result;

Console.Out.writeLine(This will generate an exception.);
try {
result = a / b; // Kural disi bir durum uret
} catch(DivideByZeroException exc) {
Console.Error.WriteLine(exc.Message);
}
}
}
Programn kts aada gsterilmitir:
This will generate an exception.
Attempted to divide by zero.
BLM 14: I/O KULLANIMI

HERKES N C#
405
Programlamaya yeni balayanlar bazen Console.Error ne zaman kullanacaklarn
kartrrlar. Hem Console.Out hem de Console.Error ktlarn konsola gnderdiklerine
gre niye iki farkl isim kullanlyor? Bu sorunun yant, standart aklarn dier aygtlara
ynlendirilebilir olmas gereinde yatyor. rnein, Console.Error ekran yerine disk
dosyasna yazacak ekilde ynlendirilebilir. Bylece, konsol ktsn etkilemeden hata ktsn
rnein bir gnlk (log) dosyasna ynlendirmeniz mmkndr. Tam tersi durumda, eer
konsol kts ynlendirilmi ve hata kts ynlendirilmemise hata mesajlar konsolda,
grlebilecekleri yerde gzkeceklerdir. Ynlendirmeleri daha sonra, dosya I/O ilemleri
anlatldktan sonra inceleyeceiz.
FileStream ve Byte Ynelimli Dosya I/O lemleri
C# dosyalar okumanza ve dosyalara yazmanza imkan veren snflar salar. Elbette, disk
dosyalar en yaygn dosya tiplerindendir. letim sistemi dzeyinde tm dosyalar byte
tabanldr. Tahmin edeceiniz gibi, C# dosyalardan okumak ve dosyalara yazmak iin metotlar
ierir. Bylece, byte aklar kullanarak dosyalardan okumak ve dosyalara yazmak ok
yaygndr. C# ayrca byte tabanl bir dosya akn karakter tabanl bir nesne iine sarmanza da
olanak tanr. Karakter tabanl dosya ilemleri metinlerin saklanmas srasnda ie yarar.
Karakter aklar bu blmn iinde ileriki sayfalarda ele alnmaktadr. Byte ynelimli I/O ise
burada anlatlmaktadr.
Bir dosyaya ilitirilmi byte tabanl bir ak oluturmak iin FileStream snfn
kullanacaksnz. FileStream, Streamden tretilmitir ve Streamin tm ilevselliine
sahiptir.
Hatrlarsanz, FileStream de dahil olmak zere ak snflar System.IO iinde
tanmlanmaktadr. Bu nedenle genellikle, ak snflarn kullanan bir programn bana yakn
bir yerlerde aadaki ifadeyi dahil etmelisiniz.
using System.IO;
Bir Dosyay Amak ve Kapatmak
Bir dosyaya bal bir byte ak oluturmak iin bir FileStream nesnesi oluturun.
FileStreamde birka yaplandrc tanmldr. Belki de en yaygn olarak kullanlan aada
gsterilmitir:
FileStream(string dosyaad, FileMode kip)
Burada dosyaad, alacak dosyann adn belirtir. dosyaad, dizin yolunun tam
ifadesini ierebilir. kip parametresi, dosyann nasl alacan belirtir. kip, FileMode
numaralandrmas tarafndan tanmlanan deerlerden biri olmaldr. Bu deerler Tablo 14.4te
gsterilmitir. Bu yaplandrc dosyay okuma/yazma eriimine aar.

HERKES N C#
KISIM I C# DL

406
Dosyay amaya alrken baarsz olunursa bir kural d durum frlatlacaktr. Eer
dosya mevcut olmad iin alamyorsa, FileNotFoundException frlatlacaktr. Eer
dosya bir I/0 hatasndan dolay alamyorsa, IOException frlatlacaktr. Dier olas kural
d durumlar unlardr: ArgumentNullException (dosya ismi mevcut olmadnda),
ArgumentException (kip parametresi geersiz olduunda), SecurityException
(kullancnn eriim haklar olmadnda) ve DirectoryNotFoundException (belirtilen
dizin geersiz olduunda).
TABLO 14.4: FileMode Deerleri


Deer Aklama
FileMode.Append kt dosyasnn sonuna eklenir.
FileMode.Create Yeni bir kt dosyas oluturur. Ayn isimde nceden mevcut herhangi
bir dosya yok edilecektir.
FileMode.CreateNow Yeni bir kt dosyas oluturur. Dosya nceden mevcut olmamaldr.
FileMode.Open nceden mevcut bir dosyay aar.
FileMode.OpenOrCreate Dosya mevcutsa dosyay aar ya da dosya nceden mevcut deilse
dosyay oluturur.
FileMode.Truncate nceden mevcut bir dosyay aar, fakat uzunluunu sfra indirir.
Aada, test.dat dosyasn girdi iin amay gsteren bir yntem sunuluyor:
FileStream fin;

try {
fin = new FileStream(test.dat, FileMode.Open);
}
catch(FileNotFoundException exc) {
Console.WriteLine(exc.Message);
return;
}
catch {
Console.WriteLine(Cannot open file.);
return;
}
Bu rnekte ilk catch ifadesi dosyann bulunamadn belirten hatay yakalyor. Tmn
yakala trnde bir ifade olan ikinci catch ise, dier olas dosya hatalarn kontrol altna
alyor. Her bir hatay ayr ayr da kontrol edebilirdiniz. Bu durumda, meydana gelen problemler
de daha spesifik olarak rapor edilmi olurdu. leri basit tutmak asndan bu kitaptaki rnekler
yalnzca FileNotFoundException ile IOException yakalayacaklardr, fakat sizin gerek
kodunuzun, koullara bal olarak dier olas kural d durumlar da kontrol altna almas
gerekebilir.
BLM 14: I/O KULLANIMI

HERKES N C#
407
Az nce anlatlan FileStream yaplandrcs, nceden de bahsedildii gibi,
okuma/yazma eriimine sahip olan bir dosyay aar. Eer eriimi yalnzca okuma ya da yazma
olarak snrlamak isterseniz, bu durumda ncekinin yerine u yaplandrcy kullann:
FileStream(String dosyaad, FileMode kip, FileAccess nasl)
nceki gibi burada da dosyaad, alacak dosyann adn, kip ise dosyann nasl
alacan belirtir. nasl zerinden aktarlan deer de, dosyann nasl eriileceini belirler. Bu
deer, FileAccess numaralandrmas tarafndan tanmlanan deerlerden biridir.
FileAccess tarafndan tanmlanan deerler aada gsterilmitir:
FileAccess.Read FileAccess.Write FileAccess.ReadWrite
rnein, u ifade salt okunur bir dosya aar:
FileStream fin = new FileStream(test.dat, FileMode.Open,
FileAccess.Read);
Bir dosyayla iiniz bittiinde Close() metodunu ararak bunu kapatmalsnz. Close()
genel olarak u ekildedir:
void Close()
Bir dosyay kapatmak, dosyaya tahsis edilen sistem kaynaklarn serbest brakr; bu sayede,
bu kaynaklarn baka bir dosya tarafndan kullanlabilmesi mmkn olur. Close(), bir
IOException frlatabilir.
Bir Filestreamden Byte'lar Okumak
FileStreamde bir dosyadan byte byte okuyan iki metot tanmldr: ReadByte() ve
Read(). Bir dosyadan tek bir byte okumak iin ReadByte() kullann. ReadByte() genel
olarak u ekildedir:
int ReadByte()
ReadByte(), her arlnda dosyadan tek bir byte okur ve bunu bir tamsay deer olarak
dndrr. Dosyann sonuna ulanca -1 dndrr. Olas kural d durumlar unlardr:
NotSupportedException (ak girdi iin almamsa) ve ObjectDisposedException
(ak kapatlmsa).
Bir byte blou okumak iin Read() kullann. Bunun genel ekli yledir:
int Read(byte[] tampon, int teleme, int byteSays)
Read(), tampon[teleme]den balayarak tampon iine byteSays kadar byte
okumaya alr. Baaryla okunan byte says dndrlr. I/O hatas meydana geldiinde bir
IOException frlatlr. Dier tipten kural d durumlardan birka da mmkndr. Okuma,
ak tarafndan desteklenmediinde frlatlan NotSupportedException da bunlardan biridir.

HERKES N C#
KISIM I C# DL

408
Aadaki program, ismi komut satr argman olarak belirtilen bir metin dosyasna girdi
girmek ve dosyann ieriini gstermek iin ReadByte() kullanmaktadr. Bu program
almaya baladnda ortaya kabilecek iki hatay kontrol altna alan try/catch bloklarna
dikkat edin: Belirtilen dosya mevcut olmayabilir ya da kullanc dosya ismini dahil etmeyi
unutabilir. Komut satr argmanlarn her kullannzda bu yntemin aynsn kullanabilirsiniz.
/* Bir metin dosyasini gosterir.

Bu programi kullanmak icin, gormek istediginiz
dosyann adini belirtin. Ornegin, TEST:CS
adinda bir dosyayi gormek icin asagidaki
komut satirini kullanin.

ShowFile TEST.CS
*/

using System;
using System.IO;

class ShowFile {
public static void Main(string[] args) {
int i;
FileStream fin;
try {
fin = new FileStream(args[0], FileMode.Open);
} catch(FileNotFoundException exc) {
Console.WriteLine(exc.Message);
return;
} catch(IndexOutOfRangeException exc) {
Console.WriteLine(exc.Message + \nUsage: ShowFile File);
return ;
}

// EOFa rastlayana kadar bytelari oku
do {
try {
i = fin.ReadByte();
} catch(Exception exc) {
Console.WriteLine(exc.Message);
return ;
}
if(i != -1) Console.Write((char) i);
} while(i != -1);

fin.Close();
}
}
Bir Dosyaya Yazmak
Bir dosyaya bir byte yazmak iin WriteByte() metodunu kullann. Bunun en basit ekli
aada gsterilmitir:
BLM 14: I/O KULLANIMI

HERKES N C#
409
void WriteByte(byte deer)
Bu metot, deer tarafndan belirtilen byte dosyaya yazar. Yazma srasnda eer bir hata
meydana gelirse, bir IOException frlatlr. Eer sz konusu ak, kt iin almamsa,
NotSupportedException frlatlr.
Write() ararak bir dosyaya bir byte dizisi yazabilirsiniz. Bu durum aada
gsterilmitir:
void Write(byte[] tampon, int ofset, int byteSays)
Write(), tampon[teleme]den balayarak tampon dizisinden byteSays kadar
byte dosyaya yazar. Yazma srasnda bir hata ortaya karsa bir IOException frlatlr. Eer
sz konusu ak, kt iin almamsa bir NotSupportedException frlatlr. Dier kural
d durumlar da ayrca mmkndr.
Muhtemelen biliyorsunuzdur, dosya kts gerekletirilirken genellikle kt, asl fiziksel
cihaza hemen yazlmaz. Bunun yerine, veriler bir kerede tmden yazlabilecek bykle
eriene kadar iletim sistemi tarafndan bir tamponda depolanr. Bu, sistemin verimliliini
artrr. rnein, disk dosyalar sektr sektr dzenlenmitir. Bir sektrn uzunluu yaklak
128 byte civarndadr; daha byk de olabilir. kt genellikle btn bir sektr bir kerede
yazlabilecek hale gelene kadar tamponlanr. Ancak, tampon dolu olsun ya da olmasn verilerin
fiziksel cihaza yazlmasn istiyorsanz, Flush() u ekilde arabilirsiniz:
void Flush()
Baarszlk durumunda bir IOException frlatlr.
Bir kt dosyas ile iiniz bitliinde dosyay Close() kullanarak kapatmanz gerektiini
hatrlamalsnz. Bu ekilde davranarak disk tamponunda kalan ktlarn gerekten diske
yazlmasn garanti etmi olursunuz. Bu nedenle, bir dosyay kapatmadan nce Flush()
armann pek bir esprisi yoktur.
te, bir dosyaya yazan basit bir rnek program:
// Dosyaya yazar.

using System;
using System.IO;

class WriteToFile {
public static void Main(string[] args) {
FileStream fout;

// cikti dosyasi ac
try {
fout = new FileStream(test.txt, FileMode.Create);
} catch(IOException exc) {
Console.WriteLine(exc.Message +
\nError Opening Output File);

HERKES N C#
KISIM I C# DL

410
return;
}

// Harfi dosyaya yaz
try {
for(char c = A; c <= Z; c++)
fout.WriteByte((byte) c);
} catch(IOException exc) {
Console.WriteLine(exc.Message + File Error);
}

fout.Close();
}
}
Program ncelikle kt iin test.txt adnda bir dosya aar. Sonra, bu dosyaya byk
harfleri yazar. Son olarak, dosyay kapatr. Olas hatalarn try/catch bloklar tarafndan nasl
kontrol altna alndna dikkat edin. Programn almasndan sonra test.txt aadaki
kty ierecektir:
ABCDEFGHIJKLMNOPQRSTUVWXYZ
Dosya Kopyalamak in FileStream Kullanmak
FileStream tarafndan kullanlan byte tabanl I/Onun salad avantajlardan biri, bunu
-sadece metin ieren dosyalar zerinde deil - her eit dosya zerinde kullanlabiliyor
olmanzdr. rnein, aadaki program, altrlabilir dosyalar da dahil olmak zere her tr
dosyann kopyasn kartmaktadr. Kaynak ve hedef dosyalarn isimleri komut satrnda
belirtilmektedir.
/* Dosyayi kopyalar.

Bu program kullanmak icin, kaynak ve
hedef dosyalarin isimlerini belirtin.
Ornegin, FIRST.DAT adinda bir dosyayi
SECOND.DAT adinda bir dosyaya kopyalamak icin
Asagidaki komut satirini kullanin.

CopyFile FIRST.DAT SECOND.DAT
*/

using System;
using System.IO;

class CopyFile {
public static void Main(string[] args) {
int i;
FileStream fin;
FileStream fout;

try {
// girdi dosyasini ac
try {
BLM 14: I/O KULLANIMI

HERKES N C#
411
fin = new FileStream(args[0], FileMode.Open);
} catch(FileNotFoundException exc) {
Console.WriteLine(exc.Message + \nInput File
Not Found);
return;
}

// cikt dosyasini ac
try {
fout = new FileStream(args[1], FileMode.Create);
} catch(IOException exc) {
Console.WriteLine(exc.Message + \nError Opening
Output File");
return;
}
} catch(IndexOutOfRangeException exc) {
Console.WriteLine(exc.Message + \nUsage:
CopyFile From To);
return;
}

// Dosyayi kopyala
try {
do {
i = fin.ReadByte();
if(i != -1) fout.WriteByte((byte)i);
} while(i != -1);
} catch(IOException exc) {
Console.WriteLine(exc.Message + File Error);
}

fin.Close();
fout.Close();
}
}
Karakter Tabanl Dosya I/O lemleri
Byte tabanl dosya ynetimi olduka yaygn olmasna ramen C# ayrca karakter tabanl
aklar da salamaktadr. Karakter tabanl aklarn avantaj, bunlarn dorudan Unicode
karakterleri zerinde ilem grmeleridir. Yani, Unicode metinlerini saklamak istiyorsanz,
karakter aklar kesinlikle sizin iin en iyi tercih olacaktr. Genel olarak, karakter tabanl dosya
ilemlerini gerekletirmek iin FileStreami ya bir StreamReader ya da StreamWriter
iine yerletireceksiniz. Bu snflar, byte akn otomatik olarak bir karakter akna
dntrrler. Tersi de geerlidir.
letim sistemi dzeyinde bir dosyann birtakm bytelardan olutuunu hatrnzdan
karmayn. StreamReader ya da StreamWriter kullanmak bu gerei deitirmeyecektir,

HERKES N C#
KISIM I C# DL

412
StreamWriter, TextWriterdan tretilmitir. StreamReader ise TextReaderdan
tretilmitir. Bylece, StreamWriter ve StreamReader kendi temel snflar tarafndan
tanmlanan zelliklere ve metotlara eriim hakknda sahiplerdir.
StreamWriter Kullanm
Karakter tabanl bit kt ak oluturmak iin bir Stream nesnesini (mesela, bir
FileStream) bir StreamWriter iine yerletirin. StreamWriterda birka yaplandrc
tanmldr. Bunlarn en poplerlerinden biri aada gsterilmitir:
StreamWriter(Stream ak)
Burada ak, ak bir akn ismidir. Bu yaplandrc, eer ak, kt iin ak deilse bir
ArgumentException frlatr, ak, null olduunda ise bir ArgumentNullException
frlatlr. Bir kez oluturulduktan sonra bir StreamWriter karakterlerin bytea dnmn
otomatik olarak ele alr.
Aada, klavyeden girilen bir satr metni okuyup, bunu test.txt adndaki bir dosyaya
yazan klavyeden diske ilevine sahip basit bir yardmc program yer almaktadr:
/* Bir StreamWriteri gosteren, klavyeden diske
islevine sahip basit bir yardimci program. */

using System;
using System.IO;

class KtoD {
public static void Main() {
string str;
FileStream fout;

try {
fout = new FileStream(test.txt, FileMode.Create);
}
catch(IOException exc) {
Console.WriteLine(exc.Message + Cannot open file.);
return;
}
StreamWriter fstr_out = new StreamWriter(fout);

Console.writeLine(Enter text (stop to quit).);
do {
Console.Write(: );
str = Console.ReadLine();

if(str != stop) {
str = str + \r\n; // yeni bir satir ekle
try {
fstr_out.Write(str);
} catch(IOException exc) {
Console.WriteLine(exc.Message + File Error);
return ;
BLM 14: I/O KULLANIMI

HERKES N C#
413
}
}
} while(str != stop);

fstr_out.Close();
}
}
Baz durumlarda bir dosyay StreamWriter kullanarak dorudan amak ok daha kullanl
olabilir. Bunun iin aadaki yaplandrclardan birini kullann:
StreamWriter(string dosyaad)
StreamWriter(string dosyaad, bool eklemeareti)
Burada dosyaad, alacak dosyann adn belirtir. dosyaad, tm dizin yolunu tam
olarak ierebilir. kinci formda, eer eklemeareti true ise kt, mevcut dosyann sonuna
eklenir. Aksi halde kt, belirtilen dosyann zerine yazar. Her iki durumda da, eer dosya
mevcut deilse oluturulur. Ayrca, bir I/O hatas durumunda her ikisi de bir IOException
frlatr. Dier kural d durumlar da mmkndr.
Aada, klavyeden diske ilevine sahip programn, kt dosyasn amak iin bir
StreamWriter kullanacak ekilde yeniden yazlm bir versiyonu yer almaktadr:
// StreamWriter kullanarak bir dosya ac.

using System;
using System.IO;

class KtoD {
public static void Main() {
string str;
StreamWriter fstr_out;

// StreamWriter kullanarak dosyayi dogrudan ac.
try {
fstr_out = new StreamWriter(test.txt);
}
catch(IOException exc) {
Console.WriteLine(exc.Message + Cannot open file.);
return;
}

Console.WriteLine(Enter text (stop to quit).);
do {
Console.Write(: );
str = Console.ReadLine();

if(str != stop) {
str = str + \r\n; // yeni bir satir ekle
try {
fstr_out.Write(str);
} catch(IOException exc) {
Console.WriteLine(exc.Message + File Error);

HERKES N C#
KISIM I C# DL

414
return ;
}
}
} while(str != stop);

fstr_out.Close();
}
}
StreamReader Kullanm
Karakter tabanl bir girdi ak oluturmak iin bir byte akn bir StreamReader iine
yerletirin. StreamReaderda birka yaplandrc tanmldr. Ska kullanlan bir yaplandrc
aada gsterilmitir:
StreamReader(Stream ak)
Burada ak, ak bir akn ismidir. Bu yaplandrc, ak null ise bir
ArgumentNullException frlatr. Bir kez oluturulduktan sonra bir StreamReader,
bytelarn karaktere dnmn otomatik olarak ele alr.
Aada, test.txt adnda bir metin dosyasn okuyup, dosya ieriini ekranda gsteren
bir diskten ekrana ilevine sahip basit bir yardmc program oluturulmaktadr. Bylece bu
program, nceki blmde gsterilen klavyeden diske ilevine sahip yardmc program
tamamlamaktadr:
/* Bir FileReaderi gosteren diskten ekrana
islevine sahip basit bir yardimci program. */

using System;
using System.IO;

class DtoS {
public static void Main() {
FileStream fin;
string s;

try {
fin = new FileStream(test.txt, FileMode.Open);
}
catch(FileNotFoundException exc) {
Console.WriteLine(exc.Message + Cannot open file.);
return ;
}

StreamReader fstr_in = new StreamReader(fin);

// Dosyayi satir satir oku.
while((s = fstr_in.ReadLine()) != null) {
Console.WriteLine(s);
}

BLM 14: I/O KULLANIMI

HERKES N C#
415
fstr_in.Close();
}
}
Dosyann sonunun nasl belirlendiine dikkat edin. ReadLine() tarafndan dndrlen
referans null ise, dosyann sonuna eriilmi demektir.
StreamWriterdaki gibi, baz durumlarda bir dosyay StreamReader kullanarak
dorudan amak size daha kolay gelebilir. Bunun iin aadaki yaplandrcy kullann:
StreamReader(string dosyaad)
Burada dosyaad, alacak dosyann ismini belirtir. dosyaad, dosyann dizin yolunu
tam olarak da ierebilir. Dosya mevcut olmaldr. Eer deilse, bir FileNotFoundException
frlatlr. Eger dosyaad null deerine sahipse, bir ArgumentNullException frlatlr.
dosyaad bo bir karakter katarndan ibaret ise ArgumentException frlatlr.
Standart Aklar Ynlendirmek
Daha nce bahsedildii gibi, standart aklar - rnein Console.In - ynlendirilebilir. En
yaygn ynlendirme, bir dosyaya yaplr. Standart bir ak ynlendirildii zaman girdi ve/veya
kt, varsaylan cihazlar atlanarak otomatik olarak yeni aka yneltilir. Standart aklar
ynlendirerek programnz bir disk dosyasndan komutlar okuyabilir, ktk dosyalar
oluturabilir, hatta bir a balantsndan girdi bile okuyabilir.
Standart aklarn ynlendirilmesi iki ekilde gerekletirilebilir: Birincisi, bir program ko-
mut satrndan altrdnzda Console.In ve/veya Console.Outa ynlendirmek iin
srasyla < ve > operatrlerini kullanabilirsiniz. rnein, aadaki program inceleyelim:
using System;

class Test {
public static void Main() {
Console.WriteLine(This is a test.);
}
}
Program aadaki ekilde altrmak, log adnda bir dosyaya This is a test. satrnn
yazlmasna neden olacaktr.
Test > log
Girdi de ayn ekilde ynlendirilebilir. Girdi ynlendirildiinde unu hatrlamalsnz: Girdi
kayna olarak belirtmi olduunuz kaynan programn taleplerini karlamak iin yeterince
girdi ierdiinden emin olmalsnz. Eer iermiyorsa program asl kalacaktr.
Komut satrn ynlendirme operatrleri olan < ve >, C#n bir paras deildirler; iletim
sistemi tarafndan salanrlar. Bylece, eer ortamnz I/O ynlendirmesini destekliyorsa
(Windowsta sz konusu olduu gibi), programnzda herhangi bir deiiklik yapmadan

HERKES N C#
KISIM I C# DL

416
standart girdi ve standart kty ynlendirebilirsiniz. Yine de, standart aklar
ynlendirebilmeniz iin sizin kontrolnzde olan ikinci bir yol da mevcuttur. Bunun iin
Consoleun yesi olan ve aada gsterilen SetIn(), SetOut() ve SetError()
metotlarn kullanacaksnz:
static void SetIn (TextReader girdi)
static void SetOut(TextWriter kt)
static void SetError(TextWriter kt)
Bylece, girdiyi ynlendirmek iin istenilen ak belirterek SetIn()i arn.
TextReaderdan tretildii srece herhangi bir girdi akn kullanabilirsiniz. kty bir
dosyaya ynlendirmek iin bir StreamWriter iine yerletirilmi bir FileStream belirtin.
Aadaki program bunun bir rneini gstermektedir:
// Console.Outa yonlendir.

using System;
using System.IO;

class Redirect {
public static void Main() {
StreamWriter log_out;

try {
log_out = new StreamWriter(logfile.txt);
}
catch(IOException exc) {
Console.WriteLine(exc.Message + Cannot open file.);
return;
}

// Standart ciktiyi kutuk dosyasina yonlendir.
Console.SetOut(log_out);
Console.WriteLine(This is the start of the log file.);

for(int i = 0; i < 10; i++) Console.WriteLine(i);

Console.WriteLine(This is the end of the log file.);
log_out.Close();
}
}
Bu program altrdnzda ekranda hi kt grmeyeceksiniz, ama logfile.txt
aadakileri ierecektir:
This is the start of the log file.
0
1
2
3
4
5
6
BLM 14: I/O KULLANIMI

HERKES N C#
417
7
8
9
This is the end of the log file.
Kendi kendinize dier standart aklar ynlendirmeyi deneyebilirsiniz.
kili Verileri Okumak ve Yazmak
imdiye dek bytelar veya karakterleri okuyup yazmaktayz. Fakat, dier tipteki verileri
okumak ve yazmak da mmkndr - hatta, yaygndr. Sz gelii, int, double ve shortlar
ieren bir dosya oluturmak isteyebilirsiniz. C#n standart tiplerinin ikili (binary) deerlerini
okumak ve yazmak iin BinaryReader ve BinaryWriter kullanacaksnz. Bu tr verilerin
insanlarn okuyaca trden metin formunda deil de dahili, ikili biim kullanlarak
okunduunu ve yazldn anlamak nemlidir.
Binary Writer
BinaryWriter, ikili verilerin yazlmasn yneten bir byte aknn elrafndaki
ambalajdr. Bunun en sk kullanlan yaplandrcs aada gsterilmitir:
BinaryWriter(Stream ktAk)
Burada ktAk, verilerin yazlaca aktr. Bir dosyaya kt yazmak amacyla bu
parametre iin FileStream tarafndan oluturulan nesneyi kullanabilirsiniz. Eer
ktAk null ise bir ArgumentNullException frlatlr. Eer ktAk yazma
ilemi iin henz almamsa ArgumentException frlatlr.
BinaryWriter, C#n tm standart tiplerini yazabilen metotlar tanmlamaktadr.
Bunlardan birka Tablo 14.5te gsterilmitir. Bir stringin, uzunluk belirleyicisini de ieren
dahili biimi kullanlarak yazldna dikkat edin. BinaryWriterda ayrca standart Close()
ve Flush() metotlar da tanmlanmaktadr. Bunlar nceden anlatldklar gibi almaktadrlar.
TABLO 14.5: BinaryWriter Tarafndan Tanmlanan Ska Kullanlan kt Metotlar


Metot Aklama
void Write(sbyte deer)
aretli bir byte yazar.
void Write(byte deer) aretsiz bir byte yazar.
void Write(byte[] tampon) Bir byte dizisi yazar.
void Write(short deer) Bir ksa tamsay yazar.
void Write(ushort deer) Bir iaretsiz ksa tamsay yazar.
void Write(int deer) Bir tamsay yazar.
void Write(uint deer) Bir iaretsiz tamsay yazar.

HERKES N C#
KISIM I C# DL

418
void Write(long deer) Bir uzun tamsay yazar.
void Write(ulong deer) Bir iaretsiz uzun tamsay yazar.
void Write(float deer)
Bir float yazar.
void Write(double deer)
Bir double yazar.
void Write(char deer) Bir karakter yazar.
void Write(char[] tampon) Bir karakter dizisi yazar.
void Write(string deer)
Bir stringi dahili gsterimini kullanarak yazar; dahili
gsterim, bir uzunluk belirleyicisi ierir.

Binary Reader
BinaryReader, ikili verileri okuma ilemini kontrol altna alan bir byte aknn
etrafndaki ambalajdr. Bunun en yaygn kullanlan yaplandrcs aada gsterilmitir:
BinaryReader(Stream girdiAk)
Burada girdiAk verilerin okunduu aktr. Bir dosyadan okumak amacyla bu
parametre iin FileStream tarafndan oluturulan nesneyi kullanabilirsiniz. Eer
girdiAk null ise bir ArgumentNullException frlatlr. Eer girdiAk okuma
ilemi iin henz almamsa, ArgumentException frlatlr.
BinaryReader, C#n tm basit tiplerini okumak iin metotlara sahiptir. Bunlardan en
yaygn olarak kullanlanlar Tablo 14.6da gsterilmitir. ReadString()in, depolanm bir
karakter katarn dahili biimini kullanarak okuduuna dikkat edin. Dahili biim, uzunluk
belirleyicisini de iermektedir. Akn sonuna ulanca tm metotlar bir
EndOfStreamException frlatrlar. Hata durumunda ise bir IOException frlatrlar.
BinaryReader ayrca Read()in versiyonunu da tanmlamaktadr. Bu versiyonlar
unlardr:
Metot Aklama
int Read() Metodu aran girdi akndaki bir sonraki mevcut
karakteri simgeleyen bir tamsay dndrr.
Dosyann sonuna ulalnca -1 dndrr.
int Read(byte[] tampon,
int teleme, int no)
tampon[teleme]den balayarak tampona
no kadar byte okumaya alr. Baaryla okunan
byte saysn dndrr.
int Read(char[] tampon,
int teleme, int no)
tampon[teleme]den balayarak tampona
no kadar karakter okumaya alr. Baaryla
okunan karakter saysn dndrr.

Bu metotlar baarszlk durumunda bir IOException frlatrlar.
BLM 14: I/O KULLANIMI

HERKES N C#
419
Standart Close() metodu da ayrca tanmlanmaktadr.
TABLO 14.6: BinaryReader Tarafndan Tanmlanan Ska Kullanlan Girdi Metotlar


Metot Aklama
bool ReadBolean()
Bir bool okur.
byte ReadByte()
Bir byte okur.
sbyte ReadSByte()
Bir sbyte okur.
byte[] ReadBytes(int no)
no adet byte okur ve bunlar bir dizi olarak dndrr.
char ReadChar()
Bir char okur.
char[] ReadChars(int no)
no adet karakter okur ve bunlar bir dizi olarak dndrr.
double ReadDouble()
Bir double okur.
float ReadSingle()
Bir float okur.
short ReadInt16()
Bir short okur.
int ReadInt32()
Bir int okur.
long ReadInt64()
Bir long okur.
ushort ReadInt16()
Bir ushort okur.
uint ReadInt32()
Bir uint okur.
ulong ReadUInt64()
Bir ulong okur.
string ReadString()
Dahili, ikili biimde simgelenen bir string okur. Biim,
uzunluk belirleyicisi ierir. Bu metot yalnzca bir
BinaryWriter kullanlarak yazlm bir karakter katarn
okumak iin kullanlmaldr.

kili I/O lemlerinin Gsterilmesi
Aada, BinaryReader ve BinaryWriter gsteren bir program yer almaktadr.
Program, eitli tipten verileri bir dosyaya yazar ve sonra bunlar dosyadan geri okur.
// Ikili verileri yaz ve sonra geri oku.

using System;
using System.IO;

class RWData {
public static void Main() {
BinaryWriter dataOut;
BinaryReader dataIn;

int i = 10;
double d = 1023.56;
bool b = true;

HERKES N C#
KISIM I C# DL

420

try {
dataOut = new BinaryWriter(new FileStream(testdata,
FileMode.Create));
}
catch(IOException exc) {
Console.WriteLine(exc.Message + \nCannot open file.);
return;
}

try {
Console.WriteLine(Writing + i);
dataOut.Write(i);

Console.WriteLine(Writing + d);
dataOut.Write(d);

Console.WriteLine(Writing + b);
dataOut.Write(b);

Console.WriteLine(Writing + 12.2 * 7.4);
dataOut.Write(12.2 * 7.4);
}
catch(IOException exc) {
Console.WriteLine(exc.Message + \nWrite error.);
}

dataOut.Close();

Console.WriteLine();

// Simdi, bunlari geri oku.
try {
dataIn = new BinaryReader(new FileStream(testdata,
FileMode.Open));
}
catch(FileNotFoundException exc) {
Console.WriteLine(exc.Message + \nCannot open file.);
return;
}

try {
i = dataIn.ReadInt32();
Console.WriteLine(Reading + i);

d = dataIn.ReadDouble();
Console.WriteLine(Reading + d);

b = dataIn.ReadBoolean();
Console.WriteLine(Reading + b);

d = dataIn.ReadDouble();
Console.WriteLine(Reading + d) ;
}
catch(IOException exc) {
BLM 14: I/O KULLANIMI

HERKES N C#
421
Console.WriteLine(exc.Message + Read error.);
}

dataIn.Close();
}
}
Programn kts aada gsterilmitir:
Writing 10
Writing 1023.56
Writing True
Writing 90.28

Reading 10
Reading 1023.56
Reading True
Reading 90.28
Bu program tarafndan oluturulan testdata dosyasn incelerseniz, dosyann insanlarn
okuyabilecei gibi bir metin deil, ikili veriler ierdiini fark edeceksiniz.
te, ikili I/Onun ne kadar gl olduunu gsteren daha pratik bir rnek. Aadaki prog-
ram ok basit bir envanter programn uygulamaktadr. Envanterdeki her kalem iin program;
maln ismini, stokta ka adet olduunu ve maliyetini saklar. Sonra program, kullancy bir ma-
ln ismini girmesi iin ynlendirir. Daha sonra veri tabann arar. Eer sz konusu mal veri
tabannda bulunursa, ilgili envanter bilgileri ekranda gsterilir.
/* Basit bir envanter programini uygulamak
icin BinaryReader ve BinaryWriter kullanir. */

using System;
using System.IO;

class Inventory {
public static void Main() {
BinaryWriter dataOut;
BinaryReader dataIn;

string item; // malin ismi
int onhand; // stoktaki mal miktari
double cost; // maliyet

try {
dataOut = new
BinaryWriter(new FileStream(inventory.dat,
FileMode.Create));
}
catch(IOException exc) {
Console.WriteLine(exc.Message + \nCannot open file.);
return;
}

// Dosyaya bazi envanter verilerini yaz.

HERKES N C#
KISIM I C# DL

422
try {
dataOut.Write(Hammers);
dataOut.Write(10);
dataOut.Write(3.95);

dataOut.Write(Screwdrivers);
dataOut.Write(18);
dataOut.Write(1.50);

dataOut.Write(Pliers);
dataOut.Write(5);
dataOut.Write(4.95);

dataOut.Write(Saws);
dataOut.Write(8);
dataOut.Write(8.95);
)
catch(IOException exc) {
Console.WriteLine(exc.Message + \nWrite error.);
}

dataOut.Close();

Console.WriteLine();

// Simdi, envanter dosyasini okuma icin ac.
try {
dataIn = new
BinaryReader(new FileStream(inventory.dat,
FileMode.Open));
}
catch(FileNotFoundException exc) {
Console.WriteLine(exc.Message + \nCannot open file.);
return;
}

// Kullanicinin girdigi mali ara.
Console.Write(Enter item to lookup: );
string what = Console.ReadLine();
Console.WriteLine();

try {
for(;;) {
// Envanter girdilerinden birini oku.
item = dataIn.ReadString();
onhand = dataIn.ReadInt32();
cost = dataIn.ReadDouble();

/* Malin istenilenle eslenip eslenmedigine bak.
Eger esleniyorsa, ilgili bilgileri ekranda
goster. */
if(item.CompareTo(what) == 0) {
Console.WriteLine(onhand + + item + on hand.
+ Cost: {0:C} each, cost);
Console.WriteLine(Total value of {0}: {1:C}.,
BLM 14: I/O KULLANIMI

HERKES N C#
423
item, cost * onhand);
break;
}
}
}
catch(EndOfStreamException) {
Console.WriteLine(Item not found.);
}
catch(IOException exc) {
Console.WriteLine(exc.Message + Read error.);
}

dataIn.Close();
}
}
te programn rnek bir almas:
Enter item to lookup: Screwdrivers

18 Screwdrivers on hand. Cost: $1.50 each
Total value of Screwdrivers: $27.00
Programda envanter bilgilerinin ikili formatta nasl saklandna dikkat edin. Bylece,
stoktaki mal miktar ve maliyet, insanlarn okuyabildii metin tabanl edeerleri yerine ikili
biimleri kullanlarak saklanmtr. Bu sayede, verileri insanlarn okuyabildii ekilden
evirmek zorunda kalmadan nmerik veriler zerinde ilem gerekletirmek mmkn olur.
Envanter programnda ilgin olan dier bir husus daha vardr. Dosyann sonunun nasl
tespit edildiine dikkat edin. kili girdi metotlar akn sonuna ulaldnda bir
EndOfStreamException frlattklar iin program istenilen eyi bulana kadar ya da bu
kural d durum retilene kadar dosyay okur. Bylece, dosyann sonunu tespit etmek iin zel
bir mekanizmaya gerek yoktur.
Rasgele Eriimli Dosyalar
Bu aamaya kadar sral dosyalar (sequential files) kullana geldik. Sral dosyalar, bir byte
ardndan bir dier byte eklinde, tamamen dorusal olarak eriilen dosyalardr. Ancak; C#, bir
dosyann ieriine rasgele erimenize de imkan vermektedir. Bunun iin FileStream tarafn-
dan tanmlanan Seek() metodunu kullanacaksnz. Bu metot, dosya konum belirtecini (buna
dosya iaretisi de denir) dosya iinde herhangi bir noktaya ayarlamanza olanak tanr.
Seek() metodu aada gsterilmitir:
long Seek(long yeniKonum, SeekOrigin orijin)
Burada yeniKonum, dosya iaretisinin yeni konumunu, orijin ile belirtilen konumdan
byte cinsinden uzaklk olarak belirtir. orijin, SeekOrigin numaralandrmas tarafndan
tanmlanan u deerlerden biri olacaktr:

HERKES N C#
KISIM I C# DL

424
Deer Anlam
SeekOrigin.Begin Dosyann bandan balayarak ara.

SeekOrigin.Current Mevcut konumdan balayarak ara.
SeekOrigin.End Dosyann sonundan balayarak ara.

Seek() arldktan sonra bir sonraki okuma ya da yazma ilemi yeni dosya konumunda
gerekletirilecektir. Arama srasnda bir hata meydana gelirse bir IOException frlatlr.
Eer sz konusu ak, konum taleplerini desteklemiyorsa, bir NotSupportedException
frlatlr.
te, rasgele eriimle ilgili I/O ilemlerini gsteren bir rnek. Bu program bir dosyaya
byk harflerle alfabeyi yazar ve sonra bunu dosyadan srasz olarak geri okur.
// Rasgele erisimi gosterir.

using System;
using System.IO;

class RandomAccessDemo {
public static void Wain() {
FileStream f;
char ch;

try {
f = new FileStream(random.dat, FileMode.Create);
}
catch(IOException exc) {
Console.WriteLine(exc.Message);
return;
}

// Alfabeyi yaz.
for(int i = 0; i < 26; i++) {
try {
f.WriteByte((byte)(A + i));
}
catch(IOException exc) {
Console.WriteLine(exc.Message);
return;
}
}

try {
// Simdi, belirli degerleri geri oku
f.Seek(0, SeekOrigin.Begin); // ilk bytei ara
ch = (char) f.ReadByte();
Console.WriteLine(First value is + ch);

f.Seek(1, SeekOrigin.Begin); // ikinci bytei ara
ch = (char) f.ReadByte();
Console.WriteLine(Second value is + ch);
BLM 14: I/O KULLANIMI

HERKES N C#
425

f.Seek(4, SeekOrigin.Begin); // 5inci bytei ara
ch = (char) f.ReadByte();
Console.WriteLine(Fifth value is + ch);

Console.WriteLine();

// Simdi, bir baska deger daha oku.
Console.WriteLine(Here is every other value: );
for(int i = 0; i < 26; i += 2) {
f.Seek(i, SeekOrigin.Begin); // inici bytei ara
ch = (char) f.ReadByte();
Console.Write(ch + );
}
}
catch(IOException exc) {
Console.WriieLine(exc.Message);
}

Console.WriteLine();
f.Close();
}
}
Programn kts aadaki gibidir:
First value is A
Second value is B
Fifth value is E

Here is every other value:
A C E G I K M O Q S U W Y
MemoryStreamin Kullanm
Kimi zaman, dorudan bir aygttan girdi okumak veya dorudan bir aygta kt yazmak
yerine, girdileri bir diziden okumak ya da ktlar bir diziye yazmak kullanldr. Bunu
gerekletirmek iin MemoryStreami kullanacaksnz. MemoryStream, girdi ve/veya kt
iin bir byte dizisi kullanan Streamin bir uygulamasdr. Bunu tanmlayan yaplandrclardan
biri u ekildedir:
MemoryStream(byte[] tampon)
Burada tampon, I/O taleplerinin kayna ve/veya hedefi olarak kullanlacak olan bir byte
dizisidir. Bu yaplandrc tarafndan oluturulan ak, okunabilir ve yazlabilir; stelik
Seek()i de destekler. tamponu, tampona ynlendireceiniz ktlar tutabilecek byklkte
yapmanz gerektiini hatrlamalsnz.
Aada, MemoryStreamin kullanmn gsteren bir program yer almaktadr:
// MemoryStreami gosterir.


HERKES N C#
KISIM I C# DL

426
using System;
using System.IO;

class MemStrDemo {
public static void Main() {
byte[] storage = new byte[255];

// Bellek tabanli bir akis olustur.
MemoryStream memstrm = new MemoryStream(storage);

// memstrmi bir okuyucu ve yazici icine yerlestir.
StreamWriter memwtr = new StreamWriter(memstrm);
StreamReader memrdr = new StreamReader(memstrm);

// memwtr araciligiyla storagea yaz.
for(int i = 0; i < 10; i++)
memwtr.WriteLine(byte [ + i + ]: + i);

// en sona bir nokta koy
memwtr.Write(.);

memwtr.Flush();

Console.WriteLine(Reading from storage directly: );

// storagein icerigini dogrudan goster.
foreach(char ch in storage) {
if(ch == .) break;
Console.Write(ch);
}

Console.WriteLine(\nReading through memrdr: );

// Akis okuyucusunu kullanarak memstrmden oku.
memstrm.Seek(0, SeekOrigin.Begin); // dosya isaretcisini
sifirla

string str = memrdr.ReadLine();
while(str != null) {
str = memrdr.ReadLine();
if(str.CompareTo(.) == 0) break;
Console.WriteLine(str);
}
}
}
Programn kts aada gsterilmitir:
Reading from storage directly:
byte [0]: 0
byte [1]: 1
byte [2]: 2
byte [3]: 3
byte [4]: 4
byte [5]: 5
BLM 14: I/O KULLANIMI

HERKES N C#
427
byte [6]: 6
byte [7]: 7
byte [8]: 8
byte [9]: 9

Reading through memrdr:
byte [1]: 1
byte [2]: 2
byte [3]: 3
byte [4]: 4
byte [5]: 5
byte [6]: 6
byte [7]: 7
byte [8]: 8
byte [9]: 9
Programda storage adnda bir byte dizisi oluturulmaktadr. Bu dizi daha sonra memstrm
adnda bir MemoryStream iin altta yatan bir depolama olarak kullanlmaktadr. memstrmden
memrdr adnda bir StreamReader ve memwtr adnda bir StreamWriter oluturulur.
memwtr kullanlarak kt, bellek tabanl aka yazlr. kt yazldktan sonra memwtr
zerinden flush()n arldna dikkat edin. memwtrin tamponunda kalan ieriin altta
yatan diziye gerekten yazlmas iin bu gereklidir. Sonra, altta yatan byte dizisinin ierii
foreach dngs kullanlarak elle gsterilir. Daha sonra Seek() kullanlarak dosya iaretisi,
akn balangcn gsterecek ekilde sfrlanr ve memrdr kullanlarak bellek ak okunur.
Bellek tabanl aklar programlamada olduka kullanldr. rnein, kty ihtiya olana
kadar dizide saklayarak karmak ktlar oluturabilirsiniz. Bu teknik, zellikle Windows gibi
bir GUI ortam iin programlama yaparken ie yarar. Ayrca bir standart ak da bir diziden
okuyacak ekilde ynlendirebilirsiniz. Bu rnein, test bilgilerini bir programa beslemek iin
yararl olabilir.
StringReader ve StringWriter Kullanm
Baz uygulamalarda bellek tabanl I/O ilemlerini gerekletirirken altta yatan depolama
olarak bir byte dizisi yerine bir string kullanmak ok daha kolay olabilir. Byle bir durum
sz konusu olduunda StringReader ve StringWriter kullann. StringReader,
TextReaderdan; StringWriter da TextWriterdan tretilmitir. Bylece, bu aklarn
sz konusu iki snf tarafndan tanmlanan metotlara eriimleri vardr. rnein, bir
StringReader zerinden ReadLine(); bir StringWriter zerinden de WriteLine()
arabilirsiniz.
StringReader iin yaplandrc aada gsterilmitir:
StringReader(string str)
Burada str, okunacak karakter katardr.

HERKES N C#
KISIM I C# DL

428
StringWriter birka yaplandrc tanmlar. Bunlardan bizim burada kullanacamz
udur:
StringWriter()
Bu yaplandrc, ktsn bir karakter katarna yerletirecek olan bir yazc oluturur. Bu
karakter katar StringWriter tarafndan otomatik olarak oluturulur. Bu karakter katarnn
ieriini ToString()i ararak elde edebilirsiniz.
te, StringReader ve StringWriter kullanan bir rnek:
// StringReader ve StringWriter gosterir.

using System;
using System.IO;

class StrRdrDemo {
public static void Main() {
// Bir StringWriter olustur
StringWriter strwtr = new StringWriter();

// StringWritera yaz.
for(int i = 0; i < 10; i++)
strwtr.WriteLine(This is i: + i);

// Bir StringReader olustur

StringReader strrdr = new StringReader(strwtr.ToString());

// Simdi, StringReaderdan oku.
string str = strrdr.ReadLine();
while(str != null) {
str = strrdr.ReadLine();
Console.WriteLine(str);
}
}
}
kt aada gsterilmitir:
This is i: 1
This is 1: 2
This is i: 3
This is i: 4
This is i: 5
This is i: 6
This is i: 7
This is i: 8
This is i: 9
Program ilk nce strwrt adnda bir StringWriter oluturur ve WriteLine()
kullanarak kty buna yazar. Sonra, strwrt iindeki karakter katarn kullanarak bir
BLM 14: I/O KULLANIMI

HERKES N C#
429
StringReader oluturur. Bu karakter katar, strwrt zerinden ToString() arlarak elde
edilir. Son olarak, bu karakter katarnn ierii ReadLine() kullanlarak okunur.
Nmerik Karakter Katarlarn Dahili Gsterimlerine
Dntrmek
I/O konusunu terk etmeden nce nmerik karakter katarlarn okurken kullanl olan bir
teknii inceleyeceiz. Bildiiniz gibi, C#n WriteLine() metodu, int ve double gibi
standart tiplerin nmerik deerleri de dahil olmak zere, eitli tipten verilerin konsola ktsn
almak iin kullanl yollardan biridir. Bylece, WriteLine() nmerik deerleri otomatik
olarak insanlarn okuyabildii ekle dntrr. Ancak, C# bunun tersini salamaz: Nmerik
deerleri simgeleyen karakter katarlarn okuyup, bunlar dahili, ikili biime dntren bir
girdi metodu salamaz. rnein, 100 gibi bir karakter katarn okuyan ve bunu karlk gelen
ve bir int deikende saklanabilecek ikili deere otomatik olarak dntren bir girdi metodu
mevcut deildir. Bunu gerekletirmek iin tm standart nmerik tipler iin tanml olan bir
metot kullanmanz gerekecektir: Parse().
Konuya balamadan nce nemli bir gerei bildirmek gereklidir: int ve double gibi
C#n tm standart tipleri aslnda .NET Framework tarafndan tanmlanan yaplar iin birer
takma isimden (alias) ibarettir. Gerekte, C# tiplerinin .NET yap tiplerinden ayrmsanamaz
olduunu Microsoft aka bildirmektedir. Biri, dierine verilen bir baka isimden ibarettir.
C#n deer tipleri yaplar tarafndan desteklendikleri iin, deer tipleri kendileri iin
tanmlanm yelere sahiplerdir.
Nmerik tipler iin, .NET yap isimleri ve bunlarn C# anahtar kelimeleri cinsinden
edeerleri aada gsterilmitir:

.NET Yap Ad
C# Ad
Decimal decimal
Double double
Single float
Int16 short
Int32 int
Int64 long
UInt16 ushort
UInt32 uint
UInt64 ulong
Byte byte
SByte sbyte


HERKES N C#
KISIM I C# DL

430
Yaplar System isim uzaynda tanmlanmtr. Bylece, Int32 iin tam olarak belirtilmi
isim System.Int32dir Bu yaplar, deer tiplerini C#n nesne hiyerarisine tam olarak
entegre etmeye yardmc olan geni bir metot dizisi sunmaktadr. Bir yan fayda olarak, nmerik
yaplar ayrca bir nmerik karakter katarn, karlk gelen ikili edeerine dntren statik
metotlar da tanmlamaktadrlar. Bu dnm metotlar aada gsterilmitir. Bunlarn her biri,
sz konusu karakter katarna karlk gelen bir deer dndrr.

Yap
Dnm Metodu
Decimal static decimal Parse(string str)
Double static double Parse(string str)
Single static float Parse(string str)
Int64 static long Parse(string str)
Int32 static int Parse(string str)
Int16 static short Parse(string str)
UInt64 static ulong Parse(string str)
UInt32 static uint Parse(string str)
UInt16 static ushort Parse(string str)
Byte static byte Parse(string str)
SByte static sbyte Parse(string str)

Eer str, metodu aran tip tarafndan tanmlanan ekliyle geerli bir say iermiyorsa
Parse() metodu bir FormatException frlatacaktr. str null deerine sahipse bir
ArgumentNullException frlatlr; strn iindeki deer aran tipi ayorsa
OverflowException frlatlr.
Ayrtrma (parsing) metotlar, klavyeden ya da bir metin dosyasndan bir karakter katar
olarak okunan bir nmerik deeri, gerek dahili biimine dntrmek iin kolay bir yntem
sunmaktadrlar. rnein aadaki program, kullanc tarafndan girilen bir say listesinin
ortalamasn hesaplar. Program ncelikle, kullancya ortalamas hesaplanacak deerlerin
adedini sorar. Sonra, ReadLine() kullanarak bu sayy okur ve sz konusu karakter katarn
bir tamsayya dntrmek iin Int32.Parse() kullanr. Daha sonra, karakter katarlarn
karlk gelen double edeerlerine dntrmek iin Double.Parse() kullanarak
deerlerin girdisini alr.
/* Bu program, kullanici tarafndan girilen bir sayi listesinin
ortalamasini hesaplar. */

using System;
using System.IO;

class AvgNums {
public static void Main() {
string str;
BLM 14: I/O KULLANIMI

HERKES N C#
431
int n;
double sum = 0.0;
double avg, t;

Console.Write(How many numbers will you enter: );
str = Console.ReadLine();
try {
n = Int32.Parse(str);
}
catch(FormatException exc) {
Console.WriteLine(exc.Message);
n = 0;
}
catch(OverflowException exc) {
Console.WriteLine(exc.Message);
n = 0;
}

Console.WriteLine(Enter + n + values.);
for(int i = 0; i < n; i++) {
Console.Write(: );
str = Console.ReadLine();
try {
t = Double.Parse(str);
} catch(FormatException exc) {
Console.WriteLine(exc.Message);
t = 0.0;
}
catch(OverflowException exc) {
Console.WriteLine(exc.Message);
t = 0;
}
sum += t;
}
avg = sum / n;
Console.WriteLine(Average is + avg);
}
}
te, programn rnek bir almas:
How many numbers will you enter: 5
Enter 5 values.
: 1.1
: 2.2
: 3.3
: 4.4
: 5.5
Average is 3.3
Son bir husus: Dntrmeye altnz deerin tipine uygun bir ayrtrma metodu
kullanmalsnz. rnein, kayan noktal bir deer ieren bir karakter katar zerinde
Int32.Parse() kullanmaya almak istenilen sonucu vermeyecektir.



O N B E N C B L M


DELEGELER VE
OLAYLAR





















15
BLM 15: DELEGELER VE OLAYLAR

HERKES N C#
433
Bu blmde C#n iki yeni zellii incelenmektedir: Delegeler ve olaylar. Bir delege
(delegate), bir metodu paketleme (encapsulation) yollarndan biridir. Bir olay (event) ise bir
faaliyetin meydana geldiini belirten bir bildirgedir. Delegeler ve olaylar birbiriyle
balantldr, nk bir olay bir delege zerine ina edilir. Bunlarn her ikisi de birtakm
programlama grevlerini C#a uygulanabilecek ekilde geniletirler.
Delegeler
Gelin, delege terimini tanmlayarak balayalm. Aka ifade etmek gerekirse, bir delege
bir metoda referansta bulunabilen bir nesnedir. Bylece, bir delege oluturduunuzda bir
metoda ynelik bir referans tulabilen bir nesne oluturuyorsunuz, stelik, sz konusu metot
bu referans araclyla arlabilir. Yani, bir delege, referansta bulunduu metodu arabilir.
Bir metoda ynelik referans fikri balangta tuhaf grnebilir, nk genellikle biz
nesnelere atfta bulunan referanslar dnrz; fakat gerekte ikisi arasnda kk bir fark
vardr. Elinizdeki kitabn daha nceki blmlerinde de akland gibi, bir referans aslnda
bir bellek adresidir. Bylece, bir nesneye ynelik bir referans da aslnda sz konusu nesnenin
adresidir. Bir metot gerekte bir nesne olmasa bile, metodun da bellekte fiziksel bir konumu
vardr ve metodun balang adresi, metot arld zaman arlan adrestir. Bu adres bir
delegeye atanabilir. Bir delege bir kez bir metoda referansta bulunduktan sonra, sz konusu
metot bu delege araclyla arlabilir.

NOT


Eer C/C++ dillerine ainaysanz, C#taki bir delegenin C/C++taki fonksiyon
iaretisine benzediini bilmek iinize yarayacaktr.
Bir programn almas srasnda, delegenin referansta bulunduu metodu deitirmek
suretiyle, farkl metotlar armak iin ayn delegenin kullanlabileceini kavramak
nemlidir. Bu nedenle, bir delege tarafndan arlacak metot, derleme zamannda deil,
alma zamannda belirlenir. Bu, delegelerin salad balca avantajdr.
Bir delege, delegate anahtar kelimesi kullanlarak deklare edilir. Delege
deklarasyonunun genel ekli aada gsterilmitir:
delegate dn-tipi isim(parametre-listesi);
Burada dn-tipi, sz konusu delegenin araca metotlar tarafndan dndrlen
deerin tipidir. Delegenin ismi isim ile belirtilir. Delege araclyla arlan metotlarn
gerektirdii parametreler parametre-listesinde belirtilir. Bir delege yalnzca, dn tipi
ve paramelre listesi (yani, imzas) deklarasyonunda belirtilen deerlerle elenen metotlar
arabilir.
Bir delege, ya bir nesne ile ilikilendirilmi bir rnek metodu ya da bir snf ile
ilikilendirilmi bir static metodu arabilir. nemli olan, yalnzca sz konusu metodun
dn tipinin ve imzasnn delegeninkilerle uyumasdr.

HERKES N C#
KISIM I C# DL

434
Delegelerin kullanmlarn anlamak amacyla gelin, aada gsterilen basit bir rnekle
balayalm:
// Basit bir delege ornegi.

using System;

// Bir delege deklare et.
delegate string strMod(string str);
class DelegateTest {
// Bosluklari tire ile degistirir.
static string replaceSpaces(string a) {
Console.WriteLine(Replaces spaces with hyphens.);
return a.Replace( , -);
}

// Bosluklari yok et.
static string removeSpaces(string a) {
string temp = ;
int a;

Console.WriteLine(Removing spaces.);
for(i = 0; i < a.Length; i++)
if(a[i] != ) temp += a[i];

return temp;
}

// Bir karakter katarini ters cevir.
static string reverse(string a) {
string temp = ;
int i, j;

Console.WriteLine(Reversing string.);
for(j = 0; i = a.Length-1; i >= 0; i--, j++)
temp += a[i];

return temp;
}

public static void Main() {
// Bir delege yapilandir.
strMod strOp = new strtMod(replaceSpaces);
string str;

// Delege araciligiyla metotlari cagir.
str = strOp(This is a test.);
Console.WriteLine(Resulting string: + str);
Console.WriteLine();

strOp = new strMod(removeSpaces);
str = strOp(This is a test.);
Console.WriteLine(Resulting string: + str);
Console.WriteLine();

BLM 15: DELEGELER VE OLAYLAR

HERKES N C#
435
strOp = new strMod(reverse);
str = strOp(This is a test.);
Console.WriteLine(Resulting string: + str);
}
}
Programn kts aada gsterilmitir:
Replaces spaces with hyphens.
Resulting string: This-is-a-test.

Removing spaces.
Resulting string: Thisisatest.

Reversing string.
Resulting string: .tset a si sihT
imdi gelin bu program yakndan inceleyelim. Program, bir string parametresi alan ve
bir string dndren strMod adnda bir delege deklare etmektedir. DelegateTest iinde
her biri elenen bir imzaya sahip olan static metot deklare edilmektedir. Bu metotlar bir
tr string deiiklii gerekletirmektedir. replaceSpaces()in boluklar tire ile
deitirmek iin Replace() adnda, string metotlarndan birini kullandna dikkat edin.
Main()de strOp adnda bir strMod referans oluturulur ve buna
replaceSpaces()a atfta bulunan bir referans atanr. Aadaki satra zellikle dikkat
edin:
strMod strOp = new strMod(replaceSpaces);
replaceSpaces()in parametre olarak nasl aktarldna dikkat edin. Metodun
yalnzca ismi kullanlmaktadr; parametreleri belirtilmemitir. Bu genelletirilebilir. Bir
delegeyi rneklerken yalnzca delegenin referansta bulunmasn istediiniz metodun ismini
belirtirsiniz. Ayrca, metodun deklarasyonu, delegenin deklarasyonuyla elenmelidir. Eer
elenmiyorsa derleme srasnda bir hata ortaya kacaktr.
Sonra, aada gsterildii gibi strOp adndaki delege rnei araclyla
replaceSpacea() arlr:
str = strOp(This is a test.);
strOp, replaceSpaces()a referansta bulunduu iin burada arlan
replaceSpaces()tir.
Daha sonra strOpa, removeSpaces()e atfta bulunan bir referans atanr ve strOp
tekrar arlr. Bu kez removeSpaces() arlmtr.
Son olarak; strOpa, reverse()e atfta bulunan bir referans atanr ve strOp arlr.
Bu, reverse()in arlmasyla sonulanr.

HERKES N C#
KISIM I C# DL

436
Bu rnek, ok nemli bir zellie sahiptir: strOpa yaplan ar, strOpun arld
srada strOpun referansta bulunduu metodun da arlmasyla sonulanr. Bylece, hangi
metodun arlaca derleme zamannda deil, alma zamannda zmlenir.
Yukardaki rnekle static metotlar kullanlm olsa da, bir delege ayrca rnek
metotlara da referansta bulunabilir. Ancak bunu bir nesne referans araclyla
gerekletirmelidir. rnein, yukardaki programn yeniden yazlm bir versiyonu karakter
katar ilemlerinin StripgOps adnda bir snf iine yerletirilmi ekliyle aada yer
almaktadr:
// Delegeler ornek metotlara da referansta bulunabilir.

using System;

// Bir delege deklare et.
delegate string strMod(string str);

class StringOps {
// Bosluklari tire ile degistir.
public string replaceSpaces(string a) {
Console.WrteLine(Replaces spaces with hyphens.);
return a.Replace( , -);
}

// Bosluklari yok et.
public string removeSpaces(string a) {
string temp = ;
int i;

Console.WriteLine(Removing spaces.);
for(i = 0; i < a.Length; i++)
if(a[i] != ) temp += a[i];

return temp;
}

// Bir karakter katarini ters cevir.
public string reverse[string a) {
string temp = ;
int i, j;

Console.WriteLine(Reversing string.);
for(j = 0, i = a.Length - 1; i >= 0; i--, j++)
temp += a[i];

return temp;
}
}

class DelegateTest {
public static void Main() {
StringOps so = new StringOps(); // StringOpsun bir
ornegini olustur
BLM 15: DELEGELER VE OLAYLAR

HERKES N C#
437

// Bir delege yapilandir.
strMod strOp = new strMod(so.replaceSpaces);
string str;

// Delegeler araciligiyla metotlari cagir.
str = strOp(This is a test.);
Console.WriteLine(Resulting string: + str);
Console.WriteLine();

strOp = new strMod(so.removeSpaces);
str = strOp(This is a test.);
Console.WriteLine(Resulting string: + str);
Console.WriteLine();

strop = new strMod(so.reverse);
str = strOp(This is a test.);
Console.WriteLine(Resulting string: + str);
}
}
Bu program, ilk programla ayn kty retir, fakat bu kez sz konusu delege, metotlara
StringOpsn bir rnei zerinden referansta bulunur.
oklu ar
Bir delegenin en heyecan verici zelliklerinden biri oklu ary (multicasting)
desteklemesidir. Basit bir ifadeyle oklu ar, bir delege etkin klndnda otomatik olarak
arlacak metotlar iin bir ar listesi ya da bir ar zinciri oluturma becerisidir. Bu tr bir
zinciri oluturmak ok kolaydr. Yapmanz gereken yalnzca bir delege rneklemek, sonra da
metotlar zincire eklemek iin += operatrn kullanmaktr. Bir metodu zincirden karmak
iin -= kullann. (Delegeleri eklemek ve karmak iin +, - ve = iaretlerini ayr ayr da
kullanabilirsiniz, fakat += ve -= kullanm ok daha yaygndr.) Tek kstlama, oklu ar
uygulanmakta olan delegenin dn tipinin void olmas gerektiidir.
te bir oklu ar rnei. Bu rnek, nceki rnekler zerinde u deiiklikler yaplarak
elde edilmitir: Karakter katarn maniple eden metodun dn tipi void olarak
deitirilmitir; deitirilen karakter katarn, metodu aran koda dndrmek iin bir ref
parametresi kullanlmtr.
// coklu cagriyi gosterir.

using System;

// Bir delege deklare et.
delegate void strMod(ref string str);

class StringOps {
// Bosluklari tire ile degistirir.
static void replaceSpaces(ref string a) {
Console.WriteLine(Replaces spaces with hyphens.);

HERKES N C#
KISIM I C# DL

438
a = a.Replace( , -);
}

// Bosluklari yok et.
static void removeSpaces(ref string a) {
string temp = ;
int i;

Console.WriteLine(Removing spaces.);
for(i = 0; i < a.Length; i++)
if(a[i] != ) temp += a[i];

a = temp;
}

// Bir karakter katarini ters cevir.
static void reverse(ref string a) {
string temp = ;
int i, j;

Console.WriteLine(Reversing string.);
for(j = 0, i = a.Length-1; i >= 0; i--, j++)
temp += a[i];

a = temp;
}

public static void Main() {
// Delegeleri yapilandir.
strMod strOp;
strMod replaceSp = new strMod(replaceSpaces);
strMod removeSp = new strMod(removeSpaces);
strMod reverseStr = new strMod(reverse);
string str = This is a test;

// oklu cagriyi hazirla.
strOp = replaceSp;
strOp += reverseStr;

// coklu cagriyi cagir.
strOp(ref str);
Console.WriteLine(Resulting string: + str);
Console.WriteLine();

// replacei kaldir ve removeu ekle.
strOp -= replaceSp;
strOp += removeSp;

str = This is a test.; // karakter katarini sifirla

// coklu cagriyi cagir.
strOp(ref str);
Console.WriteLine(Resulting string: + str);
Console.WriteLine();
}
BLM 15: DELEGELER VE OLAYLAR

HERKES N C#
439
}
kt u eklidedir:
Replaces spaces with hyphens.
Reversing string.
Resulting string: tset-a-si-sihT

Reversing string.
Removing spaces.
Resulting string: .tsetasisihT
Main()de drt delege rnei oluturulmaktadr Bunlardan biri olan strOpa ilk deer
verilmemitir. Dier karakter katar zerinde deiiklik yapan belirli metotlara referansta
bulunmaktadr. Sonra, removeSpaces()i ve reverse()i aran bir oklu ar
oluturulur, Bu, aadaki satrlar yardmyla gerekletirilir:
strOp = replaceSp;
strOp += reverseStr;
ncelikle, strOpa replaceSpye atfta bulunan bir referans atanmaktadr Sonra, +=
kullanlarak reverseStr eklenmektedir. strOp arldnda her iki metot da arlr;
bunun sonucu olarak, ktdan da grlecei zere boluklar tire ile deitirilir ve karakter
katar ters evrilir.
Daha sonra, aadaki satr kullanlarak replaceSp zincirden karlr:
strOp -= replaceSp;
removeSp u satr kullanlarak zincire eklenir:
strop += removeSp;
Sonra, strOp yeniden arlr. Bu kez, boluklar yok edilmi ve karakter katar da ters
evrilmi durumdadr.
Delege zincirleri gl bir mekanizmadr, nk bir btn olarak altrlabilen bir takm
metotlar tanmlanmanza olanak tanrlar. Bu, baz tip kodlarn yapsn bytebilir. Ayrca,
delege zincirlerinin olaylar (events) asndan da zel bir deeri olduunu yaknda
reneceksiniz.
System.Delegate
Tm delegeler System.Delegateten kapal olarak tretilen snflardr. Normalde
System.Delegatein yelerini dorudan kullanmanz gerekmez. Bu kitapta
System.Delegate ak olarak kullanlmamaktadr. Ancak, System.Delegatein yeleri
belirli zelletirilmi durumlarda kullanl olabilirler.


HERKES N C#
KISIM I C# DL

440
Delegelere Neden Gerek Vardr?
nceki rnekler, delegelerin ardndaki nasl gereini gstermi olsalar da, aslnda
neden sorusunun yantn vermemilerdir. Genel olarak delegeler balca iki nedenden tr
kullanldr. ncelikle, bir sonraki blmde de grlecei gibi, delegeler olaylar destekler.
kincisi, delegeler sayesinde programnz, derleme zamannda hangi metodun altracan
tam olarak bilmese de, alma zamannda sz konusu metodu altrabilmektedir. Bu beceri,
bileenlerin yerletirilmesine olanak tanyan bir at oluturmak istediinizde olduka ie
yarar. rnein, bir izim program hayal edin (standart Windows Paint donats gibi bir
program). Bir delege kullanarak kullancnn zel renk filtreleri ya da grnt zmleyicileri
kullanmasna olanak tanyabilirsiniz. stelik, kullanc bu filtrelerden ya da
zmleyicilerden oluan bir sra da oluturabilir. Bu tr bir plan, delege kullanlarak
kolaylkla ele alnabilir.
Olaylar
Delege temeli zerine ina edilen bir baka nemli C# zellii ise olaydr (event). Bir
olay aslnda bir faaliyetin meydana geldiini bildiren otomatik bir bildirgedir. Olaylar u
ekilde alr: Bir olayla ilgilenen bir nesne, sz konusu olay iin bir olay yneticisi (event
handler) kaydeder. Olay meydana geldiinde tm olay yneticileri arlr. Olay yneticileri
delegelerle simgelenir. Olaylar bir snfn yeleridir ve event anahtar kelimesi kullanlarak
deklare edilirler. Olaylarn en sk kullanlan biimi aada gsterilmitir:
event olay-delegesi nesne; I
Burada olay-delegesi, olay desteklemek iin kullanlan delegenin addr; nesne ise
oluturulmakta olan spesifik olay nesnesinin addr.
Gelin imdi ok basit bir rnekle balayalm:
// Cok basit bir olay gosterimi.

using System;

// Bir olay icin bir delege deklare et.
delegate void MyEventHandler();

// Bir olay sinifi deklare et.
class MyEvent {
public event MyEventHandler SomeEvent;

// Olayi ateslemek icin bu cagrilir.
public void OnSomeEvent() {
if(SomeEvent != null)
SomeEvent();
}
}

class EventDemo {
BLM 15: DELEGELER VE OLAYLAR

HERKES N C#
441
// Bir olay yoneticisi.
static void handler() {
Console.WriteLine(Event occurred);
}

public static void Main() {
MyEvent evt = new MyEvent();

// handler()i olay listesine ekle.
evt.SomeEvent += new MyEventHandler(Handler);

// Olayi atesle.
evt.OnSomeEvent();
}
}
Bu program aadaki kty ekranda gsterir:
Event occurred
Basit olmasna ramen bu program, dzgn bir olay yneticisi iin gerekli olan tm
eleri iermektedir. Gelin imdi program dikkatle inceleyelim.
Program, olay yneticisi iin aada gsterildii gibi bir delege deklare ederek
balamaktadr:
delegate void MyEventHandler();
Tm olaylar bir delege araclyla etkili hale getirilirler. Bylece, olay delegesi olayn
imzasn tanmlamaktadr. Bu rnekte olay parametreleri haricinde hi bir parametreye izin
verilmemitir. Olaylara genellikle multicast uyguland iin bir olay void dndrmelidir.
Sonra, MyEvent adnda bir olay snf oluturulur. Bu snfn iinde someEvent adnda
bir olay nesnesi deklare edilir. Bunun iin aadaki satr kullanlr:
public event MyEventHandler SomeEvent;
Sz dizimine dikkat edin. Tm olay tipleri bu ekilde deklare edilirler.
Ayrca OnSomeEvent() metodu da MyEventin iinde deklare edilmektedir.
OnSomeEvent() bir programn bir olaya iaret etmek (ya. da atelemek) iin araca bir
metottur. (Yani, olay meydana geldiinde arlan metot budur.) Sz konusu metot,
SomeEvent delegesi araclyla, aada gsterilen ekilde, bir olay yneticisi arr:
if(SomeEvent != null)
SomeEvent();
Bir yneticinin sadece ve sadece someEvent null deere sahip olmadnda
arldna dikkat edin. Programnzn dier blmleri olay bildirgelerini almak iin bir olay
kaydetmeye ilgi gstermelidir. Bu nedenle, herhangi bir olay yneticisi kaydedilmeden nce
OnSomeEvent()in arlabilmesi mmkndr. null deerine sahip bir nesnenin

HERKES N C#
KISIM I C# DL

442
arlmasn nlemek amacyla olay delegesinin null deerine sahip olmadn garanti
etmek iin olay delegesi test edilmelidir.
EventDemo iinde handler() adnda bir olay yneticisi oluturulur. Bu rnekte olay
yneticisi yalnzca ekranda bir mesaj grntler, fakat dier yneticiler daha anlaml
faaliyetlerde bulunabilirler. Main()de, aada gsterildii gibi, bir MyEvent nesnesi
oluturulur ve handler() bu olay iin bir ynetici olarak kaydedilir:
My Event evt = new MyEvent();

// handler()i olay listesine ekle.
evt.SoneEvent += new MyEventHandler(handler);
Dikkat ederseniz, ynetici += operatr kullanlarak eklenir. Olaylar yalnzca += ve -=
operatrlerini desteklerler. Bu rnekte handler(), static bir metottur; fakat olay
yneticileri ayrca rnek metot da olabilirler.
Son olarak, sz konusu olay aada gsterildii gibi atelenmektedir:
// Olayi atesle.
evt.OnSomeEvent();
OnSomeEvent()i armak kaytl olay yneticilerinin tmnn arlmasna neden
olur. Bu rnekte yalnzca tek bir kaytl ynetici mevcuttur; fakat bir sonraki blmde
akland gibi daha fazla da olabilirdi.
Bir oklu ar Olay rnei
Tpk delegeler gibi olaylara da oklu ar uygulanabilir. Bu sayede, bir olay
bildirgesine birden fazla nesnenin yant vermesi mmkn olur. te bir olay oklu ars
rnei:
// Bir olay coklu cagrisi gosterimi.

using System;

// Bir olay icin bir delege deklare et.
delegate void MyEventHandler();

// Bir olay sinifi deklare et.
class MyEvent {
public event MyEventHandler SomeEvent;

// Olayi ateslemek icin bu cagrilir.
public void OnSomeEvent() {
if(SomeEvent != null)
SomeEvent();
}
}

class X {
BLM 15: DELEGELER VE OLAYLAR

HERKES N C#
443
public void Xhandler() {
Console.WriteLine(Event received by X object);
}
}

class Y {
public void Yhandler() {
Console.WriteLine(Event received by Y object);
}
}

class EventDemo {
static void handler() {
Console.WriteLine(Event received by EventDemo);
}

public static void Main() {
MyEvent evt = new MyEvent();
X xOb = new X();
Y yOb = new Y();

// Yoneticileri olay listesine ekle.
evt.SomeEvent += new MyEventHandler(handler);
evt.SomeEvent += new MyEventHandler(xOb.Xhandler);
evt.SomeEvent += new MyEventHandler(yOb.Yhandler);

// Olayi atesle.
evt.OnSomeEvent();
Console.WriteLine();

// Yoneticiyi ortadan kaldir.
evt.SomeEvent -= new MyEventHandler(xOb.Xhandler);
evt.OnSomeEvent();
}
}
Programn kts aada gsterilmitir:
Event received by EventDemo
Event received by X object
Event received by Y object

Event received by EventDemo
Event received by Y object
Bu rnek X ve Y adnda iki ilave snf oluturmaktadr. Bu snflar da ayrca
MyEventHandler ile uyumlu olay yneticileri tanmlamaktadrlar. Bylece, bu yneticiler
olay zincirinin bir halkas haline gelebilirler. X ve Ynin iindeki yneticilerin static
olmadna dikkat edin. Bunun anlam udur: Bunlarn her biri iin nesneler oluturulmal ve
her nesne rneine balanan ynetici olay zincirine eklenmelidir. rnek ve static
yneticiler arasndaki farklar bir sonraki blmde incelenmektedir.

HERKES N C#
KISIM I C# DL

444
Olay Yneticileri Olarak static Metotlara Kar rnek
Metotlar
rnek rnetotlar ve static metotlarn her ikisi de olay yneticileri olarak kullanlabilir
olmalarna ramen, nemli bir adan farkllk gsterirler. static bir metot olay ynetici
olarak kullanldnda, olay bildirgesi snfa (ve dolayl olarak snfn tm nesnelerine)
uygulanr Bir rnek metot olay yneticisi olarak kullanldnda ise, olaylar spesifik nesne
rneklerine gnderilir. Bylece, bir snfn olay bildirgesi almak isteyen her bir nesnesi ayr
ayr kaydedilmelidir. Pratikte olay yneticilerinin birou rnek metotlardr; fakat bu durum,
kukusuz sz konusu spesifik uygulamaya bal olarak deiebilir. Gelin imdi bunlarn her
biri iin bir rnee gz atalm.
Aadaki program, olay yneticisi olarak bir rnek metot tanmlayan X adnda bir snf
oluturur. Bunun anlam udur: Olaylar almak iin her X nesnesi ayr ayr kaydedilmelidir.
Bu gerei gstermek iin program, bir olay X tipinde nesneye oklu ar uygular.
// Ornek olay yoneticileri kullanildiginda
nesneler bildirgeleri ayri ayri alirlar. */

using System;

// Bir olay icin bir delege deklare et.
delegate void MyEventHandler();

// Bir olay sinifi deklare et.
class MyEvent {
public event MyEventHandler SomeEvent;

// Olayi ateslemek icin bu cagrilir.
public void OnSomeEvent() {
if(SomeEvent != null)
SomeEvent();
}
}

class X {
int id;

public X(int x) { id = x; }

/* Bu, olay yoneticisi olarak kullanilacak olan
bir ornek metottur. */
public void Xhandler() {
Console.WriteLine(Event received by object + id);
}
}

class EvantDemo {
public static void Main() {
MyEvent evt = new MyEvent();
X o1 = new X(1);
BLM 15: DELEGELER VE OLAYLAR

HERKES N C#
445
X o2 = new X(2);
X o3 = new X(3);

evt.SomeEvent += new MyEventHandler(o1.Xhandler);
evt.SomeEvent += new MyEventHandler(o2.Xhandler);
evt.SomeEvent += new MyEventHandler(o3.Xhandler);

// Olayi atesle.
evt.OnSomeEvent();
}
}
Bu programn kts aadaki gibidir:
Event received by object 1
Event received by object 2
Event received by object 3
ktdan grld gibi, her nesne ilgilendii olaya kendi ilgisini ayr ayr kaydeder,
ayrca her nesne ayr bir bildirge alr.
Alternatif olarak, bir static metot olay yneticisi olarak kullanldnda olaylar
nesnelerden bamsz alarak ele alnrlar. Aadaki program bunu gsterir:
// Bir static metot olay yoneticisi olarak kullanildiginda bir
sinif, bildirgeyi alir. */

using System;

// Bir olay icin bir delege deklare et.
delegate void MyEventHandler();

// Bir olay sinifi deklare et.
class MyEvent {
public event MyEventHandler SomeEvent;

// Olayi ateslemek icin bu cagrilir.
public void OnSameEvent() {
if(SomeEvent != null)
SomeEvent();
}
}

class X {
/* Bu, olay yoneticisi olarak kullanilacak olan
static bir metottur. */
public static void Xhandler() {
Console.WriteLirte(Event received by class.);
}
}

class EventDemo {
public static void Main() {
MyEvent evt = new MyEvent();


HERKES N C#
KISIM I C# DL

446
evt.SomeEvent += new MyEventHandler(X.Xhandler);

// Olayi atesle.
evt.OnSomeEvent();
}
}
Bu programn kts aadaki gibidir:
Event received by class.
Programda hi X tipinde bir nesne oluturulmadna dikkat edin. Ancak; handler()
Xin bir static metodu olduu iin SomeEvente ilitirilebilir ve OnSomeEvent()
arldnda gereklenebilir.
Olay Eriimcilerinin Kullanm
event ifadesinin iki ekli mevcuttur. nceki rneklerde kullanlan ekli ile olay
yneticisinin ar listesini otomatik olarak yneten olaylar oluturulmutu. Olay
yneticilerini listeye eklemek ya da listeden karmak da bu kapsamda yer alyordu. Bylece,
listenin ynetimiyle ilgili ilevselliin herhangi bir ksmn sizin kendi kendinize
uygulamanza gerek kalmyordu. Bu tr olaylar ayrntlar sizin adnza kontrol altna aldklar
iin ak farkla en yaygn olarak kullanlan trlerdir. Olay yneticisi listesinin ilemlerini
kendiniz salamanz, belki de bir tr zelletirilmi olay depolama mekanizmas uygulamanz
da her eye ramen mmkndr.
Olay yneticisi listesini kontrol altna almak iin olay eriimcilerinin (event accessor)
kullanmna olanak tanyan, event ifadesinin ikinci eklini kullanacaksnz. Eriimciler, olay
yneticisinin uygulan biimi zerinde size kontrol salarlar.
Olay yneticisi listesini kontrol altna almak iin olay eriimcilerin kullanmna olanak
tanyan, event ifadesinin ikinci eklini kullanacaksnz. Eriimciler, olay yneticisi listesinin
uygulan biimi zerinde kontrol kurmanz salarlar. event ifadesinin bu ekli aada
gsterilmitir:
event olay-delegesi olay-ismi {
add {
// zincire bir olay eklemek iin kod
}

remove {
// zincirden bir olay karmak iin kod
}
}
event ifadesinin bu ekli iki olay eriimcisi iermektedir: add ve remove. add
eriimcisi, bir olay yneticisi += kullanlarak bir olay zincirine eklendiinde arlr. remove
eriimcisi ise, bir olay yneticisi -= kullanlarak zincirden karldnda arlr.
BLM 15: DELEGELER VE OLAYLAR

HERKES N C#
447
add ya da remove arldnda eklenilecek ya da karlacak olay yneticisi parametre
olarak aktarlr. Dier tipteki eriimcilerde olduu gibi, bu parametre value olarak
adlandrlr. add ve removeu uygulayarak kendi isteklerinize uygun bir olay yneticisi
depolama plan tanmlayabilirsiniz. rnein, yneticileri saklamak iin bir dizi, yn ya da
kuyruk kullanabilirsiniz.
te, event ifadesinin eriimci eklini kullanan bir rnek. Programda olay yneticilerini
tutmak iin bir dizi kullanlmaktadr. Dizi yalnzca eleman uzunluunda olduu iin,
herhangi bir anda zincirde yalnzca olay yneticisi tutulabilir.
/* Olay cagri listesini yonetmek iin
istege gore bir yontem olusturmak. */

using System;

// Bir olay icin bir delege deklare et.
delegate void MyEventHandler();

// En fazla 3 olay tutabilen bir olay sinifi deklare et.
class MyEvent {
MyEventHandler[] evnt = new MyEventHandler[3];

public event MyEventHandler SomeEvent {
// Listeye bir olay ekle.
add {
int i;

for(i = 0; i < 3; i++)
if(evnt[i] == null) {
evnt[i] = value;
break;
}
if(i == 3) Console.WriteLine(Event list full.);
}

// Listeden bir olay cikart.
remove {
int i;

for(i = 0; i < 3; i++)
if(evnt[i] == value) {
evnt[i] = null;
break;
}
if(i == 3)
Console.WriteLine(Event handler not found.);
}
}

// Olaylari ateslemek icin bu cagrilir.
public void OnSomeEvent() {
for(int i = 0; i < 3; i++)
if(evnt[i] != null) evnt[i]();

HERKES N C#
KISIM I C# DL

448
}
}

// MyEventHandler kullanan bazi siniflar olustur.
class W {
public void Whandler() {
Console.WriteLine(Event received by W object);
}
}

class X {
public void Xhandler() {
Console.WriteLine(Event received by X object);
}
}

class Y {
public void Yhandler() {
Console.WriteLine(Event received by Y object);
}
}

class Z {
public void Zhandler() {
Console.WriteLine(Event received by Z object);
}
}

class EventDemo {
public static void Main() {
MyEvent evt = new MyEvent();
W wOb = new W();
X xOb = new X();
Y yOb = new Y();
Z zOb = new Z();

// Yoneticileri olay listesine ekle.
Console.WriteLine(Adding events.);
evt.SomeEvent += new MyEventHandler(wOb.Whandler);
evt.SomeEvent += new MyEventHandler(xOb.Xhandler};
evt.SomeEvent += new MyEventHandler(yOb.Yhandler);

// Bunu saklayamaz -- dolu.
evt.SomeEvent += new MyEventHandler(zOb.Zhandler);
Console.WriteLine();
// Olaylari atesle.
evt.OnSomeEvent();
Console.WriteLine();

// Yoneticiyi ortadan kaldir.
Console.WriteLine(Remove xOb.Xhandler.);
evt.SomeEvent -= new MyEventHandler(xOb.Xhandler);
evt.OnSomeEvent();

Console.WriteLine();
BLM 15: DELEGELER VE OLAYLAR

HERKES N C#
449

// Tekrar cikarmaya calis.
Console.WriteLine(Try to remove xOb.Xhandler again.);
evt.SomeEvent -= new MyEventHandler(xOb.Xhandler);
evt.OnSomeEvent();

Console.WriteLine();

// Simdi, Zhandleri ekle.
Console.WriteLine(Add zOb.Zhandler.);
evt.SomeEvent += new MyEventHandler(zOb.Zhandler);
evt.OnSomeEvent();
}
}
Programn kts aada gsterilmitir:
Adding events.
Event list full.

Event received by W object
Event received by X object
Event received by Y object

Remove xOb.Xhandler.
Event received by W object
Event received by Y object

Try to remove xOb.Xhandler again.
Event handler not found.
Event received by W object
Event received by Y object

Add zOb.Zhandler.
Event received by W object
Event received by Z object
Event received by Y object
Gelin imdi bu program yakndan inceleyelim. lk nce, MyEventHandler adnda bir
olay yneticisi delegesi tanmlanr. Sonra; MyEvent, aada gsterildii gibi, olay
yneticilerinden oluan elemanl evnt adnda bir dizi tanmlayarak balar:
MyEventHandler[] evnt = new MyEventHandler[3];
Bu dizi, olay zincirine eklenen olay yneticilerini saklamak iin kullanlacaktr. evntin
elemanlarna balangta varsaylan deer olarak null atanr.
Srada, eriimci tabanl event ifadesi vardr. Bu ifade aada gsterilmitir:
public event MyEventHandler SomeEvent {
// Listeye bir olay ekle.
add {
int i;


HERKES N C#
KISIM I C# DL

450
for(i = 0; i < 3; i++)
if(evnt[i] == null) {
evnt[i] = value;
break;
}
if(i == 3) Console.WriteLine(Event list full.);
}

// Listeden bir olay cikart.
remove {
int i;

for(i = 0; i < 3; i++)
if(evnt[i] == value) {
evnt[i] = null;
break;
}
if (i == 3) Console.WriteLine(Event handler not found.);
}
}
Bir olay yneticisi eklenecei zaman add arlr ve yneticiye atfta bulunan bir referans
(value iinde tutulan) evntin kullanlmayan ilk elemanna yerletirilir. Eer bo bir eleman
yoksa, bir hata durumu rapor edilir. evnt yalnzca elemanl olduu iin yalnzca olay
yneticisi saklanabilir. Bir olay yneticisi karlaca zaman remove arlr ve value
zerinden aktarlan ve sz konusu yneticiye atfta bulunan referans evnt dizisi iinde aranr.
Eer bulunursa dizide karlk gelen elemana null deeri atanr, bylece ynetici listeden
karlm olur.
Bir olay atelendiinde OnSomeEvent() arlr. OnSomeEvent(), olay yneticilerinin
her birini srayla ararak evnt dizisi zerinden tekrarlayarak ilerler.
nceki rneklerde grld gibi, gerekli olduunda, olay yneticileri iin istee uygun
bir depolama mekanizmas uygulamak nispeten kolaydr. Uygulamalarn birounda aslnda
eventin eriimci olmayan eklinin salad varsaylan depolama daha iyidir. eventin
eriimci tabanl ekli, belirli zelletirilmi durumlarda her eye ramen kullanl olabilir.
rnein elinizdeki bir programda olay yneticilerinin zincire eklendikleri sraya gre deil de
kendi ncelik sralarna gre altrlmalar gerekiyorsa, bu durumda yneticileri saklamak
iin bir ncelikli kuyruk kullanabilirsiniz.
Olaylarn eitli zelikleri
Olaylar arayzlerde belirtilebilir. Sz konusu olay, uygulamay gerekletiren snflar
tarafndan salanmaldr. Olaylar abstract olarak belirtilebilir. Olay bir tretilmi snf
uygulamaldr. Ancak, eriimci tabanl olaylar abstract olamaz. Bir olay sealed olarak
belirtilebilir. Bir olay sanal (virtual) olabilir; yani, tretilmi bir snf iinde devre d
braklabilir.
BLM 15: DELEGELER VE OLAYLAR

HERKES N C#
451
.NETte Olaylarla lgili Esaslar
C# istediiniz her tipten olay yazmanza olanak tanmaktadr. Bununla birlikte,
bileenlerin .NET Framework ile uyumluluu iin Microsoftun bu amaca ynelik
yerletirdii esaslar takip etmeniz gerekecektir. Bu esaslarn znde, olay yneticilerinin iki
parametreye sahip olmas gerektii yer almaktadr. lk parametre, olay reten nesneye bir
referanstr. kincisi ise, ynetici tarafndan istenen dier bilgileri ieren EventArgs tipinde
bir parametredir. Bylece, .NET uyumlu olay yneticileri genel olarak u ekilde olacaktr:
void handler(objeet kaynak, EventArgs arg) {
// ...
}
Genellikle kaynak parametresine metodu aran kod tarafndan this aktarlr.
EventArgs parametresi ek bilgiler ierir ve gerekli deilse dikkate alnmayabilir.
EventArgs snfnn kendisi bir yneticiye ek veri aktarmak iin kullanacanz alanlar
iermez. Bunun yerine EventArgs, gerekli alanlar ieren bir snf kendisinden
tretebileceiniz bir temel snf olarak kullanlr. Ancak, birok ynetici ek veri
gerektirmedii iin, veri iermeyen bir nesneyi belirten Empty adndaki static alan
EventArgs iinde yer almaz.
te, .NET uyumlu bir olay oluturan bir rnek:
// .NET-uyumlu bir olay.

using System;

// EventArgs dan bir sinif turet.
class MyEventArgs : EventArgs {
public int eventnum;
}

// Bir olay icin bir delege deklare et.
delegate void MyEventHandler(object source, MyEventArgs arg);

// Bir olay sinifi deklare et.
class MyEvent {
static int count = 0;

public event MyEventHandler SomeEvent;

// Bu, SomeEventi atesler.
public void OnSomeEvent() {
MyEventArgs arg = new MyEventArgs();

if(SomeEvent != null) {
arg.eventnum = count++;
SomeEvent(this, arg);
}
}

HERKES N C#
KISIM I C# DL

452
}

class X {
public void handler(object source, MyEventArgs arg) {
Console.WriteLine(Event + arg.eventnum +
received by an X object.);
Console.WriteLine(Source is + source);
Console.WriteLine();
}
}

class Y {
public void handler(object source, MyEventArgs arg) {
Console.WriteLine(Event + arg.eventnum +
received by a Y object.);
Console.WriteLine(Source is + source);
Console.WriteLine();
}
}

class EventDemo {
public static void Main() {
X ob1 = new X();
Y ob2 = new Y();
MyEvent evt = new MyEvent();

// handler()i olay listesine ekle.
evt.SomeEvent += new MyEventHandler(ob1.handler);
evt.SomeEvent += new MyEventHandler(ob2.handler);

// Olayi atesle.
evt.OnSomeEvent();
evt.OnSomeEvent();
}
}
kt, aadadr:
Event 0 received by an X object.
Source is MyEvent

Event 0 received by a Y object.
Source is MyEvent

Event 1 received by an X object.
Source is MyEvent

Event 1 received by a Y object.
Source is MyEvent
Bu rnekte MyEventArgs, EventArgstan tretilmitir. MyEventArgs kendisi yalnzca
tek bir alan ekler; eventnum. Olay yneticisi delegesi MyEventHandler imdi .NET
Framework tarafndan istenen iki parametre almaktadr. nceden akland gibi, ilk
parametre olayn reticisine bir referanstr. kincisi ise, EventArgsa bir referans ya da
BLM 15: DELEGELER VE OLAYLAR

HERKES N C#
453
EventArgsdan tretilen bir snftr. Bu rnekte MyEventArgs tipinde bir nesneye
referanstr.
EventHandler Kullanm
Bir ok olay iin EventArgs parametresi kullanlmaz. Bu gibi durumlarda kodun
oluturulmasna kolaylk salamas iin .NET Framework, EventHandler adnda standart
bir delege tipi ierir. EventHandler, ek bir bilgi gerektirmeyen olay yneticilerini deklare
etmek iin kullanlabilir. te, EventHandler kullanan bir rnek:
// Standart EventHandler delegesini kullan.

using System;

// Bir olay sinfi deklare et.
class MyEvent {
public event EventHandler SomeEvent; // EventHandler
delegesini kullanir

// SomeEventi ateslemek icin bu cagrilir.
public void OnSomeEvent() {
if(SomeEvent != null)
SomeEvent(this, EventArgs.Empty);
}
}

class EventDemo {
static void handler(object source, EventArgs arg) {
Console.WriteLine(Event occurred);
Console.WriteLine(Source is + source);
}

public static void Main() {
MyEvent evt = new MyEvent();

// handler()i olay listesine ekle.
evt.SomeEvent += new EventHandler(handler);

// Olayi atesle.
evt.OnSomeEvent();
}
}
Bu rnekte, EventArgs parametresi kullanlmamtr; yer belirleyici bir nesne olan
EventArgs.Empty parametre olarak aktarlmtr. kt aada gsterildii gibidir:
Event occurred
Source is MyEvent



HERKES N C#
KISIM I C# DL

454
Olaylar Uygulamak: Bir rnek alma
Olaylar, Windows gibi mesaj tabanl ortamlarda ska kullanlrlar. Bu tr bir ortamda bir
program, bir mesaj alana kadar bekler ve sonra uygun bir davranta bulunur. Bu tr bir
mimari C# stili olay ynetimi iin ok uygundur, nk eitli mesajlar iin olay yneticileri
oluturmak ve bir mesaj alndnda yalnzca bir yneticiyi armak mmkndr, rnein,
farenin sol tuuna baslmasna karlk gelen mesaj bir olaya balanabilir. Sol tua
baslmasyla, kaytl tm yneticilere haber verilir.
Bu yaklam gsteren bir Windows program gelitirmek bu blmn kapsamnn
dnda kalmasna ramen, bu tr bir yaklamn nasl alaca hakknda fikir vermek
mmkndr. Aadaki program klavye vurularn ileyen bir olay yneticisi
oluturmaktadr. Sz konusu olay KeyPress olarak adlandrlr ve ne zaman bir tua baslsa
OnKeyPress() arlarak ilgili olay atelenir.
// Klavye vuruslariyla ilgili bir olay ornegi.

using System;

// Tusu tutan, istege uygun bir EventArgs sinifi turet.
class KeyEventArgs : EventArgs {
public char ch;
}

// Bir olay icin bir delege deklare et.
delegate void KeyHandler(object source, KeyEventArgs arg);

// Tus vuruslariyla ilgili bir olay sinifi deklare et.
class KeyEvent {
public event KeyHandler KeyPress;

// Bir tusa basildiginda bu cagrilir.
public void OnKeyPress(char key) {
KeyEventArgs k = new KeyEventArgs();

if(KeyPress != null) {
k.ch = key;
KeyPress(this, k);
}
}
}

// Tusa basildiginin haberini alan bir sinif.
class ProcessKey {
public void keyhandler(object source, KeyEventArgs arg) {
Console.WriteLine(Received keystroke: + arg.ch);
}
}

// Tusa basildiginin haberini alan bir baska sinif.
class CountKeys {
public int count = 0;
BLM 15: DELEGELER VE OLAYLAR

HERKES N C#
455

public void keyhandler(object source, KeyEventArgs arg) {
count++;
}
}

// KeyEventi goster.
class KeyEventDemo {
public static void Main() {
KeyEvent kevt = new KeyEvent();
ProcessKey pk = new ProcessKey();
CountKeys ck = new CountKeys();
char ch;

kevt.KeyPress += new KeyHandler(pk.keyhandler);
kevt.Keypress += new KeyHandler(ck.keyhandler);

Console.WriteLine(Enter some characters. +
Enter a period to stop.);
do {
ch = (char) Console.Read();
kevt.OnKeyPress(ch);
} while(ch != .);
Console.WriteLine(ck.count + keys pressed.);
}
}
te rnek bir alma:
Enter some characters. Enter a period to stop.
test.
Received keystroke: t
Received keystroke: e
Received keystroke: s
Received keystroke: t
Received keystroke: .
5 keys pressed.
Program, baslan bir tuu bir olay yneticisine aktarmak iin kullanlan KeyEventArgs
adnda bir snf treterek balar. Sonra, KeyHandler adnda bir delege, tua basma olaylar
iin ilgili olay yneticisini tanmlar. KeyEvent snf, tua basma olayn snf iine
paketlemekledir.
Program, baslan tular ele alan iki snf oluturmaktadr: ProcessKey ve CountKeys.
ProcessKey snf, baslan tular grntleyen keyhandler() adnda bir ynetici
iermektedir. CountKeys ise baslan tularn saysn srekli olarak takip etmektedir.
Main()de bir KeyEvent nesnesi oluturulur. Sonra, ProcessKey ve CountKeynin
nesneleri tanmlanr ve bunlarn keyhandler() metotlarna ynelik referanslar
kevt.KeyPress ar listesine eklenir. Daha sonra, bir tua basldnda
kevt.OnKeyPress()i aran bir dng balatlr. Bu, kaytl olay yneticilerinin
durumdan haberdar edilmesini salar.



O N A L T I N C I B L M


SM UZAYLARI,
N LEMC VE
ASSEMBLYLER



















16
BLM 16: SM UZAYLARI, N LEMC VE ASSEMBLYLER

HERKES N C#
457
Bu blmde, bir programn organizasyonu ve eriilebilirlii zerinde size daha fazla
kontrol salayan C# zellii ele alnmaktadr. Bunlar isim uzaylar (namespaces), nilemci
ve assemblylerdir.
sim Uzaylar
sim uzay (namespace), C#ta temel bir kavram olduu iin Blm 2de ksaca
bahsedilmiti. Aslnda, her C# program u veya bu ekilde bir isim uzayndan yararlanr.
Bundan nce isim uzaylarn ayrntl olarak incelemeye gerek grmedik, nk C#,
programnz iin otomatik olarak bir varsaylan isim uzay salar. Bylece, bataki
blmlerdeki programlar yalnzca varsaylan isim uzayn kullanmlard. Gerek dnyada ise
birok programn kendi isim uzaylarn gelitirmeleri ya da dier isim uzaylaryla etkilemeleri
gerekecektir. Bu blmde bunlar ayrntl olarak incelenmektedir.
Bir isim uzay, bir takm isimleri dierlerinden ayr tutmann yollarndan biri olan bir
deklaratif alan tanmlar. Aslnda, bir isim uzaynda deklare edilen isimler bir baka isim
uzaynda deklare edilen ayn isimlerle karmayacaktr. .NET Framework ktphanesi (yani,
C# ktphanesi) tarafndan kullanlan isim uzay Systemdr. Her programn bana yakn bir
yere aadaki satr dahil etmenizin nedeni budur;
using System;
Blm 14te grdnz gibi I/O snflar, Systemn bir alt isim uzay olan System.IO
iinde tanmlanmtr. C# ktphanesinin dier paralarn tutan ve Systemin altnda yer alan
daha birok isim uzay mevcuttur.
sim uzaylar nemlidir, nk son birka yl iinde deiken, metot, zellik ve snf
isimlerinde bir patlama olmutur. Ktphane rutinleri, nc parti kodlar ve kendi kodlarnz
da bu kapsamda yer almaktadr. sim uzaylar olmadan bu isimlerin tm global isim
uzayndaki boluklar iin yaracakt ve karklklar ortaya kacakt. rnein, eer
programnz Finder adnda bir snf tanmlam olsa; bu snf, sizin programnz kullanan
nc parti ktphane tarafndan salanan Finder adndaki bir baka snf ile akrd.
Neyse ki, isim uzaylar bu tr problemleri nlemektedir, nk bir isim uzay kendi iinde
deklare edilen isimlerin eriilebilirliini lokalize eder.
sim Uzayn Deklare Etmek
Bir isim uzay namespace anahtar kelimesi kullanlarak deklare edilir. namespacein
genel olarak ekli yledir:
namespace isim {
// yeler
}
Burada isim, isim uzaynn ismidir. Bir isim uzay iinde tanmlanan her ey, o isim
uzaynn kapsam iindedir. Bylece, bir isim uzay bir kapsam (scope) tanmlar. Bir isim uzay

HERKES N C#
KISIM I C# DL

458
iinde snf, yap, delege, numaralandrma, arayz ya da bir baka isim uzay deklare
edebilirsiniz.
te, Counter adnda bir isim uzay oluturan bir namespace rnei. Program, geriye
doru sayan CountDown adnda basit bir saya uygulamak iin kullanlan ismi lokalize eder.
// Sayaclar icin bir isim uzayi deklare et.

namespace Counter {
// Geriye dogru sayan basit bir sayac.
class ConntDown {
int val;

public CountDown(int n) {
val = n;
}

public void reset{int n) {
val = n;
}

public int count() {
if(val > 0) return val--;
else return 0;
}
}
}
Bu rnekte CountDown snf Counter isim uzay tarafndan tanmlanan kapsam iinde
deklare edilmektedir.
te Counter isim uzaynn kullanmn gsteren bir program:
Bir isim uzay goster.

using System;

// Sayaclar icin bir isim uzay deklare et.
namespace Counter {
// Geriye dogru sayan basit bir sayac.
class CountDown {
int val;

public CountDown(int n) { val = n; }

public void reset(int n) {
val = n;
}

public int count() {
if(val > 0) return val--;
else return 0;
}
}
BLM 16: SM UZAYLARI, N LEMC VE ASSEMBLYLER

HERKES N C#
459
}

class NSDemo {
public static void Main() {
Counter.CountDown cd1 = new Counter.CountDown(10);
int i;

do {
i = cd1.count();
Console.Write(i + );
} while(i > 0);
Console.WriteLine();

Counter.CountDown cd2 = new Counter.CountDown(20);

do {
i = cd2.count();
Console.Write(i + );
} while(i > 0);
Console.WriteLine();

cd2.reset(4);
do {
i = cd2.count();
Console.Write(i + );
} while(i > 0);
Console.WriteLine();
}
}
Programn kts aadaki gibidir:
10 9 8 7 6 5 4 3 2 1 0
20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
4 3 2 1 0
Bu programn yakndan incelemeye deer baz nemli yanlar mevcuttur. ncelikle,
CountDown, Counter isim uzaynda deklare edildii iin bir nesne oluturulurken
CountDown, aadaki gibi Counter ile birlikte nitelenmelidir:
Counter.CountDown cd1 = new Counter.CountDown(10);
Ancak, Counter tipinde bir nesne bir kez oluturulduktan sonra, artk bunu ya da bu
nesnenin herhangi bir yesini isim uzay ile birlikte nitelemek gerekli deildir. Bylece,
cd1.count() isim uzay niteleyicisi olmadan dorudan arlabilir; aadaki satrda
gsterildii gibi:
i = cd1.count();
sim Uzaylar sim Karklklarn nler
Bir isim uzay ile ilgili kilit neme sahip husus, bir isim uzay iinde deklare edilen
isimlerin isim uzay dnda deklare edilen ayn isimlerle karmayacak olmalardr. rnein,

HERKES N C#
KISIM I C# DL

460
aadaki programda CountDown adnda bir baka snf daha oluturulmaktadr; fakat bu snf
Counter2 adnda bir isim uzayndadr.
// Isim uzaylari isim karisikliklarini onler.

using System;

// Sayaclar icin bir isim uzayi deklare et.
namespace Counter {
// Seriye dogru sayan basit bir sayac.
class CountDown {
int val;

public CountDown(int n) {
val = n;
}

public void reset(int n) {
val = n;
}

public int count() {
if(val > 0} return val--;
else return 0;
}
}
}

// Bir baska isim uzayi deklare et.
namespace Counter2 {
/* Bu CountDown varsayilan isim uzayi icindedir ve
Counter icindekiyle karismaz. */
class CountDown {
public void count() {
Console.WriteLine(This is count() in the +
Counter2 namespace.);
}
}
}

class NSDemo {
public static void Main() {
// Bu, Counter isim uzayi icindeki CountDowndur.
Counter.CountDown cd1 = new Counter.CountDown(10);

// Bu, varsayilan isim uzayi icindeki CountDowndur.
Counters.Countdown cd2 = new Counter2.CountDown();

int i;

do {
i = cd1.count();
Console.Write(i + );
} while(i > 0);
Console.WriteLine();
BLM 16: SM UZAYLARI, N LEMC VE ASSEMBLYLER

HERKES N C#
461

cd2.count();
}
}
kt aada gsterilmitir:
10 9 8 7 6 5 4 3 2 1 0
This is count() in the Counter2 namespace.
ktnn da dorulad gibi, Counter iindeki CountDown snf, Counter2 isim
uzayndaki CountDown snfndan ayrdr ve hi isim karkl ortaya kmaz. Bu rnek
olduka basittir. Buna ramen, sizin yazdnz snflar bir isim uzay iine yerletirmenin sizin
kodunuz ve bakalar tarafndan yazlan kod arasndaki isim karklklarn nlemeye nasl
yardmc olduu bu rnekten kolaylkla grlmektedir.
using
Bolm 2de akland gibi, eer programnz bir isim uzaynn yelerine ska referansta
bulunuyorsa, bu yelere referansta bulunmanz gereken her seferde isim uzayn belirtmek zo-
runda olmanz hzla usandrc bir hal alr. using direktifi bu problemi hafifletir. Bu kitabn
bandan sonuna C# System isim uzayn programlarnza dahil etmek iin usingi
kullanmaktasnz, bu nedenle zaten buna ainasnz. Tahmin edebileceiniz gibi using, kendi
oluturduunuz isim uzaylarn programlarnza dahil etmek iin de kullanlabilir.
using direktifinin iki ekli mevcuttur. lki aada gsterilmitir;
using isim;
Burada isim, erimek istediiniz isim uzaynn adn belirtir. Bu, imdiye kadar grm
olduunuz using eklidir. Belirtilen isim uzay iinde tanmlanan yelerin tm programa
dahil edilir (yani, mevcut isim uzaynn bir paras olurlar) ve niteleyici olmadan da
kullanlabilirler. using direktifi, dier deklarasyonlardan nce, dosyalarn her birinin en
banda belirtilmelidir.
Aadaki program nceki blmdeki saya rneinin yeniden dzenlenmi versiyonudur
Bu program, kendi oluturduunuz bir isim uzayn programnza dahil etmek iin usingi
nasl kullanabileceinizi gstermektedir:
// Bir isim uzayi kullanimini gosterir.

using.System;

// Counteri programa dahil et.
using counter;

// Sayaclar icin bir isim uzayi deklare et.
namespace Counter {
// Geriye dogru sayan basit bir sayac.
class CountDown {

HERKES N C#
KISIM I C# DL

462
int val;

public CountDown(int n) {
val = n;
}

public void reset(int n) {
val = n;
}

public int count() {
if(val 0) return val--;
else return 0;
}
}
}

class NSDemo {
public static void Main() {
// simdi, CountDown dogrudan kullanilabilir.
CountDown cd1 = new CountDown(10);
int i;

do {
i = cd1.count();
Console.Write(i + );
}
while(i > 0);
Console.WriteLine();

CountDown cd2 = new CountDown(20);

do {
i = cd2.count();
Console.Write(i + );
}
while(i > 0);
Console.WriteLine();

cd2.reset(4);
do {
i = cd2.count();
Console.Write(i + );
}
while(i > 0);
Console.WriteLine();
}
}
Program, bir baka nemli hususu ortaya koymaktadr: Bir isim uzayn kullanmak bir
bakasn devre d brakmaz. Bir isim uzayn programnza dahil ettiinizde, bu isim uzay
yalnzca kendisindeki isimleri halihazrda kullanmda olan dier isim uzaylarna ekler. Bylece,
hem System hem de Counter programa dahil edilmitir.
BLM 16: SM UZAYLARI, N LEMC VE ASSEMBLYLER

HERKES N C#
463
usingin kinci Kullanm ekli
using direktifinin aada gsterildii gibi ikinci bir ekli daha mevcuttur:
using takma-isim = isim;
Burada takma-isim, isim ile belirtilen snf ya da isim uzay iin bir baka isim halini
alr. Saya program Counter.CountDown iin Count adnda bir takma isim (alias)
oluturulacak biimde bir kez daha yeniden dzenlenmitir.
// using icin takma isim kullanimini gosterir.

using System;

// Counter.CountDown icin bir takma isim olustur.
using Count = Counter.CountDown;

// Sayaclar icin bir isim uzayi deklare et.
namespace Counter {
// Geriye dogru sayan basit bir sayac.
class CountDown {
int val;

public CountDown(int n) {
val = n;
}

public void reset(int n) {
val = n;
}

public int count() {
if(val > 0) return val--;
else return 0;
}
}
}

class NSDemo {
public static void Main() {
/* Burada Count, Counter.CountDownun
ismi olarak kullaniliyor. */
Count cd1 = new Count(10);
int i;

do {
i = cd1.count();
Console.Write(i + );
} while(i > 0);
Console.WriteLine();

Count cd2 = new Count(20);

do {

HERKES N C#
KISIM I C# DL

464
i = cd2.count();
Console.Write(i + );
} while(i > 0);
Console.WriteLine();

cd2.reset(4);
do {
i = cd2.count();
Console.Write(i + );
} while(i > 0);
Console.WriteLine{);
}
}
Count bir kez Counter.CountDown iin bir isim olarak belirtildikten sonra artk baka
isim uzay niteleyicileri kullanmadan nesneleri deklare etmek iin kullanlabilir. rnein, prog-
ramda aadaki satr bir CountDown nesnesi oluturur.
Count cd1 = new Count(10);
sim Uzaylar Eklenebilir
Ayn isimde birden fazla isim uzay deklarasyonu mevcut olabilir. Bu durum, bir isim
uzaynn birka dosya arasnda blnmesine, hatta ayn dosya iinde ayrlmasna imkan verir.
rnein, aadaki programda iki tane Counter isim uzay tanmlanmaktadr. Bunlardan biri
CountDown snfn iermektedir. Dieri ise CountUp snfn iermektedir. Program
derlendiinde her iki Counter isim uzaynn ierikleri birbirine eklenir.
// Isim uzaylari eklenebilir.

using System;

// Counteri programa dahil et.
using Counter;

// Iste Counter isim uzayindan biri.
namespace Counter {
// Geriye dogru sayan basit bir sayac.
class CountDown {
int val;

public CountDown(int n) {
val = n;
}

public void reset(int n) {
val = n;
}

public int count() {
if(val > 0) return val-- ;
else return 0;
}
BLM 16: SM UZAYLARI, N LEMC VE ASSEMBLYLER

HERKES N C#
465
}
}

// Iste bir baska Counter isim uzayi.
namespace Counter {
// Ileriye dogru sayan basit bir sayac.
class CountUp {
int val;
int target;

public int Target {
get{
return target;
}
}

public CountUp(int n) {
target = n;
val = 0;
}

public void reset(int n) {
target = n;
val = 0;
}

public int count() {
if(val < target) return val++;
else return target;
}
}
}

class NSDemo {
public static void Main() {
CountDown cd = new CountDown(10);
CountUp cu = new CountUp(8);
int i;

do {
i = cd.count();
Console.Write(i + );
} while(i > 0);
Console.WriteLine();

do {
i = cu.count();
Console.Write(i + );
} while(i < cu.Target);
}
}
Bu program aadaki kty retir:
10 9 8 7 6 5 4 3 2 1 0

HERKES N C#
KISIM I C# DL

466
0 1 2 3 4 5 6 7 8
Bir baka eye dikkat edin: u ifade
using Counter;
Counter isim uzaynn btn ieriini programa dahil etmektedir. Bylece, hem
CountDown hem de CountUp isim uzay niteleyicileri olmakszn dorudan referansta
bulunulabilirler. Counter isim uzaynn iki paraya ayrlm olmas nemli deildir.
sim Uzaylar Kmelenebilir
Bir isim uzay bir dierinin iine yerletirilebilir. u program ele aln:
// Isim uzaylari kumelenebilir.

using System;

namespace NS1 {
class ClassA {
public ClassA() {
Console.WriteLine(constructing ClassA);
}
}

namespace NS2 { // kumenmis bir isim uzayi
class ClassB {
public ClassB() {
Console.WriteLine(constructing ClassB);
}
}
}
}

class NestedNSDemo {
public static void Main() {
NS1.ClassA a = new NS1.ClassA();

// NS2.ClassB b = new NS2.ClassB(); //Hata!!! NS2 gorunurde degil

NS1.NS2.ClassB b = new NS1.NS2.ClassB(); // bu dogrudur
}
}
Bu program aadaki kty retir:
constructing ClassA
constructing ClassB
Programda NS2 isim uzay NS1 iine kmelenmitir. Bylece, ClassBye referansta
bulunmak iin bunu hem NS1 hem de NS2 isim uzaylar ile birlikte nitelemelisiniz. NS2 tek
bana yeterli deildir. Grld gibi, isim uzaylar nokta ile birbirinden ayrlmlardr.
BLM 16: SM UZAYLARI, N LEMC VE ASSEMBLYLER

HERKES N C#
467
Kmelenmi bir isim uzayn, her isim uzayn nokta ile birbirinden ayrarak tek bir isim
uzay ifadesi iinde belirtebilirsiniz. rnein, u ifade
namespace OuterNS {
namespace InnerNS {
// ...
}
}
u ekilde de belirtilebilir:
namespace OuterNS.InnerNS {
// ...
}
Varsaylan sim Uzay
Programnz iin bir isim uzay deklare etmezseniz varsaylan isim uzay kullanlr. nceki
blmlerde yer alan programlarda namespace kullanmanza gerek olmam olmas bu
nedenledir. Bu kitaptaki ksa, rnek programlarda varsaylan isim uzay kullanl olmakla
birlikle gerek dnyaya ait uygulamalarn birounda kod, birisim uzayn iinde yer alacaktr.
Kodunuzu bir isim uzay iine paketlemenin balca nedeni isim karklklarn nlemektir.
sim uzaylar, programlarnz organize etmeniz ve gnmzn karmak, ala donatlm
ortamnda varlklarn srdrebilmelerini salamanz iin size yardmc olan aralardan bir
dieridir.
nilemci
C#ta programnzn kaynak dosyasnn derleyici tarafndan derlenme biimini etkileyen
birka nilemci direktifi (preprocessor directive) tanmlanmaktadr. Bu direktifler, iinde
bulunduklar kaynak dosyann metnini program nesne koduna evrilmeden nce etkilerler.
nilemci direktiflerinin byk blm C++tan alnmtr. Aslnda, C# nilemcisi C++
tarafndan tanmlanana ok benzer. nilemci komutlar geleneksel olarak nilemci olarak
adlandrlan ayr bir derleme evresinde ele alnrd. nilemci direktifi terimi bu gerekten
gelmektedir. Gnmzn modern derleyici teknolojisi direktifleri ele almak iin artk ayr bir
nilemci evresi gerektirmez; ancak, isim bak kalmtr.
C#ta aadaki nilemci direktifleri tanmldr:
#define #elif #else #endif
#endregion #error #if #line
#region #undef #warning
Tm nilemci direktifleri # simgesi ile balar. laveten, her nilemci direktifi kendi sat-
rnda yer almaldr.
Akas, C#n modern, nesne ynelimli mimarisi yannda nilemci direktiflerine daha
eski dillerdekine kyasla pek fazla gerek yoktur. Bununla birlikte, zellikle koullu

HERKES N C#
KISIM I C# DL

468
derlemelerde olmak zere nilemci direktifleri zaman zaman nemli olabilmektedirler. Bu
blmde her direktif srayla incelenmektedir.
#define
#define direktifi, sembol olarak adlandrlan bir karakter sekans tanmlar. Bir semboln
varl ya da eksiklii #if ya da #elif ile belirlenir ve derlemeyi kontrol etmek amacyla
kullanlr. #define genel olarak u ekildedir:
#define sembol
Bu ifadede noktal virgl kullanlmadna dikkat edin. #define ve sembol arasnda her-
hangi sayda boluk olabilir; fakat, sembol bir kez baladktan sonra yalnzca yeni satr karak-
teri ile sona erer rnein, EXPERIMENTAL semboln tanmlamak iin u direktifi kullann:
#define EXPERIMENTAL
NOT

C/C++ta metinleri birbiri yerine yerletirmek iin #define kullanabilirsiniz.
rnein, bir deer iin bir isim tanmlamak ya da fonksiyon benzeri makrolar
oluturmak gibi. C#, #definen bu tr kullanmlarn desteklemez. C#ta #define
yalnzca bir sembol tanmlamak iin kullanlr.
#if ve #endif
#if ve #endif direktifleri, bir veya daha fazla sembol ieren bir deyimin true deerine
sahip olup olmamasna bal olarak bir kod sekansnn koullu derlenmesini mmkn klarlar.
Bir sembol eer tanmlanmsa true deerine sahiptir. Aksi halde semboln deeri yanltr.
Bu nedenle, eer bir sembol #define direktifi ile tanmlanmsa bu semboln deeri doru
olacaktr.
#if genel olarak u ekildedir:
#if sembol-deyimi
ifade sekans
#endif
#ifi takip eden deyim doru deerindeyse #if ile #endif arasnda kalan kod derlenir.
Aksi halde, arada kalan kod atlanr. #endif direktifi #if blounun sonunu iaret eder.
Sembol deyimi yalnzca bir sembol isminden ibaret olacak kadar basit olabilir. Bir sembol
deyiminde u operatrleri de kullanabilirsiniz: !, ==, !=, && ve ||. Parantezlere de ayrca izin
verilir.
te #if, #endif ve #define kullanan bir rnek:
// #if, #endif ve #define kullanimini gosterir.

#define EXPERIMENTAL
BLM 16: SM UZAYLARI, N LEMC VE ASSEMBLYLER

HERKES N C#
469

using System;

class Test {
public static void Main() {

#if EXPERIMENTAL
Console.WriteLine(Compiled for experimental version.);
#endif

Console.WriteLinet(This is in all versions.);
}
}
Bu program aadaki kty grntler:
Compiled for experimental version.
This is in all versions.
Programda EXPERIMENTAL sembol tanmlanmaktadr. Bylece, #if ile karlanca
sembol deyiminin deeri doru olur ve ilk WriteLine() ifadesi derlenir.
EXPERIMENTAL tanmn kaldrp program yeniden derlerseniz, ilk WriteLine() ifadesi
derlenmeyecektir, nk #if, false deerine sahip olacaktr. kinci WriteLine() ifadesi
her durumda derlenir, nk bu ifade #if blounun bir paras deildir.
nceden akland gibi, #if iinde bir sembol deyimi kullanabilirsiniz. rnein:
// Bir sembol deyimi kullanir.

#define EXPERIMENTAL
#define TRIAL

using System;

class Test {
public static void Main() {

#if EXPERIMENTAL
Console.WriteLine(compiled for experimental version.);
#endif

#if EXPERIMENTAL && TRIAL
Console.Error.WriteLine(Testing experimental
trial version.);
#endif

Console.WriteLine(This is in all versions.);
}
}
Bu programn kts aada gsterilmitir:
Compiled for experimental version.

HERKES N C#
KISIM I C# DL

470
Testing experimental trial version.
This is in all versions.
Bu rnekte iki sembol tamlanmaktadr: EXPERIMENTAL ve TRIAL. kinci WriteLine()
ifadesi sadece bu sembollerin her ikisi de tanmlanrsa derlenmektedir.
#else ve #elif
#else direktifi C# dilinin bir paras olan elsee ok benzer ekilde almaktadr: #if
baarsz olursa ona bir alternatif oluturur. nceki rnek aada gsterildii gibi
geniletilebilir:
// #else kullanimini gosterir.

#define EXPERIMENTAL

using System;

class Test {
public static void Main() {

#if EXPERIMENTAL
Console.WriteLine(Compiled for experimental version.);
#else
Console.WriteLine(Compiled for release.);
#endif

#if EXPERIMENTAL && TRIAL
Console.Error.WriteLine(Testing experimental
trial version.);
#else
Console.Error.WriteLine(Not experimental
trial version.);
#endif

Console.WriteLine(This is in all versions.);
}
}
kt aada gsterilmitir:
Compiled for experimental version.
Not experimental trial version.
Tnis is in all versions.
TRIAL artk tanml olmad iin ikinci koul kod sekansnn #else blm
kullanlmaktadr.
Dikkat ederseniz, #else hem #if blounun sonunu hem de #else blounun ban iaret
etmektedir, Bu gereklidir, nk herhangi bir #if ile ilikilendirilmi yalnzca tek bir #endif
olabilir.
BLM 16: SM UZAYLARI, N LEMC VE ASSEMBLYLER

HERKES N C#
471
#elif direktifi else if anlamna gelir ve birden fazla derleme seenei iin bir if-
else-if zinciri kurar. #elifin ardndan bir sembol deyimi gelir. Deyim doru deerine
sahipse, karlk gelen kod blou derlenir ve dier #elif deyimlerinden hibiri test edilmez.
Aksi halde, seri iindeki bir sonraki blok kontrol edilir. #elif genel olarak u ekildedir:
#if sembol-deyimi
ifade sekans
#elif sembol-deyimi
ifade sekansi
#elif sembol-deyimi
ifade sekans
#elif sembol-deyimi
ifade sekans
#elif sembol-deyimi
.
.
.
#endif
rnein:
// #elif kullanimini gosterir.

#define RELEASE

using System;

class Test {
public static void Main() {

#if EXPERIMENTAL
Console.WriteLine(Compiled for experimental version.);
#elif RELEASE
Console.WriteLine(Compiled for release.);
#else
Console.WriteLine(Compiled for internal testing.);
#endif

#if TRIAL && !RELEASE
Console.WriteLine(Trial version.);
#endif

Console.WriteLine(This is in all versions.);
}
}
kt aada gsterilmitir:
Compiled for release.
This is in all versions.


HERKES N C#
KISIM I C# DL

472
#undef
#undef direktifi, kendisini takip eden semboln nceden tanmlanm tanmn ortadan
kaldrr. Yani, bir sembol tanmszlatrr (undefine). #undef direktifi genel olarak u
ekildedir:
#undef sembol
te bir rnek:
#define SMALL

#if SMALL
// ...
#undef SMALL
// bu noktada SMALL tanmszdr.
#undef direktifinden sonra SMALL artk tanml deildir.
#undef esasen, sembollerin yalnzca kendilerine gerek duyan kod blmleriyle
snrlandrlmalarna olanak tanmak iin kullanlr.
#error
#error direktifi derleyiciyi derlemeyi brakmas iin zorlar. Bu direktif hata ayklama
ilemi iin kullanlr. #error direktifi genel olarak u ekildedir:
#error hata-mesaj
#error direktifi ile karlanca hata mesaj ekranda grntlenir. rnein, derleyici
aadaki satra rastlaynca derleme ilemi durdurulur ve This is test error! hata mesaj
ekranda grntlenir.
#error This is a test error!
#warning
#warning direktifi #errorla ayndr. Tek fark, #warning ile bir hata yerine bir uyar
retilmesidir. Bylece, derleme ilemi durdurulmaz. #warning direktifi genel olarak u
ekildedir:
#warning uyar-mesaj
#line
#line direktifi, bu direktifi ieren dosya iin satr numarasn ve dosya ismini ayarlar.
Satr numaras ve dosya ismi derleme srasnda hatalarn ya da uyarlarn kts iin kullanlr.
#line genel olarak u ekildedir:
BLM 16: SM UZAYLARI, N LEMC VE ASSEMBLYLER

HERKES N C#
473
#line say dosyaad
Burada say herhangi pozitif tamsaydr. Bu ifadeyle yeni satr numaras artk say olur.
dosyaad istee baldr ve geerli herhangi bir dosya tanmlaycs, dosyaad olarak
kullanlabilir; bu ifadeyle dosyaad da artk yeni dosya ad olacaktr. #linen balca
kullanm alanlar hata ayklama ilemi ve zel uygulamalardr.
Satr numaralama ilemini orijinal haline dndrmek iin default kelimesini aada
gsterildii gibi belirtin:
#line default
#region ve #endregion
#region ve #endregion direktifleri, Visual Studio IDE iinde ana hat grnm
kullanlrken geniletilecek ya da daraltlacak bir alan tanmlamanza olanak tanr. Genel olarak
nasl kullanlacaklar aada gsterilmitir:
#region alan-ad
// kod sekans
#endregion
Burada alan-ad, sz konusu alann ismidir.
Assemblyler ve internal Eriim Niteleyicisi
C#n nemli bir paras assemblydir. Assembly, bir program iin tm kurulum ve
versiyon bilgilerini ieren bir dosyadr (ya da dosyalardr). Assemblyler .NET ortam iin
temel niteliindedirler. Microsofttan alnt yaparsak, Assemblyler, .NET Frameworkn
temel talardr. Assemblyler; gvenli bileen etkileimini, diller aras uyumluluu ve yeni
versiyonlarn gelitirilmesini destekleyen mekanizmalardr. Bir assembly ayn zamanda bir
kapsam (scope) da tanmlar.
Bir assembly drt blmden meydana gelir. Bunlardan ilki, assembly manifestosudur
(manifest). Manifesto, assemblynin kendisiyle ilgili bilgi ierir. Bu veriler arasnda
assemblynin ismi, versiyon numaras, tip eleme bilgileri ve kltrel ayarlamalar gibi bilgiler
yer almaktadr. kinci blm, program tarafndan kullanlan veri tipleriyle ilgili bilgileri ieren
tip metadatasdr. Dier avantajlarnn yan sra tip metadatas diller aras uyuma yardmc ol-
maktadr. Assemblynin nc blm Microsoft Intermediate Language (MSIL) biiminde
saklanan program kodudur. Assernblynin drdnc bileeni ise program tarafndan kullanlan
kaynaklardr.
Neyse ki, C# kullanrken assemblyler sizin ok az bir gayretinizle ya da ek bir aba
harcamanza gerek kalmadan otomatik olarak retilirler. Bunun nedeni udur: Bir C# program
derlediinizde oluturulan exe dosyas, aslnda dier tr bilgilerin yan sra programnzn
altrlabilir kodunu ieren bir assemblydir. Bylece, bir C# programn derlediinizde bir as-
sembly otomatik olarak retilir.

HERKES N C#
KISIM I C# DL

474
Assemblylerle ilgili daha birok zellik ve konu mevcuttur; ancak bunlar, elinizdeki
kitabn kapsam dndadr. (Assemblyler .NET gelitirme srecinin nemli bir parasdr,
fakat C# dilinin teknik bir zellii deildirler.) Bununla birlikte, C#n assemblylerle dorudan
balantl bir paras mevcuttur: internal eriim niteleyicisi. Bu, aada incelenmektedir.
internal Eriim Niteleyicisi
Bu kitabn bandan beri kullanmakta olduunuz public, private ve protected eriim
niteleyicilerine ek olarak C#ta ayrca internal da tanmldr. internal niteleyicisi, bir
yenin bir assembly iindeki tm dosyalar tarafmdan bilindiini ancak assembly dnda
tannmadn bildirir. Bylece, daha basit bir ifadeyle, internal olarak iaretlenmi bir ye
program boyunca bilinir, fakat bunun haricinde bilinmez. internal eriim niteleyicisi
zellikle yazlm bileenleri olutururken ie yarar.
internal niteleyicisi snflara, snf yelerine, yaplara ve yap yelerine uygulanabilir.
internal niteleyicisi arayz ve numaralandrma deklarasyonlarna da uygulanabilir.
protected internal eriim niteleyicisi ifti oluturmak amacyla protected
internal ile birlikte kullanabilirsiniz. protected internal eriim dzeyi yalnzca snf
yelerine verilebilir. protected internal eriim izni verilerek deklare edilen bir ye kendi
assemblysi iinden ya da tretilmi tiplerden eriilebilir.
te, internal kullanlan bir rnek:
// internal kullanir.

using System;

class InternalTest {
internal int x;
}

class InternalDemo {
public static void Main() {
InternalTest ob = new InternalTest();

ob.x = 10; // erisebilir - ayni dosyadalar

Console.WriteLine(Here is ob.x: + ob.x);
}
}
InternalTest iinde x alan internal olarak deklare edilmektedir. Bunun anlam
udur: x program iinden eriilebilir. xin InternalDemo iindeki kullanm da bunu
gstermektedir. Fakat, x program dndan eriime ak deildir.



O N Y E D N C B L M


ALIMA ZAMANI TP
TANIMLAMASI,
YANSIMA VE
NTELKLER


















17

HERKES N C#
KISIM I C# DL

476
Bu blmde birbiriyle balantl ve gl C# zellii ele alnmaktadr: alma zaman
tip tanmlamas, yansma ve nitelikler. alma zaman tip tanmlamas (RTTI -Runtime Type
ID) bir programn almas srasnda bir tipin tannmasna imkan veren bir mekanizmadr.
Yansma (reflection), bir tip hakknda bilgi edinmenizi mmkn klan bir zelliktir. Bu bilgiyi
kullanarak programn almas srasnda nesneler yaplandrp, bu nesneleri kullanabilirsiniz
Bu zellik ok gldr, nk bir programa programn almas srasnda dinamik olarak
ilevsellik ekleme imkan verir. Nitelik (attribute) bir C# programnn herhangi bir elemannn
bir zelliini tarif eder. rnein, dier elerin yan sra snflar, metotlar ve alanlar iin
nitelikler belirtebilirsiniz. Nitelikler programn almas srasnda sorgulanabilir ve nitelik
bilgisi elde edilebilir. Nitelikler hem alma zaman tip tanmlamasn, hem de yansmay
kullanrlar.
alma Zaman Tip Tanmlamas
alna zaman tip tanmlamas (RTTl - Runtime Type Identification), bir nesnenin tipinin
programn almas srasnda belirlenmesine imkan verir, RTTIn kullanl olmasnn birok
nedeni vardr. rnein, bir temel smf referansnn ne tr bir nesneye referansta bulunmakta,
olduunu bu sayede tam olarak kefedebilirsiniz. RTTIn bir baka kullanm, geersiz tip
atamalaryla ilgili kural d bir duruma sebebiyet vermemek iin, bir tip atamasnn baarl
olup olmayacan nceden test etmektir. alma zaman tip tanmlamas ayrca, yansmann
temel bir bileenidir.
C#, alma zaman tip tanmlamasn destekleyen anahtar kelime iermektedir: is, as
ve typeof. Bunlarn her biri srayla incelenmektedir.
Bir Tipi is le Test Etmek
is operatrn kullanarak bir nesnenin belirli bir tipte olup olmadn belirleyebilirsiniz.
is operatrnn genel olarak kullanm aada gsterilmitir:
deyim is tip
Burada deyim, tipi tip ile karlatrlmakta olan bir deyimdir. Eer deyimin tipi tip ile
ayn ya da uyumlu ise, bu ilemin sonucu true deerine sahiptir. Aksi halde, sonu false
olur. Bylece, eer sonu true deerindeyse, deyim tip atamas yoluyla tipe
dntrlebilir.
te, is kullanlan bir rnek:
// is kullanimi gosterir.

using System;

class A {}
class B : A {}

class UseIs {
BLM 17: ALIMA ZAMANI TP TANIMLAMASI, YANSIMA VE NTELKLER

HERKES N C#
477
public static void Main() {
A a = new A();
B b = new B();

if(a is A) Console.WriteLine(a is an A);
if(b is A)
Console.WriteLine(b is an A because
it is derived from A);
if(a is B)
Console.WriteLine(This wont display -- a not
derived from B);

if(b is B) Console.WriteLine(B is a B);
if(a is object) Console.WriteLine(a is an Object);
}
}
kt aada gsterilmitir:
a is an A
b is an A because it is derived from A
B is a B
a is an Object
is deyimlerinin birou kendiliinden anlalr durumdadr, ama bunlardan ikisi biraz
aklama gerektirebilir. ncelikle, u ifadeye dikkat edin:
if(b is a)
Console.WriteLine(b is an A because it is derived from A);
if ifadesi baarl olur, nk b, B tipinde bir referanstr. B ise A tipinden tretilmitir.
Bylece b, A ile uyumludur. Ancak, bunun tersi doru deildir. u ifade gereklendiinde,
if(a is B)
Console.WriteLine(This wont display -- a not derived from B);
if baarl olmaz, nk a, A tipindedir; fakat A, Bden tretilmemitir. Bu nedenle, her
ikisi uyumlu deildir.
as Kullanm
Kimi zaman programn almas srasnda bir tip atamas denemek isteyeceksiniz. yle ki,
tip atamas baarsz olursa bir kural d durum ortaya kmamasn isteyeceksiniz. Bunu
gerekletirmek iin as operatrn kullann. Bu operatr genel olarak u sekilde kullanlr:
deyim as tip
Burada deyim, tipe dntrlmekte olan deyimdir. Tip atamas baarl olursa, tipe
atfta bulunan bir referans dndrlr. Aksi halde, bir null referans dndrlr.
as operatr baz durumlarda ise standart bir alternatif oluturur. rnein, geersiz bir
tip atamasnn meydana gelmesini nlemek iin is kullanan aadaki program ele aln:

HERKES N C#
KISIM I C# DL

478
// Gecersiz bir tip atamasini onlemek icin is kullanir.

using System;

class A {}
class B : A {}

class CheckCast {
public static void Main() {
A a = new A();
B b = new B();

/* anin tip atamasi yoluyla Bye donusturulup
donusturulemeyecegini anlamak icin kontrol et. */
if(a is B) // eger oyleyse, tip atamasini uygula
b = (B) a;
else // degilse, tip atamasini atla
b = null;

if(b == null)
Console.WriteLine(Cast b = (B) a is NOT allowed.);
else
Console.WriteLine(Cast b = (B) a is allowed);
}
}
Bu program aadaki kty ekranda grntler:
Cast b = (B) a is NOT allowed.
ktdan da grlecei gibi; a, B tipinde olmad iin ann tip atamas yoluyla Bye
dntrlmesi geerli deildir; if ifadesi tarafndan bu durum engellenir. Ancak, bu yntem
iki aama gerektirir. Birincisi, tip atamasnn geerlilii dorulanmahdr. kincisi, tip atamas
gereklenmelidir. Bu aamalar, aadaki programda gsterildii gibi, as kullanlarak tek bir
admda toplanabilir:
// as kullanimini gsterir.

using System;

class A {}
class B : A {}

class CheckCast {
public static void Main() {
A a = new A();
B b = new B();

b = a as B; // tip atamasini gerceklestir, eger mumkunse

if(b == null)
Console.WriteLine(Cast b = (B) a is NOT allowed.);
else
Console.WriteLine(Cast b = (B) a is allowed);
BLM 17: ALIMA ZAMANI TP TANIMLAMASI, YANSIMA VE NTELKLER

HERKES N C#
479
}
}
Daha nceki kt ile ayn olan kt aadaki gibidir:
Cast b = (B) a is NOT allowed.
Programn bu versiyonunda as ifadesi, tip atamasnn geerliliini kontrol eder; eer
geerliyse, tek bir ifade iinde tip atamasn gerekletirir.
typeof Kullanm
as ve is operatrleri kendilerine gre kullanl olmalarna ramen yalnzca iki tipin
uyumluluunu test ederler. Genellikle, bir tip hakknda bilgi elde etmeniz gerekecektir. Bunun
iin C# typeof operatrn salamaktadr. typeof, belirli bir tip iin bir System.Type
nesnesi edinir. Bu nesneyi kullanarak sz konusu tipin zelliklerini belirleyebilirsiniz.
typeof operatrnn genel olarak kullanm u ekildedir:
typeof(tip)
Burada tip, elde edilmekte olan tiptir. Dndrlen Type nesnesi, tip ile ilikilendirilmi
bilgiyi paketler.
Belirli bir tip iin bir kez bir Type nesnesi elde ettikten sonra artk Type tarafndan
tanmlanan eitli zellik, alan ve metotlar kullanarak sz konusu tip hakknda bilgi elde
edebilirsiniz. Type, birok yesi olan byk bir snftr ve bu konuyla ilgili aklamalar
yansmann incelendii bir sonraki blme kadar ertelenmitir. Yine de, Type ksaca tantmak
iin aadaki program, onun zelliini kullanmaktadr: FullName, IsClass ve
IsAbstract. .Sz konusu tipin tam ismini elde etmek iin FullName kullann. Eer sz
konusu tip bir snf ise IsClass doru deerini dndrr. IsAbstract ise eer bir snf zet
ise doru deeri dndrr.
// typeof kullanimini gosterir.

using System;
using System.IO;

class UseTypeof {
public static void Main() {
Type t = typeof(StreamReader);

Console.WriteLine(t.FullName);

if(t.IsClass) Console.WriteLine(Is a class.);
if(t.IsAbstract) Console.WriteLine(Is abstract.);
else Console.WriteLine(Is concrete.);
}
}
Bu program aadaki kty retir:

HERKES N C#
KISIM I C# DL

480
System.IO.StreamReader
Is a class.
Is concrete.
Bu program, StreamReader tarif eden bir Type nesnesi elde eder. Program daha sonra
sz konusu tipin tam ismini ekranda grntler ve bunun bir snf olup olmadn ve zet olup
olmadn belirler.
Yansma
Bu blmn banda bahsedildii gibi yansma (reflection), bir tip hakknda bilgi
edinmenizi mmkn klan bir C# zelliidir. Yansma terimi sz konusu srecin ileyi
eklinden gelmektedir: Bir Type nesnesi simgeledii tipin aynadaki grnts gibidir. Bilgi
elde etmek iin Type nesnesine sorular sorarsnz ve Type nesnesi de tiple ile ilikili bilgileri
size geri dndrr (yanstr). Yansma gl bir mekanizmadr, nk yansma, tiplerin
yalnzca programn almas srasnda bilinen becerilerini renmenize ve kullanmanza
olanak tanr.
Yansmay destekleyen snflarn birou System.Reflection isirn uzaynda yer alan
.NET Reflection APIn bir parasdr. Bu nedenle yansma kullanlan programlarda aadaki
satr normal olarak programnza dahil edeceksiniz:
using System.Reflection;
Yansmann ekirdei: System.Type
System.Type yansma alt sisteminin ekirdeinde yer alr, nk System.Type ile tip
paketlenmektedir. System.Type, programn almas srasnda bir tip hakknda bilgi elde
etmek iin kullanacanz zellikleri ve metotlar ierir. Type,
System.Reflection.MemberInfo adnda bir zet snftan tretilmitir.
MemberInfo aadaki zet, salt okunur zellikleri tanmlamaktadr:
Type DeclaringType yenin deklare edildii snf veya arayzn tipi.
MemberTypes MemberType yenin tipi.
string Name Tipin ismi.
Type ReflectedType Yanstlmakta olan nesnenin tipi.

MemberTypen tipinin MemberTypes olduuna dikkat edin. MemberTypes, eitli ye
tipleri iin deerler tanmlayan bir numaralandrmadr. MemberTypes iinde yer alan
deerlerin bir ksm unlardr:
MemberTypes.Constructor
MemberTypes.Method
MetberTypes.Field
MemberTypes.Event
MemterTypes. Property
BLM 17: ALIMA ZAMANI TP TANIMLAMASI, YANSIMA VE NTELKLER

HERKES N C#
481
Bylece, bir yenin tipi MemberType kontrol edilerek belirlenebilir. rnein,
MemberType eer MemberTypes.Methoda eitse sz konusu ye bir metottur.
MemberInfo iki zet metot iermektedir: GetCustomAttributes() ve IsDefined().
Bunlarn her ikisi de niteliklerle balantldr.
MemberInfo tarafndan tanmlanan metot ve zelliklere Type da kendinden daha pek ok
ilave etmektedir. rnein, ite Type tarafndan tanmlanm ska kullanlan metotlardan bir
ka:
Metot Ama
ConstructorInfo[] GetConstructors() Belirtilen tip iin yaplandrclarn bir listesini elde
eder.
EventInfo[] GetEvents() Belirtilen tip iin olaylarn listesini elde eder.
FieldInfo[] GetFields() Belirtilen tip iin alanlarn listesini elde eder.
MemberInfo[] GetMembers() Belirtilen tip iin yelerin listesini elde eder.
MethodInfo[] GetMethods() Belirtilen tip iin metotlarn listesini elde eder.
PropertyInfo[] GetProperties() Belirtilen tip iin zelliklerin listesini elde eder.
te, Type tarafndan tanmlanm ska kullanlan salt okunur zelliklerden birka:
zellik Ama
Assembly Assembly Belirtilen tip iin bir assembly elde eder.
TypeAttributes Attributes Belirtilen tip iin nitelikleri elde eder.
Type BaseType Belirtilen tip iin en yakn temel tipi elde eder.
string FullName Belirtilen tipin tam ismini elde eder.
bool IsAbstract
Belirtilen tip zet ise truedur.
bool isArray
Belirtilen tip bir dizi ise truedur.
bool IsClass
Belirtilen tip bir snf ise truedur.
bool IsEnum
Belirtilen tip bir numaralandrma ise truedur.
string Namespace Belirtilen tip iin isim uzayn elde eder.
Yansmann Kullanm
Typeta tanml metotlar ve zellikleri kullanarak programn almas srasnda bir tip
hakknda ayrntl bilgi edinmek mmkndr. Bu son derece gl bir zelliktir, nk bir tip
hakkndaki bilgileri bir kez elde ettikten sonra, artk sz konusu tipin yaplandrclarn etkin
klabilir, metotlarn arabilir ve zelliklerini kullanabilirsiniz. Bylece, derleme srasnda
elverili olmayan kodu yansma sayesinde kullanmanz mmkn olur.

HERKES N C#
KISIM I C# DL

482
Reflection API olduka byktr; konunun tamamn burada ele almak mmkn deildir.
(Yansmay tam olarak ele almak kolaylkla bu kitabn tamamn doldurabilir!) Ancak,
Reflection API mantksal olarak tasarland iin bunun bir blmnn nasl kullanldn bir
kez anladktan sonra, gerisi ardndan gelir. Bu dnceden hareketle, aadaki ksmlarda
byk neme sahip drt yansma teknii gslerilmektedir: Metotlar hakknda bilgi edinmek,
metotlar armak, nesneleri kurmak ve assemblylerden tipleri yklemek.
Metotlar Hakknda Bilgi Edinmek
Elinizde bir kez bir Type nesnesi olduktan sonra sz konusu tip tarafndan desteklenen
metotlarn listesini GetMethods() kullanarak elde edebilirsiniz. Bunun bir ekli aada
gsterilmitir:
MethodInfo[] GetMethods()
Bu ifade MethodInfo nesnelerinden oluan bir dizi dndrr. MethodInfo nesneleri,
aran tipin destekledii metotlar tarif eder. MethodInfo, System.Reflection isim uzay
iindedir.
MethodInfo, MethodBase zet snfndan tretilmitir. MethodBase ise
MemberInfodan kaltm yoluyla elde edilir. Bylece, bu snfn tm tarafndan
tanmlanan zellikler ve metotlar sizin kullanmnza hazrdr. rnein, bir metodun ismini elde
etmek iin Name zelliini kullann. Bu aamada zellikle enteresan olan iki ye ReturnType
ve GetParameters()dr.
Bir metodun dn tipi Type tipinde bir nesne olan ReturnType zelliinde mevcuttur.
GetParameters() metodu, bir metotla ilikili olan parametrelerin listesini dndrr.
Genel olarak bu metot u ekildedir:
ParameterInfo[] GetParameters()
Parametre bilgileri ParameterInfo nesnesinde tutulur. ParameterInfo, sz konusu
parametreyi tarif eden ok sayda zellik ve metot tanmlanmaktadr. zellikle deeri olan iki
zellik Name ve ParameterTypedr. Name, sz konusu parametrenin adn ieren bir karakter
katardr. ParameterType ise parametrenin tipini tarif eder. Parametrenin tipi bir Type
nesnesi iinde paketlenir.
Aada, MyClass adnda bir snf tarafndan desteklenen metotlar elde etmek amacyla
yansma kullanan bir program yer almaktadr. Program, her metot iin dn tipini, metodun
adn; metotlarn her birinin sahip olabilecei parametrelerin isimlerini ve tiplerini ekranda g-
rntler.
// Yansima kullanarak metotlari analiz etmek.

using System;
using System.Reflection;

BLM 17: ALIMA ZAMANI TP TANIMLAMASI, YANSIMA VE NTELKLER

HERKES N C#
483
class MyClass {
int x;
int y;

public MyClass(int i, int j) {
x = i;
y = j;
}

public int sum() {
return x + y;
}

public bool isBetween(int i) {
if(x < i && i < y) return true;
else return false;
}

public void set(int a, int b) {
x = a;
y = b;
}

public void set(double a, double b) {
x = (int) a;
y = (int) b;
}

public void show() {
Console.WriteLine( x: {0}, y: {1}, x, y);
}
}

class ReflectDemo {
public static void Main() {
Type t = typeof(MyClass); // MyClassi simgeleyen bir
Type nesnesi al

Console.WriteLine(Analyzing methods in + t.Name);
Console.WriteLine();

Console.WriteLine(Methods supported: );
MethodInfo[] mi = t.GetMethods();

// MyClass tarafindan desteklenen metotlari goster.
foreach(MethodInfo m in mi) {
// Donus tipini ve ismini goster.
Console.Write( + m.ReturnType.Name +
+ m.Name + ();

// Parametreleri goster.
ParameterInfo[] pi = m.GetParameters();

for(int i = 0; i < pi.Length; i++) {
Console.Write(pi[i].ParameterType.Name +

HERKES N C#
KISIM I C# DL

484
+ pi[i].Name);
if(i + 1 < pi.Length) Console.Write(, );
}

Console.WriteLine());

Console.WriteLine();
}
}
}
kt aada gsterilmitir:
Analyzing methods in MyClass
Methods supported:
Int32 GetHashCode()

Boolean Equals(Object obj)

String ToString()

Int32 sum()

Boolean isBetween(Int32 i)

Void set(Int32 a, Int32 b)

Void set(Double a, Double b)

Void show()

Type GetType()
MyClass tarafndan tanmlanan metotlara ek olarak object tarafndan tanmlanan
metotlarn da ekranda gsterildiine dikkat edin. Bunun nedeni, C#ta tm tiplerin kaltm
yoluyla objectten tretilmesidir. Ayrca, .NET yap isimlerinin tip isimleri olarak
kullanldna da dikkat edin. set()in iki kez gsterildiini gzleyin. Bu durum set() ar
yklendii iin sz konusu olmutur. set()in bir versiyonu int argmanlar; dieri ise
double argmanlar almaktadr.
Gelin imdi bu programa yakndan bakalm. ncelikle, MyClassn bir public
yaplandrc ve ar yklenmi set() metodu da dahil olmak zere birka tane de public
metot tanmladna dikkat edin.
Main()in iinde aadaki kod satr kullanlarak MyClass simgeleyen bir Type
nesnesi elde edilmektedir:
Type t = typeof(MyClass); // MyClassi simgeleyen bir
Type nesnesi al
BLM 17: ALIMA ZAMANI TP TANIMLAMASI, YANSIMA VE NTELKLER

HERKES N C#
485
Program, daha sonra t ve Reflection API kullanarak MyClass tarafndan desteklenen
metotlarla ilgili bilgileri ekranda grntlemektedir. lk nce, aadaki ifade ile metotlarn lis-
tesi elde edilir:
MethodInfo[] mi = t.GetMethods();
Sonra, mi zerinden tekrarlayan bir foreach dngs kurulur. Dngnn her tekrarnda
aadaki kod tarafndan her metot iin dn tipi ve parametreler ekranda grntlenir:
// Donus tipini ve ismini goster.
Console.Write( + m.ReturnType.Name + + m.Name + ();

// Parametreleri goster.
ParameterInfo[] pi = m.GetParameters();

for(int i = 0; i < pi.Length; i++) {
Console.Write(pi[i].ParameterType.Name + + pi[i].Name);
if(i + 1 < pi.Length) Console.Write(, );
}
Bu kod sekans iinde, metotlarn her biriyle ilikili parametreler GetParameters()
arlarak elde edilir ve pi dizisinde saklanr. Sonra pi dizisi zerinde bir for dngs her
parametrenin tipini ve ismini grntleyerek tekrarlar. Buradaki en nemli nokta, bu bilgilerin
Myclass hakknda n bilgiye bel balamadan programn almas srasnda dinamik olarak
elde edilmesidir.
GetMethods()n kinci Kullanm ekli
GetMethods()n ikinci kullanm ekli, elde edilen metotlar szen eitli iaretler
kullanmanza olanak tanr. Genel olarak u ekilde kullanlr:
MethodInfo[] GetMethods(BindingFlags iaretler)
Bu versiyon ile yalnzca sizin belirtmi olduunuz kriterlerle elenen metollar elde edilir.
BindingFlags bir numaralandrmadr. En sk kullanlan BindingFlags deerlerinden
birka aada gsterilmitir:
Deer Anlam
DeclaredOnly Yalnzca belirtilen snf tarafndan tanmlanan metotlar elde eder. Kaltm
yoluyla elde edilen metotlar dahil edilmez.
Instance rnek metotlar elde eder.
NonPublic
public olmayan metotlar elde eder.
Public
public metotlar elde eder.
Static
static metotlar elde eder.

HERKES N C#
KISIM I C# DL

486
ki veya daha fazla iarete VEYA uygulayabilirsiniz. Aslnda, en azndan Public veya
NonPublic ile birlikte ya Instance ya da Statici dahil etmelisiniz. Bunun
baarlmamas durumunda metotlarn hi biri elde edilmeyecektir.
GetMethods()n BindingFlags eklinde balca kullanmlarndan biri, tretilmi
metotlar ayrca elde etmeden bir snf tarafndan tanmlanan metotlarn listesini elde etmektir.
Bu, zellikte object tarafndan tanmlanan metotlarn elde edilmesini nlemek iin
kullanldr. rnein, GetMethods()a yaplan u ary nceki programa yerletirmeyi
deneyin:
/* Simdi, yalnizca MyClass tarafindan deklare edilen metotlar
elde edilecektir. */
MethodInfo[] mi = t.GetMethods(BindingFlags.DeclaredOnly |
BindingFlags.Instance |
BindingFlags.Public);
Bu deiiklii yaptktan sonra program aadaki kty retir:
Analyzing methods in MyClass

Methods supported:
Int32 sum()

Boolean isBetween(Int32 i)

Void set(Int32 a, Int32 b)

Void set(Double a, Double b)

Void show()
Grdnz gibi, yalnzca MyClass tarafndan aka tanmlanan metotlar ekranda
grntlenmektedir.
Metotlar Yansma Kullanarak armak
Bir tipin hangi metotlar desteklediini bildikten sonra bu metotlarn birini ya da daha
fazlasn arabilirsiniz. Bunun iin MethodInfo iinde bulunan Invoke() metodunu
kullanacaksnz. Bu metot aada gsterilmitir:
ooject Invoke(object nesne, object[ ] argmanlar)
Burada nesne, metodun zerinde arld nesneye bir referanstr. static metotlar iin
nesne null deerinde olmaldr. Metoda aktarlmas gereken herhangi argman argmanlar
dizisinde belirtilir. Hi argmana gerek yoksa argmanlar dizisi null olmaldr. Ayrca,
argmanlar dizisi tam olarak argman says kadar eleman iermelidir. Bu nedenle, eer iki
argman gerekiyorsa argmanlar dizisi iki eleman uzunluunda olmaldr. rnein ya da
drt eleman uzunluunda olamaz.
BLM 17: ALIMA ZAMANI TP TANIMLAMASI, YANSIMA VE NTELKLER

HERKES N C#
487
Bir metodu armak iin GetMethods() arlarak elde edilmi olan bir MethodInfo
rnei zerinden Invoke()u armak yeterlidir. Aadaki program bu prosedr
gstermektedir:
// Yansima kullanarak metotlari cagirmak.

using System;
using System.Reflection;

class MyClass {
int x;
int y;

public MyClass(int i, int j) {
x = i;
y = j;
}

public int sum() {
return x + y;
}

public bool isBetween(int i) {
if((x < i) && (i < y)) return true;
else return false;
}

public void set(int a, int b) {
Console.Write(Inside set(int, int). );
x = a;
y = b;
show();
}

// seti asiri yukle.
public void set(double a, double b) {
Console.Write(Inside set(double, double). );
x = (int) a;
y = (int) b;
show();
}

public void show() {
Console.WriteLine(Values are x: {0}, y: {1}, x, y);
}
}

class InvokeMethDemo {
public static void Main() {
Type t = typeof(MyClass);
MyClass reflectOb = new MyClass(10, 20);
int val;

Console.WriteLine(Invoking methods in + t.Name);

HERKES N C#
KISIM I C# DL

488
Console.WriteLine();
MethodInfo[] mi = t.GetMethods();

// Metotlarin her birini cagir.
foreach(MethodInfo m in mi) {
// Parametreleri al.
ParameterInfo[] pi = m.GetParameters();

if(m.Name.CompareTo(set) == 0 &&
pi[0].ParameterType == typeof(int)) {
object[] args = new object[2];
args[0] = 9;
args[1] = 18;
m.Invoke(reflectOb, args);

}
else if(m.Name.CompareTo(set") == 0 &&
pi[0|.ParameterType == typeof(double)) {
object[] args = new object[2];
args[0] = 1.12;
args[1] = 23.4;
m.Invoke(reflectOb, args);
}
else if(m.Name.CompareTo(sum) == 0) {
val = (int) m.Invoke(reflectOb, null);
Console.WriteLine(sum is + val);
}
else if(m.Name.CompareTo(isBetween) == 0) {
object[] args = new object[1];
args[0] = 14;
if((bool) m.Invoke(reflectOb, args))
Console.WriteLine(14 is between x and y);
}
else if(m.Name.CompareTo(show) == 0) {
m.Invoke(reflectOb, null);
}
}
}
}
kt aada gsterilmitir:
Invoking methods in MyClass

sum is 30
14 is between x and y
Inside set(int, int). Values are x: 9, y: 18
Inside set(double, double). Values are x: 1, y: 23
Values are x: 1, y: 23
Metotlarn nasl arldna yakndan bakn. ncelikle, metotlarn listesi elde
edilmektedir. Sonra, foreach dngs iinde parametre bilgileri alnr. Daha sonra, bir dizi
if/else ifadesi kullanlarak metotlarn her biri uygun tip ve argman says ile birlikte
BLM 17: ALIMA ZAMANI TP TANIMLAMASI, YANSIMA VE NTELKLER

HERKES N C#
489
altrlr. Ar yklenmi set() metodunun aadaki kod kullanlarak altrl biimine
zellikle dikkat edin:
if(m.Name.CompareTo(set) == 0 &&
pi[0].ParameterType == typeof(int)) {
object[] args = new object[2];
args[0] = 9;
args[1] = 18;
m.Invoke(reflectOb, args);
}
else if(m.Name.CompareTo(set) == 0 &&
pi[0].ParameterType == typeof(double)) {
object[] args = new object[2];
args[0] = 1.12;
args[1] = 23.4;
m.Invoke(reflectOb, args);
}
Eer metodun ismi ayarlanma, sz konusu metodun hangi versiyonunun mevcut
olduunu belirlemek iin ilk parametrenin tipi test edilir. Eer sz konusu olan set(int,
int) ise bu durumda int argmanlar argsa yklenir ve set() arlr. Aksi halde, double
argmanlar kullanlr.
Typen Yaplandrclarn Elde Etmek
nceki rnekte MyClass zerinden metotlar armak iin yansma kullanmak avantaj
salamamtr, nk MyClass tipinde bir nesne zaten aka oluturulmutu. Yalnzca bu
nesnenin metotlarn armak normal olarak daha kolay olacakt. Ancak, yansmann gc, bir
nesne, programn almas srasnda dinamik olarak oluturulduunda ortaya kmaya balar.
Bunun iin ncelikle yaplandrclarn listesini edinmeniz gerekecektir. Sonra,
yaplandrclardan birini ararak sz konusu tipin bir rneini oluturacaksnz. Bu
mekanizma, herhangi bir tipteki nesneyi, bir deklarasyon ifadesi iinde isimlendirmeden
rneklemenize imkan verir.
Bir tip iin yaplandrclar elde etmek amacyla bir Type nesnesi zerinde
GetConstructors() arn. En sk kullanlan biimlerden biri aada gsterilmitir:
ConstructorInfo[] GetConstructors()
Bu ifade, yaplandrclar tarif eden ConstructorInfo nesnelerinin bir dizisini
dndrr.
ConstructorInfo, MethodBase zet snfndan tretilmitir. MethodBase, kaltm
yoluyla MemberInfodan gelmektedir. ConstructorInfo ayrca kendisine zg birka ye
daha tanmlar. Biz bu yelerden, bir yaplandrcyla ilikili parametrelerin listesini dndren
GetParameters() ile ilgilenmekteyiz. Bu metot, tpk daha nce anlatlan, MethodInfo
tarafndan tanml GetParameters() gibi almaktadr.

HERKES N C#
KISIM I C# DL

490
Uygun bir yaplandrc bulduktan sonra ConstructorInfo tarafndan tanmlanm
Invoke() metodu arlarak bir nesne oluturulur. Invoke() aada gsterilmitir:
object Invoke(object[] argmanlar)
Metoda aktarlmas gereken argmanlar, argmanlar dizisinde belirtilir. Eger hi
argman gerekmiyorsa argmanlar dizisi null olmaldr- Ayrca, argmanlar dizisi tam
olarak argman says kadar eleman iermelidir. Invoke(), sz konusu nesneye bir referans
dndrr.
Aadaki programda, Myclassn bir rneini oluturmak iin yansma kullanlmaktadr:
// Yansima kullanarak bir nesne olustur.

using System;
using System.Reflection;

class MyClass {
int x;
int y;

public MyClass(int i) {
Console.WriteLine(Constructing MyClass(int, int). );
x = y = i;
}

public MyClass(int i, int j) {
Console.WriteLine(Constructing MyClas(int, int). );
x = i;
y = j;
show();
}

public int sum() {
return x + y;
}

public bool isBetween(int i) {
if((x < i) && (i < y)) return true;
else return false;
}

public void set(int a, int b) {
Console.Write(Inside set(int, int). );
x = a;
y = b;
show();
}

// seti asiri yukle.
public void set(double a, double b) {
Console.Write(Inside set(double, double). );
x = (int) a;
y = (int) b;
BLM 17: ALIMA ZAMANI TP TANIMLAMASI, YANSIMA VE NTELKLER

HERKES N C#
491
show();
}

public void show() {
Console.WriteLine(Values are x: {0}, y: {1}, x, y);
}
}

class InvokeConsDemo {
public static void Main() {
Type t = typeof(MyClass);
int val;

// Yapilandirici bilgilerini al.
ConstructorInfo[] ci = t.GetConstructors();

Console.WriteLine(Available constructors: );
foreach(ConstructorInfo c in ci) {
// Donus tipini ve ismini goster.
Console.Write( + t.Name + ();

// Parametreleri goster.
ParameterInfo[] pi = c.GetParameters();

for(int i = 0; i < pi.Length; i++) {
Console.Write(pi[i].ParameterType.Name +
+ pi[i].Name);
if(i + 1 < pi.Length) Console.Write(, );
}

Console.WriteLine());
}

Console.WriteLine();

// Eslenen yapilandiriciyi bul.
int x;

for(x = 0; x < ci.Length; x++) {
ParameterInfo[] pi = ci[x].GetParameters();
if(pi.Length == 2) break;
}

if(x == ci.Length) {
Console.WriteLine(No matching constructor found.);
return;
}
else
Console.WriteLine(Two-parameter constructor found.\n);

// Nesneyi yapilandir.
object[] consargs = new object[2];
consargs[0] = 10;
consargs[1] = 20;
object reflectOb = ci[x].Invoke(consargs);

HERKES N C#
KISIM I C# DL

492

Console.WriteLine(\nInvoking methods on reflectOb.);
Console.WriteLine();
MethodInfo[] mi = t.GetMethods();

// Metotlarin her birini cagir.
foreach(MethodInfo m in mi) {
// Parametreleri al.
ParameterInfo[] pi = m.GetParameters();

if(m.Name.CompareTo(set) == 0 &&
pi[0].ParameterType == typeof(int)) {
// Bu, set(int, int).
object[] args = new object[2];
args[0] = 9;
args[1] = 18;
m.Invoke(reflectOb, args);
}
else if(m.Name.CompareTo(set) == 0 &&
pi[0].ParameterType == typeof(double)) {
// Bu, set(double, double).
object[] args = new object[2];
args[0] = 1.12;
args[1] = 23.4;
m.Invoke(reflectOb, args);
}
else if(m.Name.CompareTo(sum) == 0) {
val = (int) m.Invoke(reflectOb, null);
Console.WriteLine(sum is + val);
}
else if(m.Name.CompareTo(isBetween) == 0) {
object[] args = new object[1];
args[0] = 14;
if((bool) m.Invoke(reflectOb, args))
Console.WriteLine(14 is between x and y);
}
else if(m.Name.CompareTo(show) == 0) {
m.Invoke(reflectOb, null};
}
}
}
}
kt aada gsterilmitir:
Available constructors:
MyClass(Int32 i)
MyClass(Int32 i, Int32 j)

Two-parameter constructor found.

Constructing MyClass(int, int).
Values are x: 10, y: 20

Invoking methods on reflectOb.
BLM 17: ALIMA ZAMANI TP TANIMLAMASI, YANSIMA VE NTELKLER

HERKES N C#
493

sum is 30
14 is between x and y
Inside set(int, int). Values are x: 9, y: 18
Inside set(double, double). Values are x: 1, y: 23
Values are x: 1, y: 23
Gelin imdi, bir MyClass nesnesi yaplandrmak iin yansmann nasl kullanldna gz
atalm. ncelikle, aadaki ifade kullanlarak ak yaplandrclarn bir listesi elde edilir:
ConstructorInfo[] ci = t.GetConstructors();
Bir sonraki ilemde, gsterim amacyla yaplandrclar ekranda grntlenir. Sonra, aa-
daki kod kullanlarak iki argman alan bir yaplandrc listede aranr:
for(x = 0; x ci.Length; x++) {
ParameterInfo[] pi = ci[x].GetParameters();
if(pi.Length == 2) break;
}
Eer yaplandrc bulunursa (bu rnekte olduu gibi), aadaki kod sekans tarafndan bir
nesne rneklenir:
// Nesneyi yapilandir.
object[] consargs = new object[2];
consargs[0] = 10;
consargs[1] = 20;
object reflectOb = ci[x].Invoke(consargs);
Invoke() arsndan sonra reflectOb, MyClass tipinde bir nesneye referansta
bulunacaktr.
nemli bir hususun altn izmek gereklidir. Bu rnekte, ileri karmaklatrmamak iin
iki argmanl tek yaplandrcnn iki int argman alan fonksiyon olduu varsaylmtr.
Gerek dnyaya ait bir uygulamada, her argmann parametre tipi kontrol edilerek bu durumun
dorulanmas gerekecektir.
Assemblylerden Tip Elde Etmek
nceki rnekte, tek bir e haricinde, MyClass ile ilgili her ey yansma kullanlarak
kefedilmitir. Kefedilmemi olan MyClass tipinin kendisidir. Yani, nceki rneklerde
MyClass ile ilgili bilgiler dinamik olarak elde edilmi olsa da, bu rnekler yine de MyClass
tip isminin nceden bilindii ve MyClass tip isminin, zerinde tm yansma metotlarnn
dorudan ya da dolayl olarak ilem grd bir Type nesnesi elde etmek amacyla bir typeof
ifadesinde kullanld gereine dayanyorlard. Bu durum belki birka koul iin ie yaryor
olsa da yansmann tam gc, dier assemblylerin ierikleri analiz edilerek bir programn
kullanmna hazr olan tipler dinamik olarak belirlendiinde ortaya kmaktadr.
Blm 16da rendiiniz gibi, bir assembly ierdii snflar, yaplar vs hakknda tip
bilgilerini kendisiyle birlikte tar. Reflection API bir assemblyyi yklemenize, bu assembly

HERKES N C#
KISIM I C# DL

494
ile ilgili bilgileri kefetmenize ve bu assemblynin ak olarak kullanlabilir tiplerinin
rneklerini oluturmanza olanak tanr. Bu mekanizmay kullanarak bir program kendi
ortamn, mevcut olabilecek ilevsellikten yararlanarak - bu ilevsellii derleme srasnda
aka tanmlamak zorunda kalmadan - aratrabilir. Bu son derece gl ve heyecan verici bir
kavramdr. rnein, bir sistemdeki mevcut olan tm tipleri gsteren bir tip taraycs gibi
davranan bir program hayal edebilirsiniz. Bir baka uygulama, sistem tarafndan desteklenen
eitli tiplerden oluan bir program grsel olarak balamanza imkan veren bir tasarm arac
olabilir. Bir tip hakknda tm bilgiler kefedilebilir olduu iin, yansmann uygulanabilecei
yntemlere doal bir kstlama sz konusu deildir.
Bir assembly hakknda bilgi edinmek iin ncelikle bir Assembly nesnesi
oluturacaksnz. Assembly snf bir public yaplandrc tanmlamaz. Bunun yerine, bir
Assembly nesnesi metotlarndan biri arlarak elde edilir. Bizim kullanacamz
LoadForm()dur. Bizim kullanacamz ekil aada gsterilmitir:
static Assembly LoadFrom(string dosyaad)
Burada dosyaad, assemblynin adn belirtir.
Bir kez bir Assembly nesnesi elde ettikten sonra bu nesne zerinde GetTypes()
ararak nesnenin tanmlad tipleri kefedebilirsiniz. GetTypes() genel olarak u
ekildedir:
Type[] GetTypes()
Bu ifade, assemblynin iinde bulunan tiplerin bir dizisini dndrr.
Bir assembly iindeki tiplerin ortaya karln gstermek iin iki dosyaya gerek
duyacaksnz. lk dosya, ikinci dosya tarafndan kefedilecek birtakm snflar ierir.
Programlamaya aadaki kodu ieren MyClasses.cs adnda bir dosya oluturarak balayn.
// Uc sinif iceren bir dosya. Bu dosyaya MyClasses.cs ismini verin.

using System;

class MyClass {
int x;
int y;

public MyClass(int i) {
Console.WriteLine(Constructing MyClass(int). );
x = y = i;
show();
}

public MyClass(int i, int j) {
Console.WriteLine(Constructing MyClass(int, int). );
x = i;
y = j;
show();
}
BLM 17: ALIMA ZAMANI TP TANIMLAMASI, YANSIMA VE NTELKLER

HERKES N C#
495

public int sum() {
return x + y;
}

public bool isBetween(int i) {
if((x < i) && (i < y)) return true;
else return false;
}

public void set(int a, int b) {
Console.Write(Inside set(int, int). );
x = a;
y = b;
show();
}

// seti asiri yukle.
public void set(double a, double b) {
Console.Write(Inside set(double, double). );
x = (int) a;
y = (int) b;
show();
}

public void show() {
Console.WriteLine(Values are x: {0}, y: {1}, x, y);
}
}

class AnotherClass {
string remark;

public AnotherClass(string str) {
remark = str;
}

public void show() {
Console.WriteLine(remark);
}
}

class Demo {
public static void Main() {
Console.WriteLine(This is a placeholder.);
}
}
Bu dosya, nceki rneklerde kullanmakta olduumuz MyClass snfn iermektedir.
Ayrca AnotherClass adnda ikinci bir snf ve Demo adnda da nc bir snf
eklemektedir. Bylece bu programdan elde edilen assembly, snf ierecektir. Sonra, bu
dosyay MyClasses.exe dosyas retilecek ekilde derleyin. Bu, ilem srasnda sorgulanacak
olan assemblydir.

HERKES N C#
KISIM I C# DL

496
MyClasses.exe hakknda bilgileri ortaya karacak program aada gsterilmitir. Bu
program u aamada derleyicinizin editrne girin.
/* Yansima kullanarak bir assembly yapilandirin, tipleri
belirleyin ve bir nesne olusturun. */

using System;
using System.Reflection;

class ReflectAssemblyDemo {
public static void Main() {
int val;

// MyClasses.exe assemblysini yukleyin.
Assembly asm = Assembly.LoadFrom(MyClasses.exe);

// MyClasses.exenin hangi tipleri icerdigini saptayin.
Type[] alltypes = asm.GetTypes();
foreach(Type temp in alltypes)
Console.WriteLine(Found: + temp.Name);

Console.WriteLine();

// Ilk tipi kullanin, bu kez bu tip MyClassdir.
Type t = alltypes[0]; // bulunan ilk sinifi kullan
Console.WriteLine(Using: + t.Name);

// Yapilandirici bilgisini edin.
ConstructorInfo[] ci = t.GetConstructors();

Console.WriteLine(Available constructors: );
foreach(ConstructorInfo c in ci) {
// Donus tipini ve ismini goster.
Console.Write( + t.Name + ();

// Parametreleri goster.
ParameterInfo[] pi = c.GetParameters();

for(int i = 0; i < pi.Length; i++) {
Console.Write(pi[i].ParameterType.Name +
+ pi[i].Name);
if(i + 1 < pi.Length) Console.Write(, );
}

Console.WriteLine());
}
Console.WriteLine();

// Eslenen yapilandiriciyi bul.
int x;

for(x = 0; x < ci.Length; x++) {
ParameterInfo[] pi = ci[x] GetParameters();
if(pi.Length == 2) break;
}
BLM 17: ALIMA ZAMANI TP TANIMLAMASI, YANSIMA VE NTELKLER

HERKES N C#
497

if(x == ci.Length) {
Console.WriteLine(No matching constructor found.);
return;
}
else
Console.WriteLine(Two-parameter constructor found.\n);

// Nesneyi yapilandir.
object[] consargs = new object[2];
consargs[0] = 10;
consargs[1] = 20;
object reflectOb = ci[x].Invoke(consargs);

Console.WriteLine(\nInvoking methods on reflectOb.);
Console.WriteLine();
MethodInfo[] mi = t.GetMethods();

// Metotlarin her birini cagir.
foreach(MethodInfo m in mi) {
// Parametreleri al.
ParameterInfo[] pi = m.GetParameters();

if(m.Name.CompareTo(set) == 0 &&
pi[0].ParameterType == typeof(int)) {
// Bu, set(int, int).
object[] args = new object[2];
args[0] = 9;
args[1] = 18;
m.Invoke(reflectOb, args);
}
else if(m.Name.CompareTo(set) == 0 &&
pi[0].ParameterType == typeof(double)) {
// Bu, set(double, double).
object[] args = new ob)ect[2];
args[0] = 1.12;
args[1] = 23.4;
m.Invoke(reflectOb, args);
}
else if (m.Name.CompareTo(sum) == 0) {
val = (int) m.Invoke(reflectOb, null);
Console.WriteLine(sum is + val);
}
else if(m.Name.CompareTo(isBetween) == 0) {
object[] args = new object[1];
args[0] = 14;
if((bool) m.Invoke(reflectOb, args))
Console.WriteLine(14 is between x and y);
}
else if(m.Name.CompareTo(show) == 0) {
m.Invoke(reflectOb, null);
}
}
}
}

HERKES N C#
KISIM I C# DL

498
Programn kts aada gsterilmitir:
Found: MyClass
Found: AnotherClass
Found: Demo

Using: MyClass
Available constructors:
MyClass(Int32 i)
MyClass(Int32 i, Int32 j)

Two-parameter constructor found.

Constructing MyClass(int, int).
Values are x: 10, y: 20

Invoking methods on reflectOb.

sum is 30
14 is between x and y
Inside set(int, int). Values are x: 9, y: 10
Inside set(double, double). Values are x: 1, y: 23
Values are x: 1, y: 23
ktdan da grld gibi, MyClasses.exe iinde yer alan snflarn de
bulunmutur. Bunlardan ilki - bu rnekte MyClass - sonra bir nesneyi rneklemek ve metotlar
gereklemek iin kullanlmtr. Btn bu ilemler MyClasses.exe ieriinin n bilgisine
gerek kalmadan gerekletirilmitir.
MyClasses.exe iindeki tipler, Main()in balangcna yakn bir yerlerde yer alan
aadaki kod sekans kullanlarak ortaya karlmtr:
// MyClasses.exe assemblysini yukleyin.
Assembly asm = Assembly.LoadFrom(MyClasses.exe);

// MyClasses.exenin hangi tipleri icerdigini saptayin.
Type[] alltypes = asm.GetTypes();
foreach(Type temp in alltypes)
Console.WriteLine(Found: + temp.Name);
Bir assemblyyi dinamik olarak yklemeniz ve sorgulamanz gereken her durumda bu tr
bir sekans kullanabilirsiniz.
Bununla balantl bir konu udur: Bir assemblynin bir exe dosyas olmas gerekmez.
Assemblyler ayrca dll uzantsn kullanan dinamik balant ktphanesi' (DLL - Dynamic
Link Library) dosyalarnn iinde de yer alabilirler. rnein, MyClasses.cs programn u
komut satrn kullanarak derlemek durumunda kalm olsaydnz,
csc /t:library MyClasses.cs
kt dosyas MyClasses.dll olurdu. Kodu bir DLL iine yerletirmenin avantaj, bu
durumda Main() metoduna gerek olmamasdr. Tm exe dosyalar Main() gibi bir balang
BLM 17: ALIMA ZAMANI TP TANIMLAMASI, YANSIMA VE NTELKLER

HERKES N C#
499
noktas gerektirirler. Demo snfnn, yer tutucusu ilevini gren bir Main() metodu
iermesinin sebebi de budur. DLLler balang noktas gerektirmezler. Eer MyClass bir
DLLe evirmeye alrsanz, LoadFrom()a yaplan ary aada gsterildii gibi
deitirmeniz gerekecektir.
Assembly asm = Assembly.LoadFrom(MyClasses.dll);
Tiplerin Ortaya karlmasn Tam Olarak Otomatize
Etmek
Yansma konusunu terk etmeden nce son bir rnek retici olacaktr. nceki program
Myclass program iinde aka belirtmeye gerek kalmadan tam olarak kullanabiliyor
olmasna ramen, yine de MyClass ieriiyle ilgili bir n bilgiye dayanyordu. rnein,
program MyClassn metotlarnn isimlerini biliyordu; sz gelii set ve sum gibi. Ancak,
yansma kullanarak hakknda hi n bilgiye sahip olmadnz bir tipten yararlanmanz
mmkndr. Bunun iin, bir nesnenin kurulumu ve metot arlarnn retilmesi iin gerekli
tm bilgiyi ortaya karmalsnz. Bu tr bir yaklam, mein bir grsel tasarm arac iin
kullanl olacaktr, nk bu sayede sistem zerinde mevcut tiplerden yararlanlabilir.
Bir tipin dinamik olarak nasl kefedilebilecegini grmek iin aadaki rnei ele aln. Bu
rnekte, MyClasses.exe assemblysi yklenmekte, MyClass nesnesi yaplandrlmakta ve
daha sonra MyClass tarafndan tanmlanan tm metotlar arlmaktadr. Bunlar yaplrken
herhangi bir n bilgi varsaymnda bulunulmamaktadr:
// On bilgi varsayiminda bulunmadan MyClassin kullanimi.

using System;
using System.Reflection;

class ReflectAssemblyDemo {
public static void Main() {
int val;
Assembly asm = Assembly.LoadFrom(MyClasses.exe);

Type[] alltypes = asm.GetTypes();

Type t = alltypes[0]; // bulunan ilk sinifi kullan

Console.WriteLine(Using: + t.Name);

ConstructorInfo[] ci = t.GetConstructors();

// Bulunan ilk yapilandiriciyi kullan.
ParameterInfo[] cpi = ci[0].GetParameters();
object reflectOb;

if(cpi.Length > 0) {
object[] consargs = new object[cpi.Length];


HERKES N C#
KISIM I C# DL

500
//argumanlara baslangic degeri ata
for(int n = 0; n < cpi.Length; n++)
consargs[n] = 10 + n * 20;

// nesneyi yapilandir
reflectOb = ci[0].Invoke(consargs);
} else
reflectOb = ci[0].Invoke(null);

Console.WriteLine(\nInvoking methods on reflectOb.);
Console.WriteLine();

// kalitimla alinan metodlari dikkate alma.
MethodInfo[] mi = t.GetMethods(BindingFlags.DeclaredOnly |
BindingFlags.Instance |
BindingFlags.Public);

// Metotlarn her birini cagir.
foreach(MethodInfo m in mi) {
Console.WriteLine(Calling {0} , m.Name);

// Parametreleri al.
ParameterInfo[] pi = m.GetParameters();

// Metodlari calistir.
switch(pi.Length) {
case 0: // argumansiz
if(m.ReturnType == typeof(int)) {
val = (int) m.Invoke(reflectOb, null);
Console.WriteLine(Result is + val);
}
else if(m.ReturnType == typeof(void)) {
m.Invoke(reflectOb, null);
}
break;
case 1: // bir argumanli
if(pi[0].ParameterType == typeof(int)) {
object[] args = new object[1];
args[0] = 14;
if((bool) m.Invoke(reflectOb, args))
Console.WriteLine(14 is between x and y);
else
Console.WriteLine(14 is not between x and y);
}
break;
case 2: // iki argumanli
if((pi[0].ParameterType == typeof(int)) &&
(pi[1].ParameterType == typeof(int))) {
object[] args = new object[2];
args[0) = 9;
args[1] = 18;
m.Invoke(reflectOb, args);
}
else if((pi[0].ParameterType == typeof(double)) &&
(pi[1].ParameterType == typeof(double))) {
BLM 17: ALIMA ZAMANI TP TANIMLAMASI, YANSIMA VE NTELKLER

HERKES N C#
501
object[] args = new object[2];
args[0] = 1.12;
args[1] = 23.4;
m.Invoke(reflectOb, args);
}
break;
}
Console.WriteLine();
}
}
}
Programn kts yledir:
Using: MyClass
Constructing MyClass(int).
Values are x: 10, y: 10

Invoking methods on reflectOb.

Calling sum
Result is 20

Calling isBetween
14 is not between x and y

Calling set
Inside set(int, int). Values are x: 9, y: 18

Calling set
Inside set(double, double). Values are x: 1, y: 23

Calling show
Values are x: 1, y: 23
Programn almas gayet aktr, ama iki noktaya deinmekte yarar vardr. Birincisi
udur: Dikkat ederseniz sadece MyClass tarafndan aka bildirilen metotlar alnm ve
kullanlmlardr. Bu, GetMethods()n BindingFlagsi kullanlarak salanmtr. Burada
ama, objectten kaltm yoluyla alnan metotlarn arlmasn engellemektir. kinci nokta
ise udur: Parametre saysnn ve her metodun dn tipinin dinamik olarak elde edilme ekline
dikkat edin. Parametre says bir switch ifadesi tarafndan belirlenmektedir. Her case iinde
parametre tipi (ya da tipleri) ve dn tipleri kontrol edilmektedir. Daha sonra metot ars bu
bilgiye dayal olarak yaplandrlmaktadr.

Nitelikler
C#, bir programa deklaratif bilgileri nitelik biiminde eklemenize izin verir. Bir nitelik; bir
snf, yap, metot ve benzeriyle ilgili ek bilgileri tanmlar. rnein, bir snfn ekrana getirecei
dme (button) tipini belirleyen bir nitelik tanmlayabilirsiniz. Nitelikler, uygulandklar
eden nce ve keli parantez iinde belirtilirler. Bu nedenle, bir nitelik bir snfn yesi
deildir ve ilikili olduu e hakknda ek bilgi salar.

HERKES N C#
KISIM I C# DL

502
Niteliklerle lgili Temel Bilgiler
Bir nitelik, System.Attributetan kaltm yoluyla tretilen bir snf tarafndan
desteklenir. Dolaysyla, tm nitelik snflar, Attributen alt snflar olmak durumundadr.
Attributen kayda deer lde ilevsellik tanmlamasna ramen bu ilevsellik, niteliklerle
alrken her zaman gerekli deildir. Geleneksel olarak nitelik snflarnda Attribute soneki
kullanlr. rnein, ErrorAttribute, bir hatay tanmlayan bir nitelik snfnn ismi olarak
tercih edilir.
Bir nitelik snf deklare edilirken, daha nce AttributeUsage adl bir nitelik yazlr.
Sistemde tanml olan bu nitelik, deklare edilen niteliin uygulanabilecei e tiplerini belirler.
Nitelik Oluturmak
Bir nitelik snfnda nitelii destekleyen yeleri sizin tanmlamanz gerekir. Genellikle
nitelik snflar olduka basittir, sadece az sayda alan ya da zellik ierirler. rnein, bir
nitelik, ilikili olduu eyi tarif eden bir aklama tanmlayabilir. Byle bir niteliin biimi
aadaki gibi olabilir:
[AttributeUsage(AttributeTargets.All)]
public class RemarkAttribute : Attribute {
string pri_remark; // remark ozelliginin altinda yer alir

public RemarkAttribute(string comment) {
pri_remark = comment;
}

public string remark {
get {
return pri_remark;
}
}
}
imdi bu snf satr satr ele alalm.
Bu niteliin ad RemarkAttributetr. Niteliin deklarasyonundan nce
AttributeUsage adl nitelik yer almtr. AttributeUsage, RemarkAttributen tm
e tiplerine uygulanabilir olduunu belirlemektedir. AttributeUsage kullanarak bir
niteliin ilitirilebilecei eler listesini ksaltmak mmkndr ve bu niteliin neler
yapabilecei bu blmde ele alnacaktr.
Dana sonra RemarkAttribute deklare edilmitir ve Attributetan kaltm yoluyla
tretilmitir. RemarkAttributen iinde private bir alan olan pri_remark yer
almaktadr ve bu alan bir adet public, salt okunur zellii yani remark desteklemektedir.
Bir karakter katarn argman olarak alan ve bunu remarka atayan ak bir yaplandrc da
yer almaktadr.
BLM 17: ALIMA ZAMANI TP TANIMLAMASI, YANSIMA VE NTELKLER

HERKES N C#
503
Bu noktada artk baka bir adma gerek kalmamtr ve RemarkAttribute kullanma
hazrdr.
Bir Nitelii litirmek
Bir nitelik snfn tanmladktan sonra artk o nitelii bir eye ilitirebilirsiniz. Bir nitelik,
ilitirildii eden nce gelir ve yaplandrcs keli parantez iine alnarak belirlenir. rne-
in, RemarkAttributen bir snfla ilikilendirilmesi u ekilde yaplabilir:
[RemarkAttribute(This class uses an attribute.)]
class UseAttrib {
// ...
}
Bu kod ite This class uses an attribute aklamasn ieren bir RemarkAttribute
kurulmaktadr. Daha sonra nitelik UseAttrib ile ilikilendirilmektedir.
Bir nitelii ilitirirken, Attribute sonekini kullanmak aslnda gerekli deildir. rnein,
yukardaki snf u ekilde de bildirilebilir:
[Remark(This class uses an attribute.)]
class UseAttrib {
// ...
}
Burada isim olarak sadece Remark kullanlmtr. Bu ekilde ksa kullanm da dorudur
ama nitelikleri ilitirirken tam isimlerini kullanmak daha gvenlidir. nk bylece kark
belirsizlik ihtimalinden kanlm olur.
Bir Nesnenin Niteliklerini Almak
Bir nitelik bir eye ilitirildikten sonra, programn dier blmleri o nitelii okuyabilir.
Bir nitelii okumak iin genelde iki yntemden biri kullanlr. lk yntem, MemberInfo
tarafndan tanmlanan ve Type tarafndan kaltm ile alnan GetCustomAttributes()tr.
Bu metot, bir nesneye ilitirilmi olan tm niteliklerin listesini okur ve u genel biime sahiptir:
Object[ ] GetCustomAttributes(bool temelSnflarAra)
Burada temelSnflarAra true ise, kaltm zinciri zerindeki tm temel snflarn
nitelikleri dahil edilecektir. Aksi halde sadece belirtilen tip tararndan tanmlanan nitelikler
bulunacaktr.
kinci metot ise Attribute tarafndan tanmlanan GetCustomAttribute()tr. Bu
metodun biimlerinden biri aada gsterilmitir:
static Attribute GetCustomAttribute(MemberInfo mi, Type niteliktipi)
Burada mi nitelii, okunan eyi tanmlayan bir MemberInfo nesnesidir. stenen nitelik
niteliktipi tarafndan belirtilmektedir. Bu metodu, okumak istediiniz niteliin adn

HERKES N C#
KISIM I C# DL

504
bildiiniz durumlarda kullanrsnz - bu ou zaman geerli olan bir durumdur. rnein
RemarkAttributea bir referans almak iin u sekans kullanrsnz:
// RemarkAttributeu oku.
Type tRemAtt = typeof(RemarkAttribute);
RemarkAttribute ra = (RemarkAttribute)
Attribute.GetCustomAttribute(t, tRemAtt);
Bir nitelie ait bir referans elde ettikten sonra artk o niteliin yelerine eriebilirsiniz.
Dolaysyla, bir niteliin ilitirildii bir eyi kullanan bir program, o nitelikle ilintili bilgilere
eriebilir. rnein, aadaki ifade remark alann gsterir:
Console.WriteLine(ra.remark);
Aadaki program tm paralar bir araya getirmekte ve RemarkAttributen
kullanmn gstermektedir:
// Basit bir nitelik ornegi.

using System;
using System.Reflection;

[AttributeUsage(AttributeTargets.All)]
public class RemarkAttribute : Attribute {
string pri_remark; // remark ozelliginin altinda yer alir

public RemarkAttribute(string comment) {
pri_remark = comment;
}

public string remark {
get {
return pri_remark;
}
}
}

[RemarkAttribute(This class uses an attribute.)]
class UseAttrib {
// ...
}

class AttribDemo {
public static void Main() {
Type t = typeof(UseAttrib);

Console.Write(Attributes in + t.Name + : );

object[] attribs = t.GetCustomAttributes(false);
foreach(object o in attribs) {
Console.WriteLine(o);
}

Console.Write(Remark: );
BLM 17: ALIMA ZAMANI TP TANIMLAMASI, YANSIMA VE NTELKLER

HERKES N C#
505

// RemarkAttributei oku.
Type tRemAtt = typeof(RemarkAttribute);
RemarkAttribute ra = (RemarkAttribute)
Attribute.GetCustomAttribute(t, tRemAtt);

Console.WriteLine(ra.remark);
}
}
Programn kts yledir:
Attributes in UseAttrib: RemarkAttribute
Remark: This class uses an attribute.
Konumsal ve simlendirilmi Parametreler
nceki rnekte, RemarkAttributea balang deeri atamak iin tanmlayc karakter
katar, yaplandrcya normal yaplandrc sz dizimi ile aktarlmt. Bu durumda
RemarkAttribute()un comment parametresine konumsal parametre (positional
parameter) denir. Bu terim, argmann parametreye konumu itibariyle balanmasyla ilgilidir.
C#ta tm metotlar ve yaplandrclar bu ekilde alr. Ancak, bir nitelik iin isimlendirilmi
parametreler (named parameter) de oluturabilirsiniz ve bunlara, isimlerini kullanarak
balang deerleri atayabilirsiniz.
simlendirilmi bir parametre public bir alan ya da zellik tarafndan desteklenir ve bu
alan ya da zelliin salt okunur olmamas gereklidir. Byle herhangi bir alan ya da zellik,
otomatik olarak, isimlendirilmi bir parametre gibi kullanlabilir. simlendirilmi bir
parametreye deer atanmas, bir ge iin nitelik belirtilirken niteliin yaplandrcs iinde yer
alan bir atama ifadesi ile yaplr. simlendirilmi parametreleri de iine alan bir nitelik
spesifikasyonu genel ekil ile aada gsterilmitir:
[attrib(konumsal-parametre-listesi, isimlendirilmi-param1 = deer,
isimlendirilmi-param2 = deer, ...)]
Konumsal parametreler (eer mevcut iseler) nce gelirler. Daha sonra her bir
isimlendirilmi parametreye bir deer atanr. simlendirilmi parametrelerin sras nemli
deildir.
simlendirilmi parametrelere deer atanmas gerekli deildir. Bu durumda varsaylan
deerleri kullanlr.
simlendirilmi bir parametrenin nasl kullanlacan anlamann en iyi yolu, bir rnek
zerinden gitmektir. RemarkAttributen supplement adl yeni bir alan olan ve ek bir
aklamay tutabilen bir versiyonu aada yer almaktadr:
[AttributeUsage(AttributeTargets.All)]
public class RemarkAttribute : Attribute {
string pri_remark; // remark ozelliginin altinda yer alir


HERKES N C#
KISIM I C# DL

506
public string supplement; // bu isimlendirilmis bir parametredir

public RemarkAttribute(string comment) {
pri_remark = comment;
supplement = None;
}

public string remark {
get {
return pri_remark;
}
}
}
Grdnz gibi, yaplandrc tarafndan supplementa balang deeri olarak None
karakter katar atanmaktadr. Yaplandrcy baka bir ekilde kullanarak farkl bir balang
deeri atamak mmkn deildir. Ancak, supplement u ekilde isimlendirilmi bir parametre
olarak kullanlabilir:
[RemarkAttribute(This class uses an attribute.,
supplement = This is additional info.)]
class UseAttrib {
// ...
}
RemarkAttributen yaplandrcsnn nasl arldna ok dikkat edin. lk olarak,
daha nce de olduu gibi, konumsal argman belirtilmitir. Ardndan bir virgl ve onun
peinden de isimlendirilmi parametre olan supplement gelmi ve bu parametreye bir deer
atanmtr. Son olarak kapan parantezi ) yaplandrcya yaplan arya son vermitir. Bir
baka ifade ile, isimlendirilmi parametreye balang deeri, yaplandrcya yaplan ar
iinde atanmtr. Bu sz dizimini genelletirmek mmkndr. Konumsal parametreler,
grndkleri srada belirtilmelidirler. simlendirilmi parametreler ise isimlerine deer atanarak
belirtilirler.
Aadaki program supplement alann gstermektedir:
// isimlendirilmis bir nitelik parametresi kullanir.

using System;
using System.Reflection;

[AttributeUsage(AttributeTargets.All)]
public class RemarkAttribute : Attribute {
string pri_remark; // remark ozelliginin altinda yer alir
public string supplement; // bu isimlendirilmis bir parametredir

public RemarkAttribute(string comment) {
pri_remark = comment;
supplement = None;
}

public string remark {
BLM 17: ALIMA ZAMANI TP TANIMLAMASI, YANSIMA VE NTELKLER

HERKES N C#
507
get {
return pri_remark;
}
}
}

[RemarkAttribute(This class uses an attribute.,
supplement = This is additional info.)]
class UseAttrib {
// ...
}

class NamedParamDemo {
public static void Main() {
Type t = typeof(UseAttrib);

Console.Write(Attributes in + t.Name + : );

object[] attribs = t.GetCustomAttributes(false);
foreach(object o in attribs) {
Console.WriteLine(o);
}

// RemarkAttributeu oku.
Type tRemAtt = typeof(RemarkAttribute);
RemarkAttribute ra = (RemarkAttribute)
Attribute.GetCustomAttribute(t, tRemAtt);

Console.Write(Remark: );
Console.WriteLine(ra.remark);

Console.Write(Supplement: );
Console.WriteLine(ra.Supplement);
}
}
Programn kts yledir:
Attributes in UseAttrib: RemarkAttribute
Remark: This class uses an attribute.
Supplement: This is additional info.
Daha nce akland gibi, bir zellik ayn zamanda isimlendirilmi bir parametre olarak
da kullanlabilir. rnein burada priority adl bir int parametresi RemarkAttributea
eklenmektedir:
// Bir ozelligin, isimlendirilmis bir parametre olarak kullanimi.

using System;
using System.Reflection;

[AttributeUsage(AttributeTargets.All)]
public class RemarkAttribute : Attribute {
string pri_remark; // remark ozelliginin altinda yer alir


HERKES N C#
KISIM I C# DL

508
int pri_priority; // priority ozelliginin altinda yer alir

public string supplement; // bu isimlendirilmis bir parametredir

public RemarkAttribute(string comment) {
pri_remark = comment;
supplement = None;
}

public string remark {
get {
return pri_remark;
}
}

// Bir ozelligin isimlendirilmis bir parametre olarak kullanimi.
public int priority {
get {
return pri_priority;
}
set {
pri_priority = value;
}
}
}

[RemarkAttribute(This class uses an attribute.,
supplement = This is additional info.,
priority = 10)]
class UseAttrib {
// ...
}

class NamedParamDemo {
public static void Main() {
Type t = typeof(UseAttrib);

Console.Write(Attributes in + t.Name + : );

object[] attribs = t.GetCustomAttributes(false);
foreach(object o in attribs) {
Console.WriteLine(o);
}

// RemarkAttributeu oku.
Type tRemAtt = typeof(RemarkAttribute);
RemarkAttribute ra = (RemarkAttribute)
Attribute.GetCustomAttribute(t, tRemAtt);

Console.Write(Remark: );
Console.WriteLine(ra.remark);

Console.Write(Supplement: );
Console.WriteLine(ra.supplement);
Console.WriteLine(Priority: + ra.priority);
BLM 17: ALIMA ZAMANI TP TANIMLAMASI, YANSIMA VE NTELKLER

HERKES N C#
509
}
}
Programn kts yledir:
Attributes in UseAttrib: RemarkAttrbute
Remark: This class uses an attribute.
Supplement: This is additional info.
Priority: 10
Programn ilgin bir yn vardr. Dikkat ederseniz, UseAttribden nce belirtilen nitelik
aada gsterilmitir:
[RemarkAttribute(This class uses an attribute.,
supplement = Tnis is additional info.,
priority = 10)]
simlendirilmi nitelikler supplement ve priority zel bir ekilde sralanmamtr. Bu
atamalarn sras, nitelikte herhangi bir deiiklie yol amadan deitirilebilir.
Standart Niteliklerin Kullanm
C#ta standart nitelik tanmlanmtr: AttributeUsage, Conditional ve Obsolete.
Bu blmde sz konusu nitelikleri incelemekteyiz.
AttributeUsage
Daha nce de deinildii gibi, AttributeUsage nitelii, bir niteliin hangi elere
uygulanabildiini belirler. AttributeUsage, System.AttributeUsageAttribute
snfnn baka bir addr. AttributeUsagen yaplandrcs aadaki gibidir:
AttributeUsage(AttributeTargets e)
Burada e, niteliin zerinde kullanlabilecei e ya da eleri belirler.
AttributeTargets, aadaki deerleri tanmlayan bir numaralandrmadr:
All Assembly Class Constructor
Delegate Enum Event Field
Interface Method Module Parameter
Property ReturnValue Struct
Bu deerlerden iki ya da daha fazlasna VEYA uygulanabilir. rnein, sadece alan ve
zelliklere uygulanabilecek bir nitelik belirtmek iin unu kullann:
AttributeTargets.Field | AttributeTargets.Property
AttributeUsage iki isimlendirilmi parametreyi desteklemektedir. Bunlardan ilki bir
bool deeri olan AllowMultipledr. kincisi ise yine bir bool deeri olan Inheriteddir.
Eer bu deer true ise nitelik, tretilmi snflar tarafndan kaltm yoluyla alnr. Aksi halde,

HERKES N C#
KISIM I C# DL

510
kaltm yoluyla alnmaz. Hem AllowMultiple hem de Inheritedin varsaylan deerleri
false olur.
Conditional Nitelii
Conditional belki de C#n en ilgin standart niteliidir ve koullu metotlar (conditional
method) oluturmanz salar. Koullu bir metot, yalnzca spesifik bir sembol #define ile
tanmland zaman arlr. Aksi halde metot pas geilir. Dolaysyla, koullu bir metot, #if
ile yaplan koullu derlemeye bir alternatif sunmaktadr.
Conditional, System.Diagnostics.ConditionalAttributen baka bir addr.
Conditional niteliini kullanmak iin System.Diagnostics isim uzayn kullanmalsnz.
Bir rnekle balayalm:
// Conditional niteligini gosterir.

#define TRIAL

using System;
using System.Diagnostics;

class Test {

[Conditional(TRIAL)]
void trial() {
Console.WriteLine(Trial version, not for distribution.);
}

[Conditional(RELEASE)]
void release() {
Console.WriteLine(Final release version.);
}

public static void Main() {
Test t = new Test();

t.trial(); // yalnizca TRIAL tanimliysa cagrilir
t.release(); // yalnizca RELEASE tanimliysa cagrilir
}
}
Programn kts u ekildedir:
Trial version, not for distribution.
Neden bu ktnn retildiini anlamak iin programa daha yakndan bakalm. ncelikle,
programn TRIAL simgesini tanmladna dikkat edin. Ardndan trial() ve release()
metotlarnn nasl kodlandn gzleyin. Her ikisinden nce Conditional nitelii yer
almaktadr ve bu nitelik aadaki genel biime sahiptir:
[Conditional sembol]
BLM 17: ALIMA ZAMANI TP TANIMLAMASI, YANSIMA VE NTELKLER

HERKES N C#
511
Burada sembol, metodun altrlp altrlmayacan belirleyen semboldr. Bu nitelik
yalnzca metotlar zerinde kullanlabilir. Eer sembol tanmlanmsa, metot arldnda
alacaktr. Eer sembol tanmlanmamsa, metot almayacaktr.
Main()in iinde hem trial() hem de release() arlmaktadr. Ancak sadece
TRIAL tanmlanmtr. Bu nedenle trial() almaktadr. release()e yaplan ar gz
ard edilmektedir. RELEASE tanmlanrsa, o zaman release() da arlacaktr. TRIALn
tanm kaldrlrsa, trial() arlmayacaktr.
Koullu metotlarla ilgili baz kstlamalar vardr. Bu metotlarn void dndrmeleri
gereklidir. Bir arayzn deil bir snfn yesi olmaldrlar. nlerine override anahtar
kelimesi gelemez.
Obsolete Nitelii
System.ObsoleteAttributen ksa biimi olan Obsolete nitelii, bir program
esini eski olarak iaretlemenize olanak salar. Bu niteliin genel biimi aadaki gibidir:
[Obsolete(mesaj)]
Burada, ilgili program esi derlenirken mesaj ekrana gelmektedir. te, ksa bir rnek
// Obsolete niteligini gosterir.

using System;

class Test {

[Obsolete(Use myMeth2, instead.)]
static int myMeth(int a, int b) {
return a / b;
}

// myMethin gelistirilmis versiyonu.
static int myMeth2(int a, int b) {
return b == 0 ? 0 : a / b;
}

public static void Main() {
// bunun icin uyari mesaji verilir
Console.WriteLine(4 / 3 is + Test.myMeth(4, 3));

// burada uyari yapilmaz
Console.WriteLine(4 / 3 is + Test.myMeth2(4, 3));
}
}
Program derlenirken Main()de myMeth()e yaplan ar ile karlaldnda bir uyar
mesaj verilerek kullancnn bu metot yerine myMeth2()yi kullanmas istenecektir.
Obsoletein ikinci bir ekli yledir:

HERKES N C#
KISIM I C# DL

512
[Obsolete(mesaj, hata)]
Burada hata, bir Boolean deerdir. Eer true ise, eski enin kullanm uyar vermek
yerine derleme hatasna neden olacaktr. Aradaki fark elbette, hatal bir programn derlenerek
altrlabilir hale getirilmesine imkan vermemesidir.



O N S E K Z N C B L M


EMNYETSZ KOD,
ARETLER VE
ETL KONULAR



















18

HERKES N C#
KISIM I C# DL

514
Bu blmde, ismi genellikle kullanclar arasnda aknlkla karlanan bir C# zellii
ilenmektedir: Emniyetsiz kod. Emniyetsiz kod (unsafe code) genellikle iaretilerin
kullanmn ierir. Emniyetsiz kod ile iaretiler birlikte, normalde C++ ile
ilikilendirebileceiniz uygulamalar oluturmak amacyla C#n kullanlmasn mmkn
klmaktadrlar: Yksek performansa sahip sistem kodu. stelik, emniyetsiz kod ve iaretilerin
C#a dahil edilmesi, Javada olmayan becerileri C#a vermektedir.
Bu blmn sonunda, nceki blmlerde ilenmeyen birka anahtar kelime ele alnmakta-
dr.
Emniyetsiz Kod
C#, emniyetsiz kod olarak adlandrlan kodlar yazmanza olanak tanr. Bu ifade ok
edici gibi grnyor olsa da aslnda deildir. Emniyetsiz kod, kt yazlm kod demek
deildir; dorudan Common Language Runtimen (CLR) ynetiminde altrlmayan kod
demektir. Blm 1de akland gibi, C# normal olarak kontrol altnda kod oluturmak iin
kullanlmaktadr. Yine de, dorudan CLRn kontrol altnda almayan kod yazmak da
mmkndr. Bu kontrol altnda olmayan kod, kontrol altnda olan kodun tabi olduu denetim
ve kstlamalara tabi deildir; bu nedenle, buna emniyetsiz denir, nk bu tr bir kodun bir
tr zararl faaliyette bulunmayacan dorulamak mmkn deildir. Bylece, emniyetsiz
terimi, sz konusu kodun yaps gerei kusurlu olduu anlamna gelmez. Bu yalnzca, kontrol
altndaki kod erevesinde, sz konusu kodun denetime tabi olmayan faaliyetlerde bulunmas
mmkn demektir.
Emniyetsiz kodun problemlere neden olabilecei biliniyorsa, kikinin bu tr bir kodu neden
isteyebileceini sorabilirsiniz. Bu sorunun yant udur: Kontrol altndaki kod iareti (pointer)
kullanmn nler. C ya da C++a ainaysanz, iaretilerin dier nesnelerin adreslerini tutan
deikenler olduklarn bilirsiniz. Yani, iaretiler bir para C#taki referanslar gibidir. kisi
arasndaki temel fark, bir iaretinin bellekte herhangi bir yere iaret edebileceidir; bir refe-
rans ise daima kendi tipinde bir nesneye iaret eder. Bir iareti bellekte herhangi bir yere iaret
edebilecei iin, iaretileri hatal kullanmak mmkndr. Ayrca, iaretilerin kullanm
srasnda kodlama hatas yapmak da kolaydr. Kontrol altnda kod oluturulurken C#n
iaretileri desteklememesinin nedeni budur. Halbuki iaretiler, baz programlama trleri (sz
gelii, sistem dzeyinde yardmc programlar) iin hem kullanl hem de gereklidir. C#
iaretileri oluturmanza ve kullanmanza kesinlikle olanak tanr. Tm iareti ilemleri
gvensiz olarak iaretlenmelidir, nk bunlar kontrol altndaki kod kapsam dnda
gereklenmektedirler.
C#ta iaretilerin deklarasyonu ve kullanm C/C++taki ile paralellik gsterir - C/C++ta
iaretilerin nasl kullanldn biliyorsanz, bunlar C#ta kullanabilirsiniz. Ancak, C#n
dayand asl konu kontrol altndaki kodlarn oluturulmasdr. C#n kontrol altnda olmayan
kodlar destekleme becerisi, C#n zel bir dizi probleme uygulanmasna imkan vermektedir.
Bu, normal C# programlama iin geerli deildir. Aslnda, kontrol altnda olmayan kodu
derlemek iin /unsafe derleyici seeneini kullanmalsnz.
BLM 18: EMNYETSZ KOD, ARETLER VE ETL KONULAR

HERKES N C#
515
aretiler emniyetsiz kodun ekirdeinde yer aldklar iin bunlarla balayacaz.
aretilerin Esaslar
aretiler, dier deikenlerin adreslerini tutan deikenlerdir. rnein, eer x, ynin
adresini ieriyorsa; x, yye iaret ediyor denilir. Bir iareti bir kez bir deikene iaret
ettikten sonra, artk bu deikenin deeri iareti araclyla elde edilebilir ya da
deitirilebilir. aretiler araclyla gerekletirilen ilemler genellikle dolayllk (indirection)
olarak adlandrlr.
areti Deklare Etmek
areti deikenleri u ekilde deklare edilmelidir. Bir iareti deikeninin genel biimi
yledir:
tip* deiken-ismi;
Burada tip, deikenin temel tipidir. tip, referans tipi olmamaldr. Bu nedenle, bir snf
nesnesine iaret eden bir iareti deklare edemezsiniz. aretinin temel tipi ayrca iaretinin
kast edilen (referent) tipi olarak da kullanlr. * simgesinin yerine dikkat edin. Bu iaret, tip
isminin peinden gelmektedir. deiken-ismi, iareti deikeninin ismidir.
te bir rnek. Bir inte iaret eden ip adnda bir iareti deklare etmek iin u
deklarasyonu kullann:
int* ip;
Bir float iareti iin unu kullann:
float* fp;
Genel olarak, bir deklarasyon ifadesinde bir tip isminin ardndan * simgesini kullanmak bir
iareti tipi oluturur.
Bir iaretinin iaret edecei verinin tipi, iaretinin temel tipi ile belirlenir. Bylece,
nceki rnekte ip, bir inte iaret etmek iin; fp ise bir floata iaret etmek iin
kullanlabilir. Bununla birlikte, bir iaretinin baka bir yere iaret etmesini gerekten
nleyecek hibir ey olmadn anlayn. aretilerin potansiyel olarak gvenli olmamalarnn
sebebi budur.
Eer C/C++ biliyorsanz, C# ve C/C++n iaretileri deklare etme biimleri arasndaki
nemli bir farkn farknda olmanz gerekir. C/C++ta bir iareti tipi deklare edince *,
deklarasyondaki deikenler listesi zerinde dalamaz. Yani, C/C++ta u ifade
int* p, q;
p adnda bir int iareti ve q adnda bir int deklare eder. Bu ifade, aadaki iki deklaras-
yona denktir:

HERKES N C#
KISIM I C# DL

516
int* p;
int q;
Ancak, C#ta *, dalma zelliine sahiptir ve ayn deklarasyon iki iareti deikeni
oluturur:
int* p, q;
Yani, C#ta bu ifade aadaki iki deklarasyonla ayndr:
int* P;
int* q;
Bu, C/C++ kodunu C#a tarken aklnzda tutmanz gereken nemli bir farktr.
* ve & areti Operatrleri
aretilerle birlikte iki operatr kullanlr: * ve &. &, operandnn bellek adresini dndren
tekli bir operatrdr. (Tekli operatrlerin yalnzca tek operand gerektirdiklerini hatrlayn.)
rnein,
int* ip;
int num = 10;

ip = &num;
num deikeninin adresini ipye yerletirir. Bu adres, deikenin bilgisayarn dahili
belleindeki konumudur. Bunun numn deeri ile bir ilikisi yoktur. Yani, ip 10 deerini
(numn ilk deeri) iermez. numn sakland adresi ierir. & ilemi, nnde yer ald
deikenin adresini dndrmek olarak hatrtanabilir. Bu yzden, yukardaki atama ifadesi
ip, numn adresini alr olarak kelimelere dklebilir.
* ise ikinci operatrdr ve bu, & operatrnn tamamlaycsdr. *, operand tarafndan
belirtilen adresteki deikenin deerine referansta bulunan tekli bir operatrdr. Yani, bir
iareti tarafndan iaret edilen bir deikenin deerine referansta bulunur. Ayn rnekle devam
edersek, eer ip, numn bellek adresini ieriyorsa,
int val = *ip;
vala 10 deerini yerletirecektir. 10, ip tarafndan iaret edilen numn deeridir. *
ilemi adresindeki olarak hatrlanabilir. Bu rnekte, yukardaki ifade val, ip adresindeki
deeri alr eklinde okunabilir.
*, bir atama ifadesinin sol tarafnda da kullanlabilir. Bu tr bir kullanm, iareti
tarafndan iaret edilen deeri ayarlar. rnein:
*ip = 100;
ip tarafndan iaret edilen deikene - bu rnekte bu numdr - 100 deerini atar. Yani, bu
ifade ip adresine 100 deerini koy eklinde okunabilir.
BLM 18: EMNYETSZ KOD, ARETLER VE ETL KONULAR

HERKES N C#
517
unsafe Kullanm
aretileri kullanan herhangi bir kod, unsafe anahtar kelimesi kullanlarak emniyetsiz
olarak iaretlenmelidir. Tek bir ifadeyi ya da btn bir metodu unsafe olarak
iaretleyebilirsiniz. rnein, unsafe olarak iaretlenmi Main() iinde iaretileri kullanan
bir program aada yer almaktadr:
// Isaretcileri ve unsafe kullanimini goster.

using System;

class UnsafeCode {
// Maini unsafe olarak isaretle.
unsafe public static void Main() {
int count = 99;
int* p; // bir int isaretci olustur

p = &count; // countun adresini pye koy

Console.WriteLine(Initial value of count is + *p);

*p = 10; // p uzerinden counta 10 degerini ata

Console.WriteLine(New value of count is + *p);
}
}
Bu programn kts aada gsterilmitir:
Initial value of count is 99
New value of count is 10
fixed Kullanm
aretilerle alrken fixed niteleyicisi ska kullanlr. fixed, kontrol altndaki bir
deikenin anlamsz veri toplaycs (garbage collector) tarafndan tanmasm nler. Bir
iareti, rnein, bir snf nesnesi iindeki bir alana referansta bulunurken bu gereklidir.
areti, anlamsz veri toplaycsnn faaliyetlerinden haberdar olmad iin, sz konusu nesne
tanrsa iareti yanl nesneye iaret ediyor olacaktr. fixedin kullanm genel olarak u
ekildedir:
fixed (tip* p = &deiken) {
// sabit nesne kullanr
}
Burada p, kendisine bir deikenin adresi atanmakta olan bir iaretidir. Kod blou
gereklenene kadar nesne bellekteki mevcut konumunda kalacaktr. Bir fixed ifadenin
hedefi olarak tek bir ifadede de kullanabilirsiniz. fixed anahtar kelimesi ayrca emniyetsiz kod
kapsamnda da kullanlabilir. Virglle ayrlm bir liste kullanarak ayn anda birden fazla
fixed iareti deklare edebilirsiniz.

HERKES N C#
KISIM I C# DL

518
te fixed kullanlan bir program rnei:
// fixed kullanimini gosterir.

using System;

class Test {
public int num;
public Test(int i) { num = i; }
}

class FixedCode {
// Maini unsafe olarak isaretle.
unsafe public static void Main() {
Test o = new Test(19);

fixed (int* p = &o,num) { // o.numin adresini pye
// yerlestirmek icin fixed kullan

Console.WriteLine(Initial value of o.num is + *p);

*p = 10; // p uzerinden counta atama yap
Console.WriteLine(New value of o.num is + *p);
}
}
}
Bu programn kts aada gsterilmitir:
Initial value of o.num is 19
New value of o.num is 10
Burada fixed, onun tanmasna engel olur. p, o.numa iaret ettii iin, o tanmsa p
geersiz bir konuma iaret ediyor olacaktr.
Yap yelerine Bir areti Araclyla Erimek
Bir yap, referans tipleri iermedii srece, bir iareti sz konusu yap tipinde bir nesneye
iaret edebilir. Bir yapnn yesine bir iareti araclyla eriirken nokta (.) operatr yerine
ok (->) operatrn kullanmalsnz. rnein, aadaki yapnn mevcut olduunu varsayarsak,
struct MyStruct {
public int x;
public int y;
public int sum() { return x + y; }
}
bu yapnn yelerine bir iareti araclyla u ekilde eriebilirsiniz:
MyStruct o = new MyStruct();
MyStruct* p; // bir isaretci deklare et

p = &o;
p->x = 10;
BLM 18: EMNYETSZ KOD, ARETLER VE ETL KONULAR

HERKES N C#
519
p->y = 20;

Console.WriteLine(Sum is + p-sum());
areti Aritmetii
aretiler zerinde kullanlabilecek yalnzca drt aritmetik operatr mevcuttur: ++, --, +
ve -. areti aritmetiinin nasl uygulandn anlamak iin bir rnekle balayacaz. p1,
mevcut deeri 2000 olan bir int iaretisi olsun (yani, p1 2000 adresini iersin). u deyimden
sonra
pi++;
p1in ierii 2001 deil 2004 olacaktr! Bunun nedeni, p1in her artrmada bir sonraki
inte iaret edecek olmasdr. C#ta tamsaylar 4 byte uzunluunda olduu iin p1i bir kez
artrmak deerine 4 ekler. Bunun tersi de eksiltmeler iin geerlidir. Her eksiltme p1in
deerini 4 azaltr. rnein,
pi--;
p1in bir nceki deerinin 2000 olduunu varsayarsak, bu ifade p1in 1996 deerine
sahip olmasna neden olacaktr.
Yukardaki rnei genelletirecek olursak, bir iaretinin her artrmasnda sz konusu
iareti, kendi temel tipindeki bir sonraki elemann bellek konumuna iaret edecektir.
aretinin her eksiltiliinde ise kendi temel tipindeki bir nceki elemann konumuna iaret
edecektir.
areti aritmetii yalnzca artrma ve eksiltme ilemleriyle snrl deildir. aretilere
ayrca tamsay ekleyebilir ya da iaretilerden tamsay karabilirsiniz. Aadaki deyim,
p1 = p1 + 9;
p1in halihazrda iaret ettii elemandan sonraki (kendi tipindeki) 9. eleman gstermesini
salar.
aretileri birbiriyle toplayamyor olmanza ramen, bir iaretiyi bir dierinden (her ikisi-
nin de ayn temel tipte olmas artyla) karabilirsiniz. Kalan, her iki iareti arasnda kalan te-
mel tipteki elemanlarn saysdr.
Bir iaretinin bir tamsay ile toplanmas, bir iaretiden bir tamsay kartlmas ya da iki
iaretinin birbirinden kartlmas ilemlerinin haricinde iaretiler zerinde baka hi bir arit-
metik ilem gerekletirilemez. rnein, iaretilere float ya da double deerler
ekleyemezsiniz veya iaretilerden bu deerleri kartamazsnz.
areti aritmetiinin etkilerini grmek iin bir sonraki ksa program altrn. Program,
bir tamsay iaretisi (ip) ile bir kayan nokta iaretisinin (fp) gsterdii asl fiziksel adresleri

HERKES N C#
KISIM I C# DL

520
yazdrr. Dngnn her tekrarnda her iki iaretinin kendi temel tiplerine bal olarak nasl
deitiklerini gzleyin.
// Isaretci aritmetiginin etkilerini gosterir.

using System;

class PtrArithDemo {
unsafe public static void Main() {
int x;
int i;
double d;

int* ip = &i;
double* fp = &d;

Console.WriteLine(int double\n);

for(x = 0; x < 10; x++) {
Console.WriteLine((uint) (ip) + + (uint) (fp));
ip++;
fp++;
}
}
}
rnek kt aada gsterilmitir. Sizin ktnz farkl olabilir, ancak aralklar ayn
olacaktr.
int double
1243464 1243468
1243468 1243476
1243472 1243484
1243476 1243492
1243480 1243500
1243484 1243508
1243488 1243516
1243492 1243524
1243496 1343532
1243500 1243540
ktdan da grld gibi iareti aritmetii, iaretinin temel tipine bal olarak
gerekletirilir. Bir int 4 byte ve bir double 8 byte olduu iin adresler, bu deerlerin katlar
olarak deiir.
aretilerin Karlatrlmas
aretiler, == , < ve > gibi ilikisel operatrler kullanlarak karlatrabilir. Ancak
iaretilerin karlatrlmasyla elde edilen sonucun anlaml olmas iin, genellikle sz konusu
iki iaretinin kendi aralarnda bir iliki olmas gereklidir. rnein, p1 ve p2 eer birbirinden
ayr ve ilgisiz iki deikene iaret ediyorlarsa, p1 ve p2 arasndaki herhangi bir karlatrma
BLM 18: EMNYETSZ KOD, ARETLER VE ETL KONULAR

HERKES N C#
521
genellikle anlamsz olacaktr. Ancak, eer p1 ve p2, sz gelii ayn dizinin elemanlar gibi
birbiriyle balantl deikenlere iaret ediyorlarsa, anlaml bir ekilde karlatrlabilirler.
te, bir dizinin ortasndaki eleman bulmak iin iaretilerin karlatrlmasn kullanan
bir rnek:
// Isaretcilerin karsilastirilmasini gosterir.

using System;

class PtrCompDemo {
unsafe public static void Main() {

int[] nums = new int[11];
int x;

// ortadakini bul
fixed (int* start = &nums[0]) {
fixed(int* end = &nums[nums.Length-1]) {
for(x = 0; start + x <= end - x; x++);
}
}
Console.WriteLine(Middle element is + x);
}
}
kt yledir:
Middle element is 6
Bu program, start balangta dizinin ilk elemann, endi de son elemann gsterecek
ekilde ayarlayarak dizinin ortasndaki eleman bulur. Sonra, iareti aritmetii kullanlarak
start iaretisi artrlr ve start, ende eit ya da endden kk olana kadar end iaretisi
azaltlr.
Bir dier husus da udur: start ve end iaretileri bir fixed ifadesi iinde
oluturulmaldrlar, nk bu iaretiler, kendisi bir referans tipi olan bir dizinin elemanlarna
iaret ederler. C#ta dizilerin nesneler olarak uygulandklarn ve anlamsz veri toplaycs
(garbage collector) tarafndan tanabileceini hatrlayn.
aretiler ve Diziler
C#ta iaretiler ve diziler birbiriyle balantldr. rnein, indekssiz bir dizi ismi, dizinin
balangcna bir iareti retir. Aadaki program ele aln:
/* Indekssiz bir dizi ismi, dizinin baslangicina bir isaretci
uretir. */

using System;

class PtrArray {

HERKES N C#
KISIM I C# DL

522
unsafe public static void Main() {
int[] nums = new int[10];

fixed(int* p = &nums[0], p2 = nums) {
if(p == p2)
Console.WritetLine(p and p2 point to same address.);
}
}
}
kt aada gsterilmitir:
p and p2 point to same address.
ktdan da grld gibi, aadaki deyim
&nums[0]
ununla ayndr:
nums
kinci kullanm daha ksa olduu iin, bir dizinin balangcn gsteren bir iaretiye gerek
olduunda programclarn birou bunu kullanrlar.
aretiyi ndekslemek
Bir iareti bir diziye referansta bulununca sz konusu iareti sanki bir diziymi gibi
indekslenebilir. Bu sz dizimi, baz durumlarda ok daha kullanl olabilen bir iareti
aritmetiine alternatif salar. te bir rnek:
// Bir isaretciyi sanki bir diziymis gibi indeksler.

using System;

class PtrIndexDemo {
unsafe public static void Main() {
int[] nums = new int[10];

// isaretciyi indeksle
Console.WriteLine(Index pointer like array.);
fixed (int* p = nums) {
for(int i = 0; i < 10; i++)
p[i] = i; // isaretciyi tipki dizi gibi indeksle

for(int i = 0; i < 10; i++)
Console.WriteLine(p[{0}]: {1} , i, p[i]);
}

// isaretci aritmetigi kullan.
Console.WriteLine(\nUse pointer arithmetic.);
fixed (int* p = nums) {
for(int i=0; i < 10; i++)
*(p+i) = i; // isaretci aritmetigi kullan.
BLM 18: EMNYETSZ KOD, ARETLER VE ETL KONULAR

HERKES N C#
523

for(int i = 0; i < 10; i++)
Console.WriteLine(*(p+{0}): {1} , i, *(p+i));
}
}
}
kt aada gsterilmitir:
Index pointer like array.
p[0]: 0
p[1]: 1
p[2]: 2
p[3]: 3
p[4]: 4
p[5]: 5
p[6]: 6
p[7]: 7
p[8]: 8
p[9]: 9

Use pointer arithmetic.
*(p+0): 0
*(p+1): 1
*(p+2): 2
*(p+3): 3
*(p+4): 4
*(p+5): 5
*(p+6): 6
*(p+7): 7
*(p+8): 8
*(p+9): 9
Programda da gsterildii gibi, aadaki gibi genel biimde olan bir iareti deyimi
*(ptr + i)
u tr bir dizi indeksleme sz dizimi kullanlarak yeniden yazlabilir:
ptr[i]
Bir iareti indekslemekle ilgili anlalmas gereken iki nemli husus mevcuttur: ncelikle,
dizi snrlar kontrol edilmez. Bylece, iaretinin referansta bulunduu dizinin sonundan
ileride bulunan bir elemana erimek mmkndr. kincisi, iaretilerin Length zellii yoktur.
Bu nedenle, iareti kullanldnda dizinin ne kadar uzunlukta olduunu bilmenin bir yolu
yoktur.
aretiler ve Karakter Katarlar
Karakter katarlar C#ta nesneler olarak uygulansalar da, bir karakter katar iindeki
karakterlere bir iareti araclyla da erimek mmkndr. Bunun iin karakter katarnn

HERKES N C#
KISIM I C# DL

524
ban gsteren bir iaretiyi aadaki gibi bir fixed ifade kullanarak bir char* iareti
olarak atayacaksnz:
fixed(char* p = str) { // ...
fixed ifade altrldktan sonra p, karakter katarn oluturan karakter dizisinin bana
iaret edecektir. Bu dizi null sonlandrlmaldr; yani, dizinin sonunda 0 vardr. Dizinin sonunu
test etmek iin bu gerei kullanabilirsiniz. Karakter katarlar C/C++ta da null sonlandrmal
karakter dizileri eklinde uygulanrlar. Bylece, bir stringe iaret eden bir char* iaretisi
edinmek, karakter katarlar zerinde C/C++takine ok benzer ekilde ilem yapmanza olanak
tanr.
te, bir karakter katarna bir char* iaretisi araclyla eriimi gsteren bir program:
// Bir karakter katarinin basini gosteren bir isareti edinmek
// icin fixed kullanir.

using System;

class FixedString {
unsafe public static void Main() {
string str = this is a test;

// p, strin basina isaret etsin
fixed(char* p = str) {

// strin icerigini p uzerinden goruntule.
for(int i = 0; p[i] != 0; i++)
Console.Write(p[i]);
}

Console.WriteLine();
}
}
kt aada gsterilmitir:
this is a test
oklu Dolayllk
Hedef deere iaret eden iaretiye iaret eden bir baka iaretiye sahip olabilirsiniz. Bu
durum, oklu dolayllk (multiple indirection) ya da iaretilere iaret eden iaretiler olarak
adlandrlr. aretilere iaret eden iaretiler kark grnebilir. ekil 18.1, oklu dolayllk
kavramn netletirmeye yardmc olmaktadr. Grdnz gibi, normal bir iaretinin deeri,
denilen deeri ieren deikenin adresidir. Br iaretiye iaret eden baka bir iareti
durumunda, ilk iareti ikinci iaretinin adresini ierir. kinci iareti ise, istenilen deeri
ieren deikene iaret eder.
BLM 18: EMNYETSZ KOD, ARETLER VE ETL KONULAR

HERKES N C#
525
oklu dolayllk istenilen seviyeye kadar uzatlabilir; fakat bir iaretiye iaret eden ikinci
bir iaretiden daha fazlasna ok ender olarak gerek duyulur. Aslnda, ar dolayll takip et-
mesi zordur ve bu, kavramsal hatalara aktr.
Baka bir iaretiye iaret eden bir iareti niteliindeki bir deiken u ekilde deklare
edilmelidir. Bunu, tip isminden sonra ilave bir * yerletirerek gerekletirirsiniz. rnein,
aadaki deklarasyon derleyiciye qnun int tipinde bir iaretiye iaret eden bir iareti
olduunu bildirmektedir:
int** q;
qnun bir tamsayya iaret eden bir iareti olmadn kavramalsnz. Bunun yerine q, bir
int iaretiye iaret eden bir iaretidir,
Bir iaretiye iaret eden baka bir iareti tarafndan, iaret edilen hedef deere erimek
iin * operatrn aadaki rnekteki gibi iki kez uygulamalsnz:
using System;
class MultipleIndirect {
unsafe public static void Main() {
int x; // bir int degeri tutar
int* p; // bir int isaretcisi tutar
int** q; // bir int isaretcisine isaret eden bir isaretci
// tutar
x = 10;
p = &x; // xin adresini pye yerlestir
q = &p; // pnin adresini qya yerlestir
Console.WriteLine(**q); // xin degerini goster
}
}
kt, xin deeri olan 10dur. Programda p, bir inte iaret eden bir iareti olarak; q ise
bir int iaretiye iaret eden bir iareti olarak deklare edilmitir.
Son bir husus: oklu dolayll, sz gelii bal listeler gibi iareti kullanan yksek
dzeyli veri yaplaryla kartrmamalsnz. Bunlar temel olarak farkl iki kavramdr.

areti Deiken
adres deer
Tekli dolayllk
areti areti Deiken
adres adres deer
oklu Dolayllk
EKL 18.1: Tekli ve oklu dolayllk

HERKES N C#
KISIM I C# DL

526
areti Dizileri
aretiler de dier veri tipleri gibi diziye yerletirilebilirler. 3 elemanl bir int iareti
dizisinin deklarasyonu u ekildedir:
int * [] ptrs = new int * [3];
var adnda bir int deikeninin adresini iareti dizisinin nc elemanna atamak iin
yle yazn:
ptrs[2] = &var;
varn deerini bulmak iin yle yazn:
*ptrs[2]
eitli Anahtar Kelimeler
Ksm 1i noktalamadan nce, baka hi bir yerde bahsedilmemi olan C#ta tanml kalan
birka anahtar kelime ksaca ele alnacaktr.
sizeof
Arada srada, C#n deer tiplerinden birinin bykln byte cinsinden bilmek sizin iin
yararl olabilir. Bu bilgiyi elde elmek iin sizeof operatrn kullann. Bu operatr genel
olarak u ekildedir:
sizeof(tip)
Burada tip, bykl elde edilmekte olan tiptir. sizeof operatr yalnzca emniyetsiz
kod iinde kullanlabilir. Yani, sizeof operatr esasen zel durumlarda, zellikle kontrol
altnda olan ve olmayan kodlarn bir harman ile alrken kullanlmak zere tasarlanmtr.
lock
lock anahtar kelimesi, oklu kanall (multiple threads) programlarla alrken kullanlr.
C#ta bir program, iki ya da daha fazla alma kanal (threads of execution) ierebilir. Byle
bir durum sz konusu olunca, programn paralar ok grevli (multitasked) olur Yani,
programn paralar birbirinden bamsz olarak ve kavramsal olarak ifade edersek, ezamanl
olarak alr. Bu durum zel bir problem tipinin ortaya kma olasln artrr: Bir kerede
yalnzca tek bir kanal tarafndan kullanlabilen bir kaynak, iki kanal tarafndan kullanlmaya
allrsa ne olur? Bu problemin zm iin, bir kerede sadece ve sadece tek bir kanal
tarafndan altrlacak olan bir kritik kod blm (critical code section) tanmlayabilirsiniz.
Bu, lock ile gerekletirilir. Genel olarak lockun kullanm yledir:
lock(nesne) {
// kritik blm
}
BLM 18: EMNYETSZ KOD, ARETLER VE ETL KONULAR

HERKES N C#
527
Burada nesne, kilidi (lock) yakalamaya alan nesnedir. Eer kanallardan biri nceden
kritik blme girmise, ikinci kanal ilk kanal almana kadar bekleyecektir. Kilit kabul edilince,
kritik blm altrlabilir. (Ek ayrntlar iin Blm 21e bakn.)
readonly
Bir snf iindeki bir alan readonly olarak deklare ederek salt okunur bir alan
oluturabilirsiniz. Bir readonly alana ilk deer atanabilir, fakat bu deer daha sonra
deitirilemez. Bylece, readonly alanlar, program boyunca kullanlan sabitleri, sz gelii
dizi boyutlarn tanmlamak iin iyi bir yoldur. Statik ve statik olmayan readonly alanlar
tanmlamak mmkndr.
te, readonly bir alan oluturan bir rnek:
// readonly kullanimini gosterir.

using System;

class MyClass {
public static readonly int SIZE = 10;
}

class DemoReadOnly {
public static void Main() {
int[]nums = new int[MyClass.SIZE];

for(int i = 0; i < MyClass.SIZE; i++)
nums[i] = i;

foreach(int i in nums)
Console.Write(i + );

// MyClass.SIZE = 100; // Hata!!! Degistirilemez
}
}
Burada MyClass.SIZEa ilk deer olarak 10 atanmaktadr. Bundan sonra, bu deer
kullanlabilir ama deitirilemez. Bunu kantlamak iin son satrdaki aklama simgelerini
kaldrmay ve sonra program yeniden derlemeyi deneyin. Bir hatann ortaya ktn
greceksiniz.
stackalloc
stackalloc kullanarak yndan bellek alan ayrabilirsiniz, stackalloc yalnzca yerel
deikenlere ilk deer atanrken kullanlabilir. Genel olarak kullanm u ekildedir:
tip *p = stackalloc tip[byklk]
Burada p, tip tipinde nesnelerin byklk adedini tutabilecek kadar byk olan bellein
adresini alan bir iaretidir. stackalloc, emniyetsiz kod kapsamnda kullanlmaldr.

HERKES N C#
KISIM I C# DL

528
Normal olarak, nesneler iin gerekli bellek alan, katmandan (heap) ayrlr. Katman, bo
bellek alandr. Bellek alann yndan ayrmak bir istisnadr. Yndan bellek alan ayrlan
deikenler, anlamsz verilerin toplanmas ilemine tabi tutulmazlar. Bunun yerine, bu
deikenler, deklare edildikleri blok alt srece varlklarn srdrrler. Blok terk edilince,
ilgili bellek alan serbest braklr. stackalloc kullanmann bir avantaj olarak, anlamsz veri
toplaycs tarafndan tanan bellei dert etmenize gerek yoktur.
te, stackalloc kullanan bir rnek:
// stackalloc kullanimini gosterir.
using System;

class UseStackAlloc {
unsafe public static void Main() {
int* ptrs = stackalloc int[3];

ptrs[0] = 1;
ptrs[1] = 2;
ptrs[2] = 3;

for(int i = 0; i < 3; i++)
Console.WriteLine(ptrs[i]);
}
}
kt aada gsterilmitir:
1
2
3
using fadesi
nceden ele alnan using direktifine ek olarak usingin using ifadesi olarak
adlandrlan ikinci bir ekli daha mevcuttur. usingin kullanmlar genel olarak u ekildedir:
using (nesne) {
// nesneyi kullan
}

using (tip nesne = ilk-deer) {
// nesneyi kullan
}
Burada nesne, using blou iinde kullanlmakta olan nesnedir. lk biimde, sz konusu
nesne using ifadesinin dnda deklere edilmektedir. kinci biimde, nesne using ifadesinin
iinde deklare edilmektedir. Blok sona erdiinde, nesne zerinde Dispose() metodu
(System.IDisposable arayz tarafndan tanmlanmtr) arlacaktr. using ifadesi
yalnzca System.IDisposable arayzn gerekleyen nesnelere uygulanabilir.
te, using ifadesinin her iki biimini de kullanan bir rnek:
BLM 18: EMNYETSZ KOD, ARETLER VE ETL KONULAR

HERKES N C#
529
// using ifadesinin kullanimini gosterir.
using System;
using System.IO;

class UsingDemo {
public static void Main() {
StreamReader sr = new StreamReader(test.txt);

// using ifadesi icinde nesne kullan.
using(sr) {
Console.WriteLine(sr.ReadLine());
sr.Close();
}
// using ifadesi icinde StreamReader olustur.
using(StreamReader sr2 = new StreamReader(test.txt)) {
Console.WriteLine(sr2.ReadLine());
Sr2.Close();
}
}
}
StreamReader snf IDisposable arayzn (TextReader temel snf araclyla)
gereklemektedir. Bylece, StreamReader bir using ifadesinde kullanlabilir.
(IDisposable ile ilgili aklamalar iin Blm 24e bakn.)
const ve volatile
const niteleyicisi, deitirilemeyen alanlar ya da yerel deikenleri deklare etmek iin
kullanlr. Bu deikenlere ilk deerleri deikenler deklare edilirken verilmelidir. Bylece, bir
const deiken aslnda bir sabittir. rnein,
const int i = 10;
bu ifade, i adnda 10 deerine sahip bir const deiken oluturur.
volatile niteleyicisi, bir alann deerinin program tarafndan aka belirtilmeyen
yntemlerle deitirilebileceini derleyiciye bildirir. rnein, mevcut sistem zamann tutan bir
alan, iletim sistemi tarafndan otomatik olarak deitirilebilir. Bu durumda, sz konusu alann
ierii ak bir atama ifadesi olmadan deitirilir. Bir alann haricen deitirilmesi, nemli
olabilir. Bunun nedeni udur: Bir alan, bir atama ifadesinin sol tarafnda yer almyorsa sz
konusu alann ieriinin deimeden kalaca varsaymna dayanarak, C# derleyicisinin belirli
deyimleri otomatik olarak optimize etmesine izin verilmitir. Ancak, mevcut kodun dnda
kalan etmenler, sz gelii ikinci bir kanal sz konusu alann deerini deitirirse, bu varsaym
yanl olur. volatile kullanarak, bu alana ne zaman eriilse bu alann deerinin elde etmesi
gerektiini derleyiciye bildiriyorsunuz.



K N C K I S I M


C# KTPHANESN
KEFETMEK


Ksm IIde C# ktphanesi incelenmektedir. Ksm Ide
akland gibi, C# tarafndan kullanlan snf ktphanesi .NET
Framework ktphanesidir. Bu nedenle, bu blmde ilenen
konular yalnzca C#a uygulanmaz, ayn zamanda .NET
Frameworke de bir btn olarak uygulanr.
C# ktphanesi isim uzaylar eklinde dzenlenmitir.
Ktphanenin bir blmn kullanmak iin normal olarak karlk
gelen isim uzayn using direktifini de dahil ederek programnzn
iine aktarmalsnz. Elbette sz konusu enin ismini isim uzayyla
birlikte tam olarak nitelenmi biimde de kullanabilirsiniz, fakat
btn isim uzayn programa aktarmak genellikle ok daha kolaydr.
C# ktphanesi byktr ve bunun her parasn incelemek
elinizdeki kitabn kapsamnn dnda kalmaktadr. (Konunun
komple tanm, btn bir kitab kolaylkla doldururdu!) Bunun
yerine, Ksm IIde ktphanenin ekirdek elemanlar
incelenmektedir. Bu elemanlar System isim uzaynda bulunurlar.
Ayrca ele alnan konular, koleksiyon snflar, ok kanalllk
(multithreading) ve a oluturmadr (networking).
I/O snflar Blm 14te ele alnmtr.





II



O N D O K U Z U N C U B L M


SYSTEM SM UZAYI






















19

HERKES N C#
KISIM II C# KTPHANESN KEFETMEK

532
Bu blmde System isim uzay incelenmektedir. System, C# ktphanesinde yer alan en
st dzeydeki isim uzaydr. System, bir C# program tarafndan en yaygn olarak kullanlan
ya da dier bakmlardan .NET Frameworke btnleik zannedilen snf, yap, arayz, delege
ve numaralandrmalar dorudan ierir. Bu nedenle System, C# ktphanesinin ekirdeini
oluturur.
System ayrca System.Net gibi belirli alt sistemleri destekleyen birok kmelenmi isim
uzay da ierir. Bu alt sistemlerden birka elinizdeki kitabn ileriki sayfalarnda anlatlmtr.
Bu blm yalnzca Systemin kendi yelerine ayrlmtr.
Systemin yeleri
ok saydaki kural d durum snfna ek olarak System, aadaki snflar da ierir:
Activator AppDomain
AppDomainsetup Array
AssemblyLoadEventArgs Attribute
AttributeUsageAttribute BitConverter
Buffer CharEnumerator
CLSCompliantAttribute Console
ContextBoundObject ContextStaticAttribute
Convert DBNull
Delegate Enum
Environment EventArgs
Exception FlagsAttribute
GC LoaderOptimizationAttribute
LocalDataStoreSlot MarshalByRefObject
Math MTAThreadAttribute
MulticastDelegate NonSerializedAttribute
Object ObsoleteAttribute
OperstingSystem ParamArrayAttrAbute
Random ResolveEventArgs
SerializableAttribute STAThreadAttribute
String ThreadStaticAttribute
TimeZone Type
UnhandledExceptionEventArgs Uri
UriBuilder ValueType
Version WeakReference
System'da aadaki yaplar tanmldr:
ArgIterator Boolean
Byte Char
DateTime Decimal
Double Guid
Int16 Int32
Int64 IntPtr
RuntimeArgumentHandle RuntimeFieldHandle
RuntimeMethodHandle RuntimeTypeHandle
SByte Single
TimeSpan TypedReference
UInt16 UInt32
BLM 19: SYSTEM SM UZAYI

HERKES N C#
533
UInt64 UIntPtr
Void
System'da aadaki arayzler tanmldr:
IAppDomainSetup IAsyncResult
ICloneable IComparable
IConvertible ICustomFormatter
IDisposable IFormatProvider
IFormattable IserviceProvider
Systemda aadaki delegeler tanmldr:
AssemblyLoadEventHandler AsyncCallback
CrossAppDomainDelegate EventHandler
ResolveEventHandler UnhandledExceptionEventHandler
Systemda bu numaralandrmalar tanmldr:
AttributeTargets DayOfWeek
Environment.SpecialFolder LoaderOptimization
PlatformID TypeCode
UriHostNameType UriPartial
Yukardaki tabloda grld gibi, System olduka byktr. Tek bir blmde
Systemn tm bileenlerini ayrntl olarak incelemek mmkn deildir, stelik, Systemn
baz yeleri genel olarak .NET Frameworke uygulanabilir olsa da C# programclar tarafndan
ounlukla kullanlmazlar. Ayrca, Systemn birka snf, sz gelii Type, Exception ve
Attribute, Ksm Ide ya da bu kitabn eitli yerlerinde anlatlmtr. Son olarak, C#
string tipini tanmlayan System.String byk ve nemli bir konu olduu iin Blm
20de biimlendirme ile birlikle ilenmektedir. Bu nedenlerden tr, bu blmde yalnzca C#
programclar tarafndan en yaygn olarak kullanlan ve baka hi bir yerde ilenmeyen yeler
incelenmektedir.
Math Snf
Mathte standart matematik ilemlerinden birka tanmlanmaktadr. Sz gelii, karekk,
sins, kosins ve logaritmalar. Mathte tanml metotlar Tablo 19.lde gsterilmitir. Alarn
tm radyan cinsindendir. Mathte tanml tm metotlarn static olduuna dikkat edin. Bu
nedenle, bir Math nesnesi kurmaya gerek yoktur; stelik, ak Math yaplandrclar da
salanmaz.
Mathte ayrca aadaki iki alan da tanmlanmtr:
public const double E
public const double PI
E, genellikle e olarak bahsedilen doal logaritma tabannn deeridir. PI ise pi saysnn
deeridir.

HERKES N C#
KISIM II C# KTPHANESN KEFETMEK

534
Math snf mhrlenmitir; sealed niteliine sahiptir. Yani, kaltm yoluyla baka bir
snfa aktarlamaz.
TABLO 19.1: Math Tarafndan Tanmlanan Metotlar


Metot Anlam
public static double Abs(double v)
vnin mutlak deerini dndrr.
public static float Abs(float v)
vnin mutlak deerini dndrr.
public static int Abs(int v)
vnin mutlak deerini dndrr.
public static short Abs(short v)
vnin mutlak deerini dndrr.
public static long Abs(long v)
vnin mutlak deerini dndrr.
public static sbyte Abs(sbyte v)
vnin mutlak deerini dndrr.
public static double Abs(double v)
vnin mutlak deerini dndrr.
public static double Acos(double v)
vnin ters kosins deerini dndrr. vnin
deeri -1 ile 1 arasnda olmaldr.
public static double Asin(double v)
vnin ters sins deerini dndrr. vnin deeri
-1 ile 1 arasnda olmaldr.
public static double Atan(double v)
vnin ters tanjant deerini dndrr.
public static double Atan2(double y,
double x)
y/xin ters tanjant deerini dndrr.
public static double Ceiling(double v)
vden kk olmayan (kayan noktal deer
olarak simgelenen) en kk tamsayy
dndrr. rnein, 1.02 verildiinde
Ceiling() 2.0 dndrr. -1.02
verildiinde Ceiling() -1 dndrr.
public static double Cos(double v)
vnin kosinsn dndrr.
public static double Cosh(double v)
vnin hiperbolik kosinsn dndrr.
public static double Exp(double v)
Doal logaritma taban enin vnci kuvvetini
dndrr.
public static double Floor(double v)
vden byk olmayan (kayan noktal deer
olarak simgelenen) en byk tamsayy
dndrr. rnein, 1.02 verildiinde
Floor() 1.0 dndrr. -1.02 verildiinde
Floor () -2 dndrr.
public static double
IEEERemainder(double dividend, double
divisor)
dividend / divisor ileminin kalann
dndrr.
public static double Log(double v)
v iin doal logaritmay dndrr.
public static double Log(double v,
double base)
Taban olarak basei kullanarak v iin doal
logaritmay dndrr.
BLM 19: SYSTEM SM UZAYI

HERKES N C#
535
public static double Log10(double v)
Taban olarak 10u kullanarak v iin doal
logaritmay dndrr.
public static double Max(double v1,
double v2)
v1 ve v2nin byn dndrr.
public static float Max(float v1,
float v2)
v1 ve v2nin byn dndrr.
public static decimal Max(decimal v1,
decimal v2)
v1 ve v2nin byn dndrr.
public static int Max(int v1, int v2)
v1 ve v2nin byn dndrr.
public static short Max(short v1,
short v2)
v1 ve v2nin byn dndrr.
public static long Max(long v1,
long v2)
v1 ve v2nin byn dndrr.
public static uint Max(uint v1,
uint v2)
v1 ve v2nin byn dndrr.
public static ushort Max(ushort v1,
ushort v2)
v1 ve v2nin byn dndrr.
public static ulong Max(ulong v1,
ulong v2)
v1 ve v2nin byn dndrr.
public static byte Max(byte v1,
byte v2)
v1 ve v2nin byn dndrr.
public static sbyte Max(sbyte v1,
sbyte v2)
v1 ve v2nin byn dndrr.
public static double Min(double v1,
double v2)
v1 ve v2nin kn dndrr.
public static float Min(float v1,
float v2)
v1 ve v2nin kn dndrr.
public static decimal Min(decimal v1,
decimal v2)
v1 ve v2nin kn dndrr.
public static int Min(int v1, int v2)
v1 ve v2nin kn dndrr.
public static short Min(short v1,
short v2)
v1 ve v2nin kn dndrr.
public static long Min(long v1,
long v2)
v1 ve v2nin kn dndrr.
public static uint Min(uint v1,
uint v2)
v1 ve v2nin kn dndrr.
public static ushort Min(ushort v1,
ushort v2)
v1 ve v2nin kn dndrr.
public static ulong Min(ulong v1,
ulong v2)
v1 ve v2nin kn dndrr.
public static byte Min(byte v1,
byte v2)
v1 ve v2nin kn dndrr.

HERKES N C#
KISIM II C# KTPHANESN KEFETMEK

536
public static sbyte Min(sbyte v1,
sbyte v2)
v1 ve v2nin kn dndrr.
public static double Pow(double base,
double exp)
base in exp kuvvetini dndrr (base
exp
).
public static double Round(double v)
En yakn tamsayya yuvarlanm v deerini
dndrr.
public static decimal Round(decimal v)
En yakn tamsayya yuvarlanm v deerini
dndrr.
public static double Round(double v,
int frac)
frac ile belirtilen ondalk basamak saysna
yuvarlanm v deerini dndrr.
public static decimal Round(decimal v,
int frac)
frac ile belirtilen ondalk basamak saysna
yuvarlanm v deerini dndrr.
public static int Sign(double v)
v sfrdan kkse -1, v sfr ise 0 ve v
sfrdan bykse 1 dndrr.
public static int Sign(float v)
v sfrdan kkse -1, v sfr ise 0 ve v
sfrdan bykse 1 dndrr.
public static int Sign(decimal v)
v sfrdan kkse -1, v sfr ise 0 ve v
sfrdan bykse 1 dndrr.
public static int Sign(int v)
v sfrdan kkse -1, v sfr ise 0 ve v
sfrdan bykse 1 dndrr.
public static int Sign(short v)
v sfrdan kkse -1, v sfr ise 0 ve v
sfrdan bykse 1 dndrr.
public static int Sign(long v)
v sfrdan kkse -1, v sfr ise 0 ve v
sfrdan bykse 1 dndrr.
public static int Sign(sbyte v)
v sfrdan kkse -1, v sfr ise 0 ve v
sfrdan bykse 1 dndrr.
public static double Sin(double v)
vnin sinsn dndrr.
public static double Sinh(double v)
vnin hiperbolik sinsn dndrr.
public static double Sqrt(double v)
vnin karekkn dndrr.
public static double Tan(double v)
vnin tanjantn dndrr.
public static double Tanh(double v)
vnin hiperbolik tanjantn dndrr.
te, Pisagor teoremini uygulamak iin Sqrt() kullanan bir rnek. Bu program, bir dik
genin dik kenarlarnn uzunluklar verildiinde hipotensn uzunluunu hesaplar.
// Pisagor teoremini uygular.

using System;

class Pythagorean {
public static void Main() {
double s1;
double s2;
double hypot;
string str;
BLM 19: SYSTEM SM UZAYI

HERKES N C#
537

Console.WriteLine(Enter length of first side: );
str = Console.ReadLine();
s1 = Double.Parse(str);

Console.WriteLine(Enter length of second side: );
str = Console.ReadLine();
s2 = Double.Parse(str);

hypot = Math.Sqrt(s1 * s1 + s2 * s2);

Console.WriteLine(Hypotenuse is + hypot);
}
}
Programn rnek almas aada gsterilmitir:
Enter length of first side: 3
Enter length of second side: 4
Hypotenuse is 5
Bir sonraki rnek, yllk faiz oran ve faizin uygulanaca yl says verildiinde, gelecekte
istenilen deere ulamas iin balang yatrmnn ne kadar olmas gerektiini hesaplamak
amacyla Pow() metodunu kullanmaktadr. Balang yatrmn hesaplayan forml aada
gsterilmitir
BalangtakiYatrm = GelecektekiDeer / (1 + FaizOran)
YlSays

Pow(), double tipinde argmanlar gerektirdii iin faiz oran ve yl says double
deerler iinde tutulmaktadr. Gelecekteki deer ve balangtaki yatrm iin decimal tipi
kullanlmaktadr.
/* Yillik faiz orani ve faizin uygulanacagi yil sayisi
verildiginde, bilinen bir gelecek degere ulasmak icin
gerekli baslangic yatirimini hesaplar. */

using System;

class InitialInvestment {
public static void Main() {
decimal InitInvest; // baslangictaki yatirim
decimal FutVal; // gelecekteki deger

double NumYears; // yil sayisi
double IntRate; // ondalik degerde, yillik getiri orani

string str;

Console.Write(Enter future value: );
str = Console.ReadLine();
try {
FutVal = Decimal.Parse(str);
} catch(FormatException exc) {
Console.WriteLine(exc.Message);

HERKES N C#
KISIM II C# KTPHANESN KEFETMEK

538
return;
}

Console.Write(Enter interest rate (such as 0.085): );
str = Console.ReadLine();
try {
IntRate = Double.Parse(str);
} catch(FormatException exc) {
Console.WriteLine(exc.Message);
return;
}

Console.Write(Enter number of years: );
str = Console.ReadLine();
try {
NumYears = Double.Parse(str);
} catch(FormatException exc) {
Console.WriteLine(exc.Message);
return;
}

InitInvest = FutVal / (decimal) Math.Pow(IntRate + 1.0,
NumYears);

Console.WriteLine(Initial investment required: {0:C},
InitInvest);
}
}
Programn rnek almas aada gsterilmitir:
Enter future value: 10000
Enter interest rate (such as 0.085): 0.07
Enter number of years: 10
Initial investment required: $5,083.49
Deer Tipindeki Yaplar
Deer tipindeki yaplar Blm 14te tantlmt. Bunlar, insanlar tarafndan okunabilen
nmerik deerleri tutan karakter katarlarn karlk gelen ikili deerlere dntrmek iin
kullanlmlard. Burada ayrntl olarak incelenmektedirler.
Deer tipindeki yaplar, C#n deer tiplerinin altnda yatan yaplardr. Bu yaplar
tarafndan tanmlanan yeleri kullanarak, deer tipleriyle balantl ilemleri
gerekletirebilirsiniz.
.NET yap adlar ve bunlarn C#taki anahtar kelime olarak edeerleri aada
gsterilmitir:
.NET Yap Ad C# Ad
Boolean bool
BLM 19: SYSTEM SM UZAYI

HERKES N C#
539
Char char
Decimal decimal
Double double
Single float
Int16 short
Int32 int
Int64 long
UInt16 ushort
UInt32 uint
UInt64 ulong
Byte byte
SByte sbyte
Bu yaplarn her biri aadaki konulurda incelenmektedir.
NOT


Deer tipindeki yaklar tarafndan tanmlanan baz metotlar IFormatProvider
ya da NumberStyles tipinde bir parametre alrlar. IFormatProvider bu
blmn ileriki sayfalarnda ksaca incelenecektir. NumberStyles ise
System.Globalization isim uzaynda bulunan bir numaralandrmadr.
Biimlendirme konusu Blm 20de ele alnmaktadr.

Tamsay Tipinde Yaplar
Tamsay tipinde yaplar unlardr:
Byte SByte Int16 UInt16
Int32 UInt32 Int64 UInt64
Bu yaplarn her biri ayn metotlar ierirler. Bu metotlar Tablo 19.2de gsterilmitir. Bir
yapdan dierine fark eden tek ey Parse()n dn tipidir. Her yap iin Parse(), yap
tarafndan simgelenen tipin deerini dndrr. rnein, Int32 iin Parse() bir int deer
dndrr. UInt16 iin Parse() bir ushort deer dndrr. Parse() tantan bir rnek iin
Blm 14e bakn.
Tablo 19.2de gsterilen metotlara ek olarak tamsay tipindeki yaplar aadaki const
alanlar da ierirler:
MaxValue
MinValue
Her yap iin bu alanlar, sz konusu tamsay tipinin tutabilecei en byk ve en kk
deeri ierirler.

HERKES N C#
KISIM II C# KTPHANESN KEFETMEK

540
Tamsay tipindeki tm yaplar u arayzleri uygularlar: IComparable, IConvertible
ve IFormattable.
TABLO 19.2: Tamsay Tipindeki Yaplar Tarafndan Desteklenen Metotlar


Metot Anlam
public int CompareTo(object v) Metodu aran nesnenin nmerik deerini
vnin deeri ile karlatrr. Deerler eitse sfr
dndrr, Metodu aran nesne daha kk bir
deere sahipse negatif bir deer dndrr.
Metodu aran nesne daha byk bir deere
sahipse pozitif bir deer dndrr.

public override bool Equals(object v)
Metodu aran nesnenin deeri vnin deerine
eitse true dndrr.

public override int GetHashCode() Metodu aran nesnenin hash kodunu
dndrr.

public TypeCode GetTypeCode()
Edeer deer tipleri iin TypeCode
numaralandrmasn dndrr. rnein, Int32
iin tip kodu TypeCode.Int32dir.

public static retType Parse(string
str)
str iindeki nmerik karakter katarnn ikili
edeerini dndrr. Eer karakter katar, yap
tipi tarafndan tanmlanan ekliyle bir nmerik
deeri temsil etmiyorsa, bir kural d durum
frlatlr.

public static retType Parse(string
str, IFormatProvider fmtpvdr)
fmtpvdr ile salanan kltrel bilgiyi
kullanarak str iindeki nmerik karakter
katarnn ikili edeerini dndrr. Eer
karakter katar, yap tipi tarafndan tanmlanan
ekliyle bir nmerik deeri temsil etmiyorsa, bir
kural d durum frlatlr.

public static retType Parse(string
str, NumberStyles styles)
styles ile salanan stil bilgisini kullanarak
str iindeki nmerik karakter katarnn ikili
edeerini dndrr. Eer karakter katar, yap
tipi tarafndan tanmlanan ekliyle bir nmerik
deeri temsil etmiyorsa, bir kural d durum
frlatlr.

public static retType Parse(string
str, NumberStyles styles,
IFormatProvider fmtpvdr)
styles ile salanan stil bilgisini ve fmtpvdr
ile salanan kltrel bilgiyi kullanarak str
iindeki nmerik karakter katarnn ikili
edeerini dndrr. Eer karakter katar, yap
tipi tarafndan tanmlanan ekliyle bir nmerik
deeri temsil etmiyorsa, bir kural d durum
frlatlr.

public override string ToString() Metodu aran nesnenin deerinin karakter
katar olarak gsterimini dndrr.

BLM 19: SYSTEM SM UZAYI

HERKES N C#
541
public string ToString(string format) Metodu aran nesnenin deerinin karakter
katar olarak gsterimini, format iinde
aktarlan biim karakter katar tarafndan
belirtilen ekliyle dndrr.

public string ToString(IFormatProvider
fmtpvdr)
fmtpvdr iinde belirtilen kltrel bilgiyi
kullanarak, metodu aran nesnenin deerinin
karakter katar olarak gsterimini dndrr.
public string ToString(string format,
IFormatProvider fmtpvdr)
fmtpvdr iinde belirtilen kltrel bilgiyi ve
format ile belirtilen biimi kullanarak, metodu
aran nesnenin deerinin karakter katar olarak
gsterimini dndrr.

Kayan Nokta Tipinde Yaplar
Kayan nokta tipinde iki yap mevcuttur: Double ve Single. Single, float simgeler.
Bu yapnn metotlar Tablo 19.3te ve alanlar da Tablo 19.4te gsterilmitir. Double,
double simgeler. Bu yapnn metotlar Tablo 19.5te ve alanlar Tablo 19.6da gsterilmitir,
Tamsay tipindeki yaplarda olduu gibi, Parse()a ya da ToString()e arda bulunurken
kltrel bilgileri ve biim bilgilerini belirtebilirsiniz.
Kayan nokta tipindeki yaplar u arayzleri uygularlar: IComparable, IConvertible ve
IFormattable.
TABLO 19.3: Single Tarafndan Tanmlanan Metotlar


Metot Anlam
public int CompareTo(object v) Metodu aran nesnenin nmerik deerini
vnin deeri ile karlatrr. Deerler eitse sfr
dndrr, Metodu aran nesne daha kk bir
deere sahipse negatif bir deer dndrr.
Metodu aran nesne daha byk bir deere
sahipse pozitif bir deer dndrr.

public override bool Equals(object v)
Metodu aran nesnenin deeri vnin deerine
eitse true dndrr.

public override int GetHashCode() Metodu aran nesnenin hash kodunu
dndrr.

public TypeCode GetTypeCode()
Single iin bir TypeCode numaralandrma
deeri dndrr ki bu,
TypeCode.Singledr.

public static bool IsInfinity(float v) v, sonsuzu (pozitif ya da negatif) simgeliyorsa
true dndrr. Aksi halde false dndrr.

public static bool IsNaN(float v) v, bir say deilse, true dndrr. Aksi halde
false dndrr.


HERKES N C#
KISIM II C# KTPHANESN KEFETMEK

542
public static bool
IsPositiveInfinity(float v)
v, pozitif sonsuzu simgeliyorsa, true
dndrr. Aksi halde false dndrr.

public static bool
IsNegativeInfinity(float v)
v, negatif sonsuzu simgeliyorsa, true
dndrr. Aksi halde false dndrr.

public static float Parse(string str)
str iindeki nmerik karakter katarnn ikili
edeerini dndrr. Eer karakter katar, bir
float deeri temsil etmiyorsa, bir kural d
durum frlatlr.

public static float Parse(string str,
IFormatProvider fmtpvdr)
fmtpvdr ile salanan kltrel bilgiyi
kullanarak, str iindeki nmerik karakter
katarnn ikili edeerini dndrr. Eer
karakter katar, bir float deeri temsil
etmiyorsa, bir kural d durum frlatlr.

public static float Parse(string str,
NumberStyles styles)
styles ile salanan stil bilgisini kullanarak
str iindeki nmerik karakter katarnn ikili
edeerini dndrr. Eer karakter katar, bir
float deeri temsil etmiyorsa, bir kural d
durum frlatlr.

public static float Parse(string str,
NumberStyles styles,
IFormatProvider fmtpvdr)
styles ile salanan stil bilgisini ve fmtpvdr
ile salanan kltrel bilgiyi kullanarak str
iindeki nmerik karakter katarnn ikili
edeerini dndrr. Eer karakter katar, bir
float deeri temsil etmiyorsa, bir kural d
durum frlatlr.

public override string ToString() Metodu aran nesnenin deerinin karakter
katar olarak gsterimini dndrr.

public string ToString(string format) Metodu aran nesnenin deerinin karakter
katar olarak gsterimini, format iinde
aktarlan biim karakter katar tarafndan
belirtilen ekliyle dndrr.

public string ToString(IFormatProvider
fmtpvdr)
fmtpvdr iinde belirtilen kltrel bilgiyi
kullanarak, metodu aran nesnenin deerinin
karakter katar olarak gsterimini dndrr.

public string ToString(string format,
IFormatProvider fmtpvdr)
fmtpvdr iinde belirtilen kltrel bilgiyi ve
format ile belirtilen biimi kullanarak, metodu
aran nesnenin deerinin karakter katar olarak
gsterimini dndrr.

TABLO 19.4: Single Tarafndan Tanmlanan Alanlar


Alan Anlam
public const float Epsilon Sfrdan farkl en kk pozitif deer.
public const float MaxValue
Bir floatn tutabilecei en byk deer.
public const float MinValue
Bir floatn tutabilecei en kk deer.
BLM 19: SYSTEM SM UZAYI

HERKES N C#
543
public const float NaN Say olmayan bir deer.
public const float NegativeInfinity Negatif sonsuzu simgeleyen bir deer.
public const float PositiveInfinity Pozitif sonsuzu simgeleyen bir deer.
TABLO 19.5: Double Tarafndan Tanmlanan Metotlar


Metot Anlam
public int CompareTo(object v) Metodu aran nesnenin nmerik deerini
vnin deeri ile karlatrr. Deerler eitse sfr
dndrr, Metodu aran nesne daha kk bir
deere sahipse negatif bir deer dndrr.
Metodu aran nesne daha byk bir deere
sahipse pozitif bir deer dndrr.

public override bool Equals(object v)
Metodu aran nesnenin deeri vnin deerine
eitse true dndrr.

public override int GetHashCode() Metodu aran nesnenin hash kodunu
dndrr.

public TypeCode GetTypeCode()
Double iin bir TypeCode numaralandrma
deeri dndrr ki bu,
TypeCode.Doubledr.

public static bool IsInfinity
(double v)
v, sonsuzu (pozitif ya da negatif) simgeliyorsa
true dndrr. Aksi halde false dndrr.

public static bool IsNaN(double v) v, bir say deilse, true dndrr. Aksi halde
false dndrr.

public static bool
IsPositiveInfinity(double v)
v, pozitif sonsuzu simgeliyorsa, true
dndrr. Aksi halde false dndrr.

public static bool
IsNegativeInfinity(double v)
v, negatif sonsuzu simgeliyorsa, true
dndrr. Aksi halde false dndrr.

public static double Parse(string str)
str iindeki nmerik karakter katarnn ikili
edeerini dndrr. Eer karakter katar, bir
double deeri temsil etmiyorsa, bir kural d
durum frlatlr.

public static double Parse(string str,
IFormatProvider fmtpvdr)
fmtpvdr ile salanan kltrel bilgiyi
kullanarak, str iindeki nmerik karakter
katarnn ikili edeerini dndrr. Eer
karakter katar, bir double deeri temsil
etmiyorsa, bir kural d durum frlatlr.

public static double Parse(string str,
NumberStyles styles)
styles ile salanan stil bilgisini kullanarak
str iindeki nmerik karakter katarnn ikili
edeerini dndrr. Eer karakter katar, bir
double deeri temsil etmiyorsa, bir kural d
durum frlatlr.


HERKES N C#
KISIM II C# KTPHANESN KEFETMEK

544
public static double Parse(string str,
NumberStyles styles,
IFormatProvider fmtpvdr)
styles ile salanan stil bilgisini ve fmtpvdr
ile salanan kltrel bilgiyi kullanarak str
iindeki nmerik karakter katarnn ikili
edeerini dndrr. Eer karakter katar, bir
double deeri temsil etmiyorsa, bir kural d
durum frlatlr.

public override string ToString() Metodu aran nesnenin deerinin karakter
katar olarak gsterimini dndrr.

public string ToString(string format) Metodu aran nesnenin deerinin karakter
katar olarak gsterimini, format iinde
aktarlan biim karakter katar tarafndan
belirtilen ekliyle dndrr.

public string ToString(IFormatProvider
fmtpvdr)
fmtpvdr iinde belirtilen kltrel bilgiyi
kullanarak, metodu aran nesnenin deerinin
karakter katar olarak gsterimini dndrr.

public string ToString(string format,
IFormatProvider fmtpvdr)
fmtpvdr iinde belirtilen kltrel bilgiyi ve
format ile belirtilen biimi kullanarak, metodu
aran nesnenin deerinin karakter katar olarak
gsterimini dndrr.

TABLO 19.6: Double Tarafndan Tanmlanan Alanlar


Alan Anlam
public const double Epsilon Sfrdan farkl en kk pozitif deer.
public const double MaxValue
Bir doublen tutabilecei en byk deer.
public const double MinValue
Bir doublen tutabilecei en kk deer.
public const double NaN Say olmayan bir deer.
public const double NegativeInfinity Negatif sonsuzu simgeleyen bir deer.
public const double PositiveInfinity Pozitif sonsuzu simgeleyen bir deer.
Decimal
Decimal yaps, tamsay ve kayan noktal akrabalarna kyasla biraz daha karmaktr. Bu
yap, birok yaplandrc, alan, metot ve decimali C# tarafndan desteklenen dier nmerik
tiplere entegre etmeye yardmc olan operatrler ierir. rnein, metotlarn birka decimal ve
dier nmerik tipler arasnda dnm salarlar.
Decimal, sekiz tane public yaplandrc sunmaktadr. Aadaki alt tanesi en sk
kullanlanlardr:
public Decimal(int v)
public Decimal(uint v)
public Decimal(long v)
public Decimal(ulong v)
BLM 19: SYSTEM SM UZAYI

HERKES N C#
545
public Decimal(float v)
public Decimal(double v)
Bunlarn her biri belirtilen deerden bir Decimal oluturur.
Bir Decimali, aadaki yaplandrcnn kullanmyla Decimali oluturan paralar
belirterek de oluturabilirsiniz:
public Decimal(int alt, int orta, int st, bool iaretBayra,
byte lekFaktr)
Bir decimal deer paradan oluur. lk para, 96 bit uzunluunda bir tamsaydr.
kinci para, iaret bayradr. nc para ise lekleme faktrdr. 96 bit tamsay, alt,
orta ve st araclyla 32 bit paralar halinde aktarlr. aret, iaretBayra araclyla
aktarlr. iaretBayra, pozitif bir say iin false; negatif bir say iin true deerindedir.
lekleme faktr lekFaktr iinde aktarlr. Bu deer 0 ile 28 arasnda olmaldr. Bu
faktr, saynn ondalk bileenini ortaya karmak iin sayy blen 10nun kuvvetini (yani,
10
lekFaktr
) belirtir.
Her bileeni ayr ayr aktarmak yerine, bir Decimali oluturan paralar, aada
gsterilen yaplandrcy kullanarak, bir tamsay dizisinde belirtebilirsiniz:
public Decimal(int[ ] parts)
parts iindeki ilk int, 96 bit tamsay deeri ierir. parts[3]deki 31nci bit iaret
bayran (pozitif saylar iin 0, negatif saylar iin 1) ierir ve 16 ila 23nc bitler de
lekleme faktrn ierirler.
Decimal u arayzleri uygular: Icomperable, IConvertible ve IFomattable.
te, bir decimal deeri elle oluturan bir rnek:
// Elle ondalik bir sayi olustur.

using System;

class CreateDec {
public static void Main() {
decimal d = new decimal(12345, 0, 0, false, 2);

Console.WriteLine(d);
}
}
kt aada gsterilmitir:
123.45
Bu rnekte. 96 bit tamsaynn deeri 12345tir. Bunun iareti pozitiftir ye iki ondalk
ksm ierir.

HERKES N C#
KISIM II C# KTPHANESN KEFETMEK

546
Decimal tarafndan tanmlanan metotlar Tablo 19.7de gsterilmitir. Decimal tarafndan
tanmlanan alanlar ise Tablo 19.8de gsterilmitir. Decimalde ayrca decimal deerlerin
dier nmerik tiplerle birlikte deyimlerde kullanlmasna olanak tanyan ok sayda operatr ve
dnmler de tanmlanmaktadr. Deyimlerde ve atamalarda decimal kullanmn dzenleyen
kurallar Blm 3te anlatlmtr.
TABLO 19.7: Decimal Tarafndan Tanmlanan Metotlar


Metot Anlam
public static decimal Add(decimal v1,
decimal v2)
vnin mutlak deerini dndrr.
public static int CompareTo(decimal
v1, decimal v2)
v1in nmerik deerini v2ninkiyle
karlatrr. Deerler eitse sfr dndrr. v1,
v2den kkse negatif bir deer dndrr. v1,
v2den bykse pozitif bir deer dndrr.
public int CompareTo(object v) Metodu aran nesnenin deerini vninkiyle
karlatrr. Deerler eitse sfr dndrr.
Metodu aran nesnenin deeri daha kkse
negatif bir say dndrr. Metodu aran
nesnenin deeri daha bykse pozitif bir say
dndrr.
public static decimal Divide(decimal
v1, decimal v2)
v1 / v2 sonucunu dndrr.
public override bool Equals(object v) Metodu aran nesnenin deeri vnin deerine
eitse true dndrr.
public override bool Equals(decimal
v1, decimal v2)
v1, v2ye eitse true dndrr.
public static decimal Floor(decimal v) vden byk olmayan (ondalk deer olarak
simgelenen) en byk tamsayy dndrr.
rnein, 1.02 verildiinde Floor() 1.0
dndrr. -1.02 verildiinde Floor() -2
dndrr.
public static decimal
FromOACurrency(long v)
vnin iindeki OLE Otomasyon deerini karlk
gelen decimal edeerine dntrr ve
sonucu dndrr.
public static int[] GetBits(decimal v) vnin ikili gsterimini dndrr ve bu deeri bir
int dizisi iinde dndrr. Bu dizinin nasl
organize edildii metin iinde anlatlmtr.
public override int GetHashCode() Metodu aran nesne iin hash kodu
dndrr.
public TypeCode GetTypeCode() Decimal iin bir TypeCode numaralandrma
deeri dndrr ki bu,
TypeCode.Decimaldr.
BLM 19: SYSTEM SM UZAYI

HERKES N C#
547
public static decimal Multiply(decimal
v1, decimal v2)
v1 * v2 sonucunu dndrr.
public static decimal Negate
(decimal v)
-v deerini dndrr.
public static decimal Parse(string
str)
str iindeki nmerik karakter katarnn ikili
edeerini dndrr. Eer karakter katar, bir
decimal deeri temsil etmiyorsa, bir kural d
durum frlatlr.

public static decimal Parse(string
str, IFormatProvider fmtpvdr)
fmtpvdr ile salanan kltrel bilgiyi
kullanarak, str iindeki nmerik karakter
katarnn ikili edeerini dndrr. Eer
karakter katar, bir decimal deeri temsil
etmiyorsa, bir kural d durum frlatlr.

public static decimal Parse(string
str, NumberStyles styles,
IFormatProvider fmtpvdr)
styles ile salanan stil bilgisini ve fmtpvdr
ile salanan kltrel bilgiyi kullanarak str
iindeki nmerik karakter katarnn ikili
edeerini dndrr. Eer karakter katar, bir
decimal deeri temsil etmiyorsa, bir kural d
durum frlatlr.

public static decimal
Remainder(decimal v1, decimal v2)
v1 / v2 tamsay blme ileminin kalann
dndrr.
public static decimal Round(decimal v,
int decPlaces)
decPlaces ile belirtilen ondalk basamak
saysna yuvarlanm v deerini dndrr.
decPlaces, 0 ile 28 arasnda olmaldr.
public static decimal Subtract(decimal
v1, decimal v2)
v1 - v2 sonucunu dndrr.
public static byte ToByte(decimal v) vnin byte edeerini dndrr. Ondalk ksm
kesilir. v, byten menzili (tanml olduu
aralk) iinde deilse bir
OverflowException meydana gelir.
public static double ToDouble
(decimal v)
vnin double edeerini dndrr. Duyarlk
(precision) kayb meydana gelebilir, nk
double, decimalden daha az anlaml
(significant) basamaa sahiptir.
public static short ToInt16(decimal v) vnin short edeerini dndrr. Ondalk
ksm kesilir. v, shortun menzili (tanml
olduu aralk) iinde deilse bir
OverflowException meydana gelir.
public static int ToInt32(decimal v) vnin int edeerini dndrr. Ondalk ksm
kesilir. v, intin menzili (tanml olduu aralk)
iinde deilse bir OverflowException
meydana gelir.

HERKES N C#
KISIM II C# KTPHANESN KEFETMEK

548
public static long ToInt64(decimal v) vnin long edeerini dndrr. Ondalk ksm
kesilir. v, longun menzili (tanml olduu
aralk) iinde deilse bir
OverflowException meydana gelir.
public static long
ToOACurrency(decimal v)
vyi karlk gelen OLE Otomasyon deerine
dntrr ve sonucu dndrr.
public static sbyte ToSByte(decimal v) vnin sbyte edeerini dndrr. Ondalk
ksm kesilir. v, sbyten menzili (tanml
olduu aralk) iinde deilse bir
OverflowException meydana gelir.
public static float ToSingle
(decimal v)
vnin float edeerini dndrr. Ondalk
ksm kesilir. v, floatun menzili (tanml
olduu aralk) iinde deilse bir
OverflowException meydana gelir.
public override string ToString() Metodu aran nesnenin deerinin karakter
katar olarak gsterimini dndrr.

public string ToString(string format) Metodu aran nesnenin deerinin karakter
katar olarak gsterimini, format iinde
aktarlan biim karakter katar tarafndan
belirtilen ekliyle dndrr.

public string ToString(IFormatProvider
fmtpvdr)
fmtpvdr iinde belirtilen kltrel bilgiyi
kullanarak, metodu aran nesnenin deerinin
karakter katar olarak gsterimini dndrr.

public string ToString(string format,
IFormatProvider fmtpvdr)
fmtpvdr iinde belirtilen kltrel bilgiyi ve
format ile belirtilen biimi kullanarak, metodu
aran nesnenin deerinin karakter katar olarak
gsterimini dndrr.

public static ushort ToUInt16
(decimal v)
vnin ushort edeerini dndrr. Ondalk
ksm kesilir. v, ushortun menzili (tanml
olduu aralk) iinde deilse bir
OverflowException meydana gelir.
public static uint ToUInt32(decimal v) vnin uint edeerini dndrr. Ondalk ksm
kesilir. v, uintin menzili (tanml olduu
aralk) iinde deilse bir
OverflowException meydana gelir.
public static ulong ToUInt64
(decimal v)
vnin ulong edeerini dndrr. Ondalk
ksm kesilir. v, ulongun menzili (tanml
olduu aralk) iinde deilse bir
OverflowException meydana gelir.
public static decimal Truncate
(decimal v)
vnin tamsay ksmn dndrr. Bylece,
ondalk basamaklar kesilmi olur.
BLM 19: SYSTEM SM UZAYI

HERKES N C#
549
TABLO 19.8: Decimal Tarafndan Desteklenen Alanlar


Alan Anlam
public static readonly decimal MaxValue
Bir decimalin tutabilecei en byk deer.
public static readonly decimal MinusOne
-1in decimal olarak gsterimi
public static readonly decimal MinValue
Bir decimalin tutabilecei en kk deer.
public static readonly decimal One
1in decimal olarak gsterimi
public static readonly decimal Zero
0n decimal olarak gsterimi
Char
Deer tipinde yaplardan gnlk bazda belki de en kullanl olan Chardr, nk bu
yap, karakterleri ileyip kategorize etmenize imkan veren ok sayda metot sunmaktadr.
rnein, ToUpper() ararak bir kk harfi byk harfe evirebilirsiniz. IsDigit()i
ararak bir karakterin rakam olup olmadn belirleyebilirsiniz.
Char tarafndan tanmlanan metotlar Tablo 19.9da gsterilmitir. Charda aadaki
alanlar tanmldr:
public const char MaxValue
public const char MinValue
Bunlar, bir char deikenin tutabilecei en byk ve en kk deerleri simgelerler.
Char u arayzleri uygular: IComparable ve IConvertible.
TABLO 19.9: Char Tarafndan Tanmlanan Metotlar


Metot Anlam
public int CompareTo(object v) Metodu aran nesnenin deerini vninkiyle
karlatrr. Deerler eitse sfr dndrr, Metodu
aran nesnenin deeri daha kkse negatif bir
say dndrr. Metodu aran nesnenin deeri
daha bykse pozitif bir say dndrr.
public override bool Equals
(object v)
Metodu aran nesnenin deeri vnin deerine
eitse true dndrr.

public override int GetHashCode() Metodu aran nesne iin hash kodu dndrr.

public static double
GetNumericValue(char ch)
ch bir rakam ise chin nmerik deerini dndrr.
Aksi halde, -1 dndrr.
public static double
GetNumericValue(string str, int idx)
str[idx] bir rakam ise bu karakterin nmerik
deerini dndrr. Aksi halde, -1 dndrr.

HERKES N C#
KISIM II C# KTPHANESN KEFETMEK

550
public TypeCode GetTypeCode() Char iin bir TypeCode numaralandrma deeri
dndrr. Bu deer, TypeCode.Chardr.

public static UnicodeCategory
GetUnicodeCategory(char ch)
ch iin bir UnicodeCategory numaralandrma
deeri dndrr. UnicodeCategory, Unicode
karakterleri kategorize eden
System.Globalization tarafndan
tanmlanan bir numaralandrmadr.

public static UnicodeCategory
GetUnicodeCategory(string str,
int idx)
str[idx] iin bir UnicodeCategory
numaralandrma deeri dndrr.
UnicodeCategory, Unicode karakterleri
kategorize eden System.Globalization
tarafndan tanmlanan bir numaralandrmadr.

public static bool IsControl
(char ch)
ch bir kontrol karakteri ise true dndrr. Aksi
halde false dndrr.

public static bool IsControl(string
str, int idx)
str[idx] bir kontrol karakteri ise true
dndrr. Aksi halde false dndrr.

public static bool IsDigit(char ch) ch bir rakam ise true dndrr. Aksi halde
false dndrr.

public static bool IsDigit(string
str, int idx)
str[idx] bir rakam ise true dndrr. Aksi
halde, false dndrr.

public static bool IsLetter(char ch) ch alfabenin bir harfi ise true dndrr. Aksi
halde, false dndrr.

public static bool IsLetter(string
str, int idx)
str[idx] alfabenin bir harfi ise true dndrr.
Aksi halde, false dndrr.

public static bool
IsLetterOrDigit(char ch)
ch ya alfabenin bir harfi ya da bir rakam ise true
dndrr. Aksi halde, false dndrr.

public static bool IsLetterOrDigit
(string str, int idx)
str[idx] ya alfabenin bir harfi ya da bir rakam
ise true dndrr. Aksi halde, false dndrr.

public static bool IsLower(char ch) ch ya alfabenin kk harflerinden biri ise true
dndrr. Aksi halde, false dndrr.

public static bool IsLower(string
str, int idx)
str[idx] alfabenin kk harflerinden biri ise
true dndrr. Aksi halde, false dndrr.

public static bool IsNumber(char ch) ch onaltlk bir rakam ise true dndrr.
Onaltlk rakam 0 ile 9 ya da A ile F arasndadr.
Aksi halde, false dndrr.
public static bool IsNumber(string
str, int idx)
str[idx] onaltlk bir rakam ise true dndrr.
Onaltlk rakam 0 ile 9 ya da A ile F arasndadr.
Aksi halde, false dndrr.
public static bool
IsPunctuation(char ch)
ch bir noktalama iareti ise true dndrr. Aksi
halde false dndrr.

public static bool IsPunctuation
(string str, int idx)
str[idx] bir noktalama iareti ise true
dndrr. Aksi halde false dndrr.

BLM 19: SYSTEM SM UZAYI

HERKES N C#
551
public static bool IsSeperator
(char ch)
ch bir ayrc karakter ise, rnein boluk gibi,
true dndrr. Aksi halde false dndrr.

public static bool
IsSeperator(string str, int idx)
str[idx] bir ayrc karakter ise, rnein boluk
gibi, true dndrr. Aksi halde false dndrr.

public static bool IsSurrogate
(char ch)
ch bir Unicode yedek karakteri ise true
dndrr. Aksi halde false dndrr.

public static bool
IsSurrogate(string str, int idx)
str[idx] bir Unicode yedek karakteri ise true
dndrr. Aksi halde false dndrr.


public static bool IsSymbol(char ch) ch bir simgesel karakter ise, rnein para birimi
simgesi gibi, true dndrr. Aksi halde false
dndrr.

public static bool IsSymbol(string
str, int idx)
str[idx] bir simgesel karakter ise, rnein para
birimi simgesi gibi, true dndrr. Aksi halde
false dndrr.

public static bool IsUpper(char ch) ch byk harf ise true dndrr. Aksi halde,
false dndrr.

public static bool IsUpper(string
str, int idx)
str[idx] byk harf ise true dndrr. Aksi
halde, false dndrr.

public static bool IsWhiteSpace(char
ch)
ch bir boluk ise, rnein boluk karakteri ya da
sekme gibi, true dndrr. Aksi halde false
dndrr.

public static bool
IsWhiteSpace(string str, int idx)
str[idx] bir boluk ise, rnein boluk
karakteri ya da sekme gibi, true dndrr. Aksi
halde false dndrr.

public static char Parse(string str) str iindeki karakterin char edeerini
dndrr. Eer str birden fazla karakter
ieriyorsa, bir FormatException frlatlr.

public static char ToLower(char ch) ch byk harf ise chin kk harf edeerini
dndrr. Aksi halde, ch deiiklie uramadan
dndrlr.

public static char ToLower(char ch,
CulturInfo c)
ch byk harf ise chin kk harf edeerini
dndrr. Aksi halde, ch deiiklie uramadan
dndrlr. Dnm, belirtilen kltrel bilgiye
bal olarak ele alnr. CultureInfo,
System.Globalization iinde tanml bir
snftr.

public static char ToUpper(char ch) ch kk harf ise chin byk harf edeerini
dndrr. Aksi halde, ch deiiklie uramadan
dndrlr.

public static char ToUpper(char ch,
CulturInfo c)
ch kk harf ise chin byk harf edeerini
dndrr. Aksi halde, ch deiiklie uramadan
dndrlr. Dnm, belirtilen kltrel bilgiye
bal olarak ele alnr. CultureInfo,
System.Globalization iinde tanml bir
snftr.


HERKES N C#
KISIM II C# KTPHANESN KEFETMEK

552
public override string ToString() Metodu aran Charn deerinin karakter katar
olarak gsterimini dndrr.
public static string ToString
(char ch)
chin karakter katar olarak gsterimini dndrr.
public string
ToString(IFormatProvider fmtpvdr)
Belirtilen kltrel bilgiyi kullanarak metodu aran
Charn deerinin karakter katar olarak
gsterimini dndrr.
te, Char tarafndan tanmlanan metotlardan birkan gsteren bir program:
// Birkac Char metodunu gosterir.

using System;

class CharDemo {
public static void Main() {
string str = This is a test. $23;
int i;

for(i = 0; i < str.Length; i++) {
Console.Write(str[i] + is);
if(Char.IsDigit(str[i]))
Console.Write( digit);
if(Char.IsLetter(str[i]))
Console.Write( letter);
if(Char.IsLower(str[i]))
Console.Write( lowercase);
if(Char.IsUpper(str[i]))
Console.write( uppercase);
if(Char.IsSymbol(str[i]))
Console.Write( symbol);
if(Char.IsSeparator(str[i]))
Console.Write( separator);
if(Char.IsWhiteSpace(str[i]))
Console.Write( whitespace);
if(Char.IsPunctuation(str[i]))
Console.Write( punctuation);

Console.WriteLine();
}

Console.WriteLine(Original: + str);

// Buyuk harfe cevir.
string newstr = ;

for(i = 0; i < str.Length; i++)
newstr += Char.Toupper(str[i]);

Console.WriteLine(Uppercased: + newstr);
}
}
BLM 19: SYSTEM SM UZAYI

HERKES N C#
553
kt aada gsterilmitir:
T is letter uppercase
h is letter lowercase
i is letter lowercase
s is letter lowercase
is separator whitespace
i is letter lowercase
s is letter lowercase
is separator whitespace
a is letter lowercase
is separator whitespace
t is letter lowercase
e is letter lowercase
s is letter lowercase
t is letter lowercase
is punctuation
is separator whitespace
$ is symbol
2 is digit
3 is digit
Original: This is s test. $23
Uppercased: THIS IS A TEST. S23
Boolean Yaps
Boolean yaps, bool veri tipini destekler. Boolean tarafndan tanmlanan metotlar
Tablo 19.10da gsterilmitir. Booleanda aadaki alanlar tanmldr:
public static readonly string FalseString
public static readonly string TrueString
Bunlar, true ve falseun insanlarn okuyabildii biimlerini ierirler. rnein,
WriteLine() ars kullanarak FalseStringin ktsn alrsanz, ekranda False
karakter katar grntlenir.
Booleanda u arayzler tanmldr: IComparable ve IConvertible.
TABLO 19.10: Boolean Tarafndan Tanmlanan Metotlar


Metot Anlam
public int CompareTo(object v) Metodu aran nesnenin deerini vninkiyle
karlatrr. Deerler eitse sfr dndrr, Metodu
aran nesne false ve v true ise negatif bir
say dndrr. Metodu aran nesne true ve v
false ise pozitif bir say dndrr.
public override bool Equals
(object v)
Metodu aran nesnenin deeri vnin deerine
eitse true dndrr.


HERKES N C#
KISIM II C# KTPHANESN KEFETMEK

554
public override int GetHashCode() Metodu aran nesne iin hash kodu dndrr.

public TypeCode GetTypeCode() Boolean iin bir TypeCode numaralandrma
deeri dndrr. Bu deer,
TypeCode.Booleandr.

public static bool Parse(string str) str iindeki karakter katarnn bool edeerini
dndrr. Eer karakter katar ne True ne de
False ise kural d bir durum frlatlr. Byk-
kk harf farkll dikkate alnmaz.
public override string ToString() Metodu aran nesnenin deerinin karakter katar
olarak gsterimini dndrr.
string ToString(IFormatProvider
fmtpvdr)
fmtpvdr iinde belirtilen kltrel bilgiyi
kullanarak, aran nesnenin deerinin karakter
katar olarak gsterimini dndrr.

Array Snf
System iinde yer alan ok kullanl snflardan biri Arraydir. Array, C#taki tm
diziler iin temel bir snftr. Bu nedenle, Arrayin metotlar, standart tipteki dizilere ya da
sizin oluturduunuz tipteki dizilere uygulanabilir. Arrayde Tablo 19.11de gsterilen
zellikler ve Tablo 19.12de gsterilen metotlar tanmldr.
Arrayde u arayzler tanmldr: ICloneable, ICollection, IEnumerable ve
IList. ICollection, IEnumerable ve IList, System.Collections isim uzaynda
tanmlanmlardr ve Blm 22de anlatlmaktadrlar.
Metotlarn birka IComparer tipinde bir parametre kullanr. Bu arayz,
System.Collections iinde tanmldr. ki nesnenin deerini karlatran Compare()
adnda bir metot bu arayzde tanmlanmtr. Compare() aada gsterilmitir:
int Compare(object v1, object v2)
v1, v2den bykse metot, sfrdan byk bir deer dndrr; v1, v2den kkse sfrdan
kk bir deer dndrlr; iki deer eitse sfr dndrlr.
Sradaki birka konuda, ska kullanlan dizi ilemlerinden birka gsterilmektedir.
Dizileri Sralamak ve Aramak
En ok kullanlan dizi ilemlerinden biri sralamadr. Bu nedenle Array, sralama
metotlarndan oluan zengin bir btn destekler. Sort() metodunu kullanarak btn bir
diziyi, dizi iinde bir aral ya da uygun anahtar/deer iftlerini ieren bir dizi iftini
sralayabilirsiniz. Bir diziyi bir kez sralandktan sonra BinarySearch() kullanarak artk
diziyi verimli ve hzl biimde arayabilirsiniz. Bir int dizisini sralayarak Sort() ve
BinarySearch() metotlarn gsteren program aada yer almaktadr:
BLM 19: SYSTEM SM UZAYI

HERKES N C#
555
// Bir diziyi sirala ve dizi icinde bir degeri ara.

using System;

class SortDemo {
public static void Main() {
int[] nums = { 5, 4, 6, 3, 14, 9, 8, 17, 1, 24, -1, 0 };

// Orijinal sirayi goster.
Console.Write(Original order: );
foreach(int i in nums)
Console.Write(i + );
Console.WriteLine();

// Diziyi sirala.
Array.Sort(nums);

// Siralanmis diziyi goster.
Console.Write( Sorted order: );
foreach(int i in nums)
Console.Write(i + );
Console.WriteLine();

// I4u ara.
int idx = Array.BinarySearch(nums, 14);

Console.WriteLine(Index of 14 is + idx);
}
}
kt aada gsterilmitir:
Original order: 5 4 6 3 14 9 8 17 1 24 -1 0
Sorted order: -1 0 1 3 4 5 6 8 9 14 17 24
Index of 14 is 9
Yukardaki rnekte dizinin temel tipi inttir. int, bir deer tipidir. Array tarafndan
tanml tm metotlar otomatik olarak standart veri tiplerinin tmnn kullanmna hazrdr.
Ancak, nesne referanslar ieren diziler iin bu durum geerli olmayabilir. Nesne referanslar
ieren dizileri sralamak ya da aramak iin sz konusu nesnelerin snf tipi IComparable
arayzn uygulamaldr. Eer sz konusu snf IComparable uygulamazsa, diziyi sralama
ya da arama giriiminde bulunurken programn almas srasnda kural d bir durum
meydana gelir. Neyse ki, IComparable kolaylkla uygulanabilir, nk yalnzca u metodu
iermektedir:
int CompareTo(object v)
Bu metot, metodu aran nesneyi v deeri ile karlatrr. Metodu aran nesne vden
bykse metot, sfrdan byk bir deer dndrr. ki nesne eitse metot, sfr dndrr.
arda bulunan nesne vden kkse metot, sfrdan kk bir deer dndrr. Kullanc

HERKES N C#
KISIM II C# KTPHANESN KEFETMEK

556
tarafndan tanmlanan snf nesnelerinden oluan bir diziyi sralamay ve aramay gsteren bir
rnek aada yer almaktadr:
// Bir nesne dizisini siralamak ve aramak.

using System;

class MyClass : IComparable {
public int i;
public MyClass(int x) { i = x; }

// IComparablei uygula.
public int CompareTo(object v) {
return i - ((MyClass)v).i;
}
}

class SortDemo {
public static void Main() {
MyClsss[] nums = new MyClass[5];

nums[0] = new MyClass(5);
nums[1] = new MyClass(2);
nums[2] = new MyClass(3);
nums[3] = new MyClass(4);
nums[4] = new MyClass(1);

// Orijinal sirayi goster.
Console.Write(Original order: );
foreach(MyClass o in nums)
Console.Write(o.i + );
Console.writeLine();

// Diziyi sirala.
Array.Sort(nums);

// Siralanmis diziyi goster.
Console.Write(Sorted order: );
foreach(MyClass o in nums)
Console.Write(o.i + );
Console.WriteLine();

// MyClass(2)yi ara.
MyClass x = new MyClass(2);
int idx = Array.BinarySearch(nums, x);

Console.WriteLine(Index of MyClass(2) is + idx);
}
}
kt aadaki gibidir:
Original order: 5 2 3 4 1
Sorted order: 1 2 3 4 5
Index of MyClass(2) is 1
BLM 19: SYSTEM SM UZAYI

HERKES N C#
557
Diziyi Ters evirmek
Kimi zaman bir dizinin ieriini ters evirmek kullanl olur. rnein, artan srada
sralanm bir diziyi azalan srada sral olacak ekilde deitirmek isteyebilirsiniz. Bir diziyi
ters evirmek kolaydr: Yalnzca Reverse()i arn. Aadaki program bu ilemi
gstermektedir:
// Bir diziyi ters cevir.

using System;

class ReverseDemo {
public static void Main() {
int[] nums = { 1, 2, 3, 4, 5 };

// 0rijinal sirayi goster.
Console.Write(Original order: );
foreach(int i in nums)
Console.Write(i + );
Console.WriteLine();

// Butun diziyi ters cevir.
Array.Reverse (nums);

// Tersten sirali diziyi goster.
Console.Write(Reversed order: );
foreach(int i in nums)
Console.Write(i + );
Console.WriteLine();

// Bir araligi tersine cevir.
Array.Reverse(nums, 1, 3);

// Tersten sirali diziyi goster.
Console.Write(Range reversed: );
foreach(int i in nums)
Console.Write(i + );
Console.WriteLine();
}
}
kt aada gsterilmitir:
Original order: 1 2 3 4 5
Reversed order: 5 4 3 2 1
Range reversed: 5 2 3 4 1
Diziyi Kopyalamak
Bir dizinin tmn ya da bir ksmn bir baka diziye kopyalamak yaygn dizi
ilemlerinden bir bakasdr. Bir diziyi kopyalamak iin Copy()yi kullann. Copy()nin hangi

HERKES N C#
KISIM II C# KTPHANESN KEFETMEK

558
versiyonunu kullandnza bal olarak Copy(), eleri hedef dizinin bana ya da ortasna
yerletirir. Copy() aadaki programda gsterilmitir:
// Bir diziyi kopyala.

using System;

class CopyDemo {
public static void Main() {
int[] source = { 1, 2, 3, 4, 5 };
int[] target = { 11, 12, 13, 14, 15 };
int[] source2 = { -1, -2, -3, -4, -5 };

// Kaynagi goster.
Console.Write(source: );
foreach(int i in source)
Console.Write(i + );
Console.WriteLine();

// Orijinal hedefi goster.
Console.Write(Original contents of target: );
foreach(int i in target)
Console.Write(i + );
Console.WriteLine();

// Butun diziyi kopyala.
Array.Copy(source, target, source.Length);

// Kopyayi goster.
Console.Write(target after copy: );
foreach(int i in target)
Console.Write(i + );
Console.WriteLine();

// Hedefin ortasina kopyala.
Array.Copy(source2, 2, target, 3, 2);

// Kopyayi goster.
Console.Write(target after copy: );
foreach(int i in target)
Console.Write(i + );
Console.WriteLine();
}
}
kt aadaki gibidir:
source: 1 2 3 4 5
Original contents of target: 11 12 13 14 15
target after copy: 1 2 3 4 5
target after copy: 1 2 3 -3 -4

BLM 19: SYSTEM SM UZAYI

HERKES N C#
559
TABLO 19.11: Array Tarafndan Tanml zellikler


zellik Anlam
public virtual bool IsFixedSize
{ get; }
Dizi sabit byklkteyse true deerinde, dizi
dinamik ise false deerinde salt okunur bir zellik.
public virtual bool IsReadOnly
{ get; }
Array nesnesi salt okunur ise true deerinde;
deilse false deerinde salt okunur bir zellik.
public virtual bool IsSynchronized
{ get; }
Dizi ok kullanml bir ortamda kullanlmak iin
emniyetli ise true deerinde; aksi halde false
deerinde salt okunur bir zellik.
public int Length { get; } Dizinin eleman saysn ieren salt okunur bir zellik.
public int Rank { get; } Dizinin boyut saysn ieren salt okunur bir zellik.
public virtual object SyncRoot
{ get; }
Diziye eriimi senkronize etmek amacyla
kullanlmas gereken nesneyi ieren salt okunur bir
zellik.
TABLO 19.12: Array Tarafndan Tanml Metotlar


Metot Anlam
public static int BinarySearch(Array
a, object v)
a ile belirtilen dizi iinde v ile belirtilen deeri
arar. lk elemenin indeksini dndrr. v
bulunamazsa negatif bir deer dndrr. Dizi
sral ve tek boyutlu olmaldr.
public static int BinarySearch(Array
a, object v, IComparer comp)
comp ile belirtilen karlatrma metodunu
kullanarak a ile belirtilen dizi iinde v ile
belirtilen deeri arar. lk elemenin indeksini
dndrr. v bulunamazsa negatif bir deer
dndrr. Dizi sral ve tek boyutlu olmaldr.
public static int BinarySearch(Array
a, int start, int count, object v)
a ile belirtilen dizinin bir blmnde v ile
belirtilen deeri arar. Arama start ile belirtilen
indeksten balar ve count sayda eleman ile
snrldr. lk elemenin indeksi dndrlr. v
bulunamazsa negatif bir deer dndrlr. Dizi
sral ve tek boyutlu olmaldr.
public static int BinarySearch(Array
a, int start, int count, object v,
IComparer comp)
comp ile belirtilen karlatrma metodunu
kullanarak a ile belirtilen dizinin bir blmnde
v ile belirtilen deeri arar. Arama start ile
belirtilen indeksten balar ve count sayda
eleman ile snrldr. lk elemenin indeksi
dndrlr. v bulunamazsa negatif bir deer
dndrlr. Dizi sral ve tek boyutlu olmaldr.

HERKES N C#
KISIM II C# KTPHANESN KEFETMEK

560
public static void Clear(Array a,
int start, int count)
ann belirtilen elemanlarna sfr deeri verir.
Sfrlanacak elemanlar start ile belirtilen
indeksten balar ve count sayda eleman iin
geerlidir.
public virtual object Clone() arda bulunan dizinin kopyasn dndrr.
Kopya dizi, orijinal dizideki elemanlara
referansta bulunur. Buna s kopyalama denir.
Bylece, elemanlar zerindeki deiiklikler her
iki diziyi de etkiler, nk her iki dizi de ayn
elemanlar kullanmaktadr.
public static void Copy(Array source,
Array dest, int count)
Her dizinin bandan balayarak sourcedan
deste count sayda eleman kopyalar. Her iki
dizi de ayn referans tipinde olunca Copy() s
kopyalama yapar; yani, her iki dizi ayn
elemanlara referansta bulunacaktr.
public static void Copy(Array source,
int srcStart, Array dest, int
destStart, int count)
source[srcStart]dan
dest[destStart]a count sayda eleman
kopyalar. Her iki dizi de ayn referans tipinde
olunca Copy() s kopyalama yapar; yani,
her iki dizi ayn elemanlara referansta
bulunacaktr.
public virtual void CopyTo(Array
dest, int start)
arda bulunan dizinin elemanlarn,
dest[start]tan balayarak deste
kopyalar.
public static Array
CreateInstance(Type t, int size)
t tipinde size eleman ieren tek boyutlu bir
diziye bir referans dndrr.
public static Array
CreateInstance(Type t,
int size1, int size2)
size1 x size2 boyutunda iki boyutlu bir
diziye bir referans dndrr. Elemanlarn her biri
t tipindedir.
public static Array
CreateInstance(Type t, int size1,
int size2, int size3)
size1 x size2 x size3 boyutunda
boyutlu bir diziye bir referans dndrr.
Elemanlarn her biri t tipindedir.
public static Array
CreateInstance(Type t, int[] sizes)
sizes ile belirtilen boyutlara sahip ok boyutlu
bir diziye bir referans dndrr. Elemanlarn her
biri t tipindedir.
public static Array
CreateInstance(Type t, int[] sizes,
int[] startIndexes)
sizes ile belirtilen boyutlara sahip ok boyutlu
bir diziye bir referans dndrr. Elemanlarn her
biri t tipindedir. Her boyutun balang indeksi
startIndexes iinde belirtilmitir. Bylece,
sfrdan farkl bir indeksten balayan diziler
oluturmak mmkndr.
public override bool Equals(object v) arda bulunan nesnenin deeri vnin deerine
eitse true dndrr.
BLM 19: SYSTEM SM UZAYI

HERKES N C#
561
public virtual IEnumerator
GetEnumerator()
Dizi iin bir numaralandrc (enumerator) nesne
dndrr. Numaralandrc, dizi zerinden
dnerek tekrar tekrar gemenizi mmkn klar.
Numaralandrclar Blm 22de (Koleksiyonlar)
anlatlmtr.
public int GetLength(int dim) Belirtilen boyutun uzunluunu dndrr. Sz
konusu boyut sfr tabanldr; yani ilk boyutun
uzunluunu almak iin metoda 0 aktarn. kinci
boyutun uzunluunu elde etmek iin 1 aktarn.
public int GetLowerBound(int dim) Belirtilen boyutun ilk indeksini dndrr. Bu
deer genellikle sfrdr. Sz konusu boyut sfr
tabanldr; yani ilk boyutun uzunluunu almak
iin metoda 0 aktarn. kinci boyutun uzunluunu
elde etmek iin 1 aktarn.
public override int GetHashCode() Metodu aran nesne iin hash kodu dndrr.
public TypeCode GetTypeCode() Array iin bir TypeCode numaralandrma
deeri dndrr. Bu deer,
TypeCode.Arraydir.
public int GetUpperBound(int dim) Belirtilen boyutun son indeksini dndrr. dim
parametresi sfr tabanldr; yani ilk boyutun son
indeksini almak iin metoda 0 aktarn. kinci
boyutun son indeksini elde etmek iin 1 aktarn.
public object GetValue(int idx) arda bulunan dizinin idx indeksindeki
elemann deerini dndrr. Dizi tek boyutlu
olmaldr.
public object GetValue(int idx1,
int idx2)
arda bulunan dizinin [idx1, idx2]
indeksindeki elemann deerini dndrr. Dizi iki
boyutlu olmaldr.
public object GetValue(int idx1,
int idx2, int idx3)
arda bulunan dizinin [idx1, idx2,
idx3] indeksindeki elemann deerini dndrr.
Dizi boyutlu olmaldr.
public object GetValue(int[] idxs) arda bulunan dizi iinde, belirtilen
indekslerdeki elemanlarn deerlerini dndrr.
Dizi, idxsin sahip olduu eleman says kadar
boyuta sahip olmaldr.
public static int IndexOf(Array a,
object v)
Tek boyutlu a dizisinde, v ile belirtilen deere
sahip ilk elemann indeksini dndrr. Deer
bulunamazsa -1 dndrr. (Eer dizinin alt snr
sfrdan farklysa; baarszlk deeri, alt snr
-1dir.)
public static int IndexOf(Array a,
object v, int start)
Tek boyutlu a dizisinde, v ile belirtilen deere
sahip ilk elemann indeksini dndrr. Arama
a[start]tan balar. Deer bulunamazsa -1
dndrr. (Eer dizinin alt snr sfrdan
farklysa; baarszlk deeri, alt snr -1dir.)

HERKES N C#
KISIM II C# KTPHANESN KEFETMEK

562
public static int IndexOf(Array a,
object v, int start, int count)
Tek boyutlu a dizisinde, v ile belirtilen deere
sahip ilk elemann indeksini dndrr. Arama
a[start]tan balar ve count eleman iin
geerlidir. Deer bulunamazsa -1 dndrr.
(Eer dizinin alt snr sfrdan farklysa;
baarszlk deeri, alt snr -1dir.)
public void Initialize() arda bulunan dizinin her elemanna, elemann
yaplandrcsn ararak ilk deer atar. Bu metot
yalnzca deer tipindeki dizilerde kullanlabilir.
public static int LastIndexOf(Array
a, object v)
Tek boyutlu a dizisinde, v ile belirtilen deere
sahip ilk elemann indeksini dndrr. Deer
bulunamazsa -1 dndrr. (Eer dizinin alt snr
sfrdan farklysa; baarszlk deeri, alt snr
-1dir.)
public static int LastIndexOf(Array
a, object v, int start)
Tek boyutlu a dizisinde, v ile belirtilen deere
sahip ilk elemann indeksini dndrr. Arama
a[start]tan balayp a[0]da sona erecek
ekilde ters srada ilerler. Deer bulunamazsa -1
dndrr. (Eer dizinin alt snr sfrdan
farklysa; baarszlk deeri, alt snr -1dir.)
public static int LastIndexOf(Array
a, object v, int start, int count)
Tek boyutlu a dizisinde, v ile belirtilen deere
sahip ilk elemann indeksini dndrr. Arama
a[start]tan balayp count eleman iin
geerli olacak ekilde ters srada ilerler. Deer
bulunamazsa -1 dndrr. (Eer dizinin alt snr
sfrdan farklysa; baarszlk deeri, alt snr
-1dir.)
public static void Reverse(Array a) ann elemanlarn ters evirir.
public static void Reverse(Array a,
int start, int count)
a iindeki bir araln elemanlarn ters evirir.
Ters evrilecek aralk a[start]tan balar ve
count eleman iin geerlidir.
public void SetValue(object v, int
idx)
arda bulunan dizinin idx indeksindeki
elemana v deerini verir. Dizi tek boyutlu
olmaldr.
public void SetValue(object v, int
idx1, int idx2)
arda bulunan dizinin [idx1, idx2]
indeksindeki elemana v deerini verir. Dizi iki
boyutlu olmaldr.
public void SetValue(object v, int
idx1, int idx2, int idx3)
arda bulunan dizinin [idx1, idx2,
idx3] indeksindeki elemana v deerini verir.
Dizi boyutlu olmaldr.
public void SetValue(object v,
int[] idxs)
arda bulunan dizi iinde, belirtilen
indekslerdeki elemana v deerini verir. Dizi,
idxsnin sahip olduu eleman says kadar
boyuta sahip olmaldr.
public static void Sort(Array a) a dizisini artan srada sralar. Dizi tek boyutlu
olmaldr.
BLM 19: SYSTEM SM UZAYI

HERKES N C#
563
public static void Sort(Array a,
IComparer comp)
comp ile belirtilen karlatrma metodunu
kullanarak a dizisini artan srada sralar. Dizi tek
boyutlu olmaldr.
public static void Sort(Array k,
Array v)
Bir ift tek boyutlu diziyi artan srada sralar. k
dizisi sralama anahtarlarn ierir. v dizisi bu
anahtarlarla balantl deerleri ierir. Bylece, iki
dizi anahtar/deer iftlerini ierirler. Sralamadan
sonra her iki dizi de artan anahtar srasndadr.
public static void Sort(Array k,
Array v, IComparer comp)
comp ile belirtilen karlatrma metodunu
kullanarak bir ift tek boyutlu diziyi artan srada
sralar. k dizisi sralama anahtarlarn ierir. v
dizisi bu anahtarlarla balantl deerleri ierir.
Bylece, iki dizi anahtar/deer iftlerini ierirler.
Sralamadan sonra her iki dizi de artan anahtar
srasndadr.
public static void Sort(Array a, int
start, int count)
a iindeki bir araln elemanlarn artan srada
sralar. Aralk a[start]tan balar ve count
eleman uzunluundadr. Dizi tek boyutlu
olmaldr.
public static void Sort(Array a, int
start, int count, IComparer comp)
comp ile belirtilen karlatrma metodunu
kullanarak a iindeki bir araln elemanlarn
artan srada sralar. Aralk a[start]tan balar
ve count eleman uzunluundadr. Dizi tek
boyutlu olmaldr.
public static void Sort(Array k,
Array v, int start, int count)
Bir ift tek boyutlu dizi iinde bir aral artan
srada sralar. Her iki dizide de sralanacak aralk
start ile aktarlan indeksten balar ve count
eleman uzunluundadr. k dizisi sralama
anahtarlarn ierir. v dizisi bu anahtarlarla
balantl deerleri ierir. Bylece, iki dizi
anahtar/deer iftlerini ierirler. Sralamadan
sonra her iki dizi de artan anahtar srasndadr.
public static void Sort(Array k,
Array v, int start, int count,
IComparer comp)
comp ile belirtilen karlatrma metodunu
kullanarak bir ift tek boyutlu dizi iinde bir
aral artan srada sralar. Her iki dizide de
sralanacak aralk start ile aktarlan indeksten
balar ve count eleman uzunluundadr. k dizisi
sralama anahtarlarn ierir. v dizisi bu
anahtarlarla balantl deerleri ierir. Bylece, iki
dizi anahtar/deer iftlerini ierirler. Sralamadan
sonra her iki dizi de artan anahtar srasndadr.
BitConverter
Programlama yaparken sk sk standart veri tiplerini bir byte dizisine dntrmemiz
gerekir. Sz gelii, bir donanm cihaz bir tamsay deer gerektiriyor olabilir; fakat bu deer bir
kerede bir byte eklinde gnderilmelidir. Tersi durum da sk sk meydana gelir. Bazen veriler,
standart tiplerden birine dntrlmesi gereken sral bir byte sekans olarak alnacaktr.

HERKES N C#
KISIM II C# KTPHANESN KEFETMEK

564
rnein, bir cihaz, bir byte ak eklinde gnderilen tamsay ktlar retebilir. Ne tr bir
dnme ihtiya duyarsanz duyun C# bu problemlerin zm iin BitConverter snfn
salamaktadr.
BitConverter Tablo 19.13te gsterilen metotlar ierir. Ayrca aadaki alan da bu snf
iinde tanmldr:
public static readonly bool IsLittleEndian
Mevcut ortam bir szc en az anlaml byte ilk srada, en ok anlaml byte ikinci srada
yer alacak ekilde saklyorsa bu alan true deerine sahiptir. Buna kk endian biimi
denir. Eer mevcut ortam en ok anlaml byte ilk srada, en az anlaml byte ikinci srada yer
alacak ekilde saklarsa isLittleEndian falsetur. Buna byk endian biimi denir. Intel
Pentium tabanl makineler kk endian biimini kullanrlar.
BitConverter mhrlenmitir (sealed), yani kaltm yoluyla aktarlamaz.
TABLO 19.13: BitConverter Tarafndan Tanmlanan Metotlar


Metot Anlam
public static long
DoubleToInt64Bits(double v)
vyi bir long tamsayya dntrr ve sonucu
dndrr.
public static byte[ ] GetBytes(bool v) vyi 1 byte uzunluunda bir diziye dntrr
ve sonucu dndrr.
public static byte[ ] GetBytes(char v) vyi 2 byte uzunluunda bir diziye dntrr
ve sonucu dndrr.
public static byte[ ] GetBytes
(double v)
vyi 8 byte uzunluunda bir diziye dntrr
ve sonucu dndrr.
public static byte[ ] GetBytes
(float v)
vyi 4 byte uzunluunda bir diziye dntrr
ve sonucu dndrr.
public static byte[ ] GetBytes(int v) vyi 4 byte uzunluunda bir diziye dntrr
ve sonucu dndrr.
public static byte[ ] GetBytes(long v) vyi 8 byte uzunluunda bir diziye dntrr
ve sonucu dndrr.
public static byte[ ] GetBytes
(short v)
vyi 2 byte uzunluunda bir diziye dntrr
ve sonucu dndrr.
public static byte[ ] GetBytes(uint v) vyi 4 byte uzunluunda bir diziye dntrr
ve sonucu dndrr.
public static byte[ ] GetBytes
(ulong v)
vyi 8 byte uzunluunda bir diziye dntrr
ve sonucu dndrr.
public static byte[ ] GetBytes
(ushort v)
vyi 2 byte uzunluunda bir diziye dntrr
ve sonucu dndrr.
public static double
Int64BitsToDouble(long v)
vyi double tipinde bir kayan noktal deere
dntrr ve sonucu dndrr.
BLM 19: SYSTEM SM UZAYI

HERKES N C#
565
public static bool ToBoolean(byte[ ]
a, int idx)
a[idx] teki byte karlk gelen bool
edeerine dntrr ve sonucu dndrr.
Sfrdan farkl bir deer trueya dntrlr;
sfr, falsea dntrlr.
public static char ToChar(byte[ ] a,
int start)
a[start] tan balayan iki byte karlk
gelen char edeerine dntrr ve sonucu
dndrr.
public static double ToDouble(byte[ ]
a, int start)
a[start] tan balayan sekiz byte karlk
gelen double edeerine dntrr ve sonucu
dndrr.
public static short ToInt16(byte[] a,
int start)
a[start] tan balayan iki byte karlk
gelen short edeerine dntrr ve sonucu
dndrr.
public static int ToInt32(byte[ ] a,
int start)
a[start] tan balayan drt byte karlk
gelen int edeerine dntrr ve sonucu
dndrr.
public static long ToInt64(byte[ ] a,
int start)
a[start] tan balayan sekiz byte karlk
gelen long edeerine dntrr ve sonucu
dndrr.
public static float ToSingle(byte[ ]
a, int start)
a[start] tan balayan drt byte karlk
gelen float edeerine dntrr ve sonucu
dndrr.
public static string ToString
(byte[ ] a)
ann iindeki bytelar bir karakter katarna
dntrr. Karakter katar, bytelarla ilintili
onaltlk deerleri tire ile ayrlm olarak ierir.
public static string ToString(byte[ ]
a, int start)
a[start] tan balayarak ann iindeki
bytelar bir karakter katarna dntrr.
Karakter katar, bytelarla ilintili onaltlk
deerleri tire ile ayrlm olarak ierir.
public static string ToString(byte[ ]
a, int start, int count)
a[start] tan balayarak ann iindeki
count sayda byte bir karakter katarna
dntrr. Karakter katar, bytelarla ilintili
onaltlk deerleri tire ile ayrlm olarak ierir.
public static ushort ToUInt16(byte[ ]
a, int start)
a[start] tan balayan iki byte karlk
gelen ushort edeerine dntrr ve sonucu
dndrr.
public static uint ToUInt32(byte[ ] a,
int start)
a[start] tan balayan drt byte karlk
gelen uint edeerine dntrr ve sonucu
dndrr.
public static ulong ToUInt64(byte[ ]
a, int start)
a[start] tan balayan sekiz byte karlk
gelen ulong edeerine dntrr ve sonucu
dndrr.


HERKES N C#
KISIM II C# KTPHANESN KEFETMEK

566
Random ile Rasgele Saylar retmek
Szde-rasgele (pseudorandom) saylar sekans retmek iin Random snfn
kullanacaksnz. Rasgele say sekanslar simlasyonlar ve modelleme de dahil olmak zere ok
eitli durumlarda ie yararlar. Sekansn balama noktas bir tohum (seed) deer ile belirlenir.
Bu deer otomatik olarak Random tarafndan salanabilir ya da aka belirtilebilir.
Randomda aadaki iki yaplandrc tanmldr:
public Random( )
public Random(int tohum)
lk versiyonda, tohum deerini hesaplamak iin sistem saatini kullanan bir Random nesnesi
oluturulur. kinci versiyon, tohum deeri olarak tohumu kullanr.
Random tarafndan tanmlanan metotlar Tablo 19.14te gsterilmitir.
TABLO 19.14: Random Tarafndan Tanmlanan Metotlar


Metot Anlam
public virtual int Next() 0 ve Int32.Max.Value-1 (bu saylar dahil)
arasndaki bir sonraki rasgele tamsayy
dndrr.
public virtual int Next(int
upperBound)
0 ve upperBound-1 (bu saylar dahil)
arasndaki bir sonraki rasgele tamsayy
dndrr.
public virtual int Next(int
lowerBound, int upperBound)
lowerBound ve upperBound-1 (bu
saylar dahil) arasndaki bir sonraki rasgele
tamsayy dndrr.
public virtual void NextBytes(byte[ ]
buf)
bufi bir seri rasgele tamsay ile doldurur. Dizi
iindeki her byte 0 ile Byte.MaxValue-1
(bu saylar dahil) arasnda olmaldr.
public virtual int NextDouble() 0.0dan byk veya 0.0a eit ve 1.0den
kk bir kayan noktal deer ile simgelenen
seriden bir sonraki rasgele deeri dndrr.
public virtual double Sample() 0.0dan byk veya 0.0a eit ve 1.0den
kk bir kayan noktal deer ile simgelenen
seriden bir sonraki rasgele deeri dndrr.
arpk ya da zelletirilmi bir dalm
oluturmak iin bu metodu tretilmi bir snf
iinde devre d brakn.

te, kompterize edilmi bir ift zar oluturarak Randomu tantan bir program:
BLM 19: SYSTEM SM UZAYI

HERKES N C#
567
// Otomatize edilmis bir cift zar.

using System;

class RandDice {
public static void Main() {
Random ran = new Random();

Console.Write(ran.Next(1, 7) + );
Console.WriteLine(ran.Next(1, 7));
}
}
Programn almasndan rnek ite u ekildedir:
5 2
4 4
1 6
Bu program ncelikle bir Random nesnesi oluturarak almaktadr. Program sonra 1 ile 6
arasnda iki rasgele say talep etmektedir.
Bellek Ynetimi ve GC Snf
GC snf C#n anlamsz verileri toplama (garbage-collection) becerisini kendi bnyesinde
paketlemektedir. GC tarafndan tanmlanan metotlar Tablo 19.l5te gsterilmitir. Aada
gsterilen salt okunur zellik de bu snf iinde tanmldr:
public static int MaxGeneration { get; }
MaxGeneration tahsis edilen en eski bellek parasnn retim numarasn ierir. Ne
zaman bir tahsis sz konusu olsa (sz gelii, new kullanm ile) tahsis edilen bellee retim
numaras olarak sfr verilir. nceden ayrlan birimlerin retim numaralar artrlr. Bylece,
MaxGeneration ayrlan en eski bellek biriminin numarasn gsterir. retim numaralar,
anlamsz veri toplama ileminin verimliliini artrmaya yardmc olmaktadrlar.
Birok uygulamada GCnin becerilerinin hibirini kullanmayacaksnz. Yine de,
zelletirilmi durumlarda, bu beceriler ok kullanl olabilir. rnein, anlamsz verilerin
toplanmas ileminin istediiniz bir anda meydana gelmesini zorlamak iin Collect()i
kullanmak isteyebilirsiniz. Normal olarak, anlamsz verilerin toplanmas ilemi, programnz
tarafndan belirtilmeyen anlarda meydana gelir. Anlamsz verilerin toplanmas ilemi zaman
alc olduundan, zaman asndan kritik baz grevler srasnda bu ilemin gereklemesini
istemeyebilirsiniz. Ya da, bo geen zaman deerlendirmek iin anlamsz verilerin toplanmas
ilemini ve dier toparlama ilerini uygulamak isteyebilirsiniz.
GC mhrlenmitir (sealed), yani kaltm yoluyla aktarlamaz.

HERKES N C#
KISIM II C# KTPHANESN KEFETMEK

568
TABLO 19.15: GC Tarafndan Tanmlanan Metotlar


Metot Anlam
public static void Collect() Anlamsz verilerin toplanmas (garbage
collection) ilemini balatr.
public static void Collect(int
MaxGen)
retim numaralar 0 ile MaxGen arasnda olan
bellek iin anlamsz verilerin toplanmas ilemini
balatr.
public static int
GetGeneration(object o)
o ile referansta bulunulan bellek iin retim
numarasn dndrr.
public static int
GetGeneration(WeakReference o)
o ile belirtilen zayf referans tarafndan atfta
bulunulan bellek iin retim numarasn dndrr.
Zayf referans, nesnenin anlamsz veri olarak
toplanmasn nlemez.


public static long
GetTotalMemory(bool collect)
Halihazrda tahsis edilmi olan toplam byte
saysn dndrr. collect true ise ncelikle
anlamsz verilerin toplanmas ilemi
gerekletirilir..
public static void KeepAlive
(object o)
oya bir referans oluturur; bylece, anlamsz
veri olarak toplanmasn nlemi olur.
public static void
ReRegisterForFinalize(object o)
o iin sonulandrcnn (yani, yok edicinin)
arlmasna neden olur. Bu metot,
SuppressFinalize()n etkilerini etkisiz
klar.
public static void
SuppressFinalize(object o)
o iin sonulandrcnn (yani, yok edicinin)
arlmasn nler.
public static void
WaitForPendingFinalizers()
arda bulunan program kanalnn almasn
askda bulunan tm sonulandrclar (yani, yok
ediciler) arlana kadar durdurur.
Object
Object, C# nesne tipinin altnda yatan snftr. Objectin yeleri Blm 11de ele
alnmt; fakat Objectin C#ta sahip olduu merkezi rolden dolay Objectin metotlar, size
kolaylk salamas asndan, Tablo 19.16da tekrarlanmtr. Objectte, aada gsterilen, bir
adet yaplandrc tanmldr:
Object()
Bu yaplandrc bo bir nesne oluturur.

BLM 19: SYSTEM SM UZAYI

HERKES N C#
569
TABLO 19.16: Object Tarafndan Tanmlanan Metotlar


Metot Anlam
public virtual bool Equals(object ob) arda bulunan nesne objectin referansta
bulunduu nesne ile ayn ise true dndrr.
Aksi halde, false dndrr.
public static bool Equals(object ob1,
object ob2)
ob1, ob2 ile ayn ise true dndrr. Aksi
halde, false dndrr.
protected Finalize() Anlamsz veri toplama ileminden nce
kapatma(shutdown) faaliyetlerini
gerekletirir. C#ta Finalize() bir yok
edici araclyla eriilir.
public virtual int GetHashCode() arda bulunan nesne ile ilintili hash kodu
dndrr.
public Type GetType() Bir nesnenin tipini programn almas
srasnda elde eder.
protected object MemberwiseClone() Nesnenin s kopyasn karr. Bu tr
kopyalamada yeler kopyalanr ama yeler
tarafndan referansta bulunulan nesneler
kopyalanmaz.
public static bool
ReferenceEquals(object ob1, object ob2)
ob1 ve ob2 ayn nesneye referansta
bulunuyorsa true dndrr. Aksi halde,
false dndrr.
public virtual string ToString() Nesneyi tarif eden bir karakter katar
dndrr.
IComparable Arayz
Birok snf IComparable arayzn uygulamak zorunda kalacaktr, nk
IComparable, C# ktphanesinde tanml eitli metotlar araclyla bir nesnenin bir dieri
ile karlatrlmasn mmkn klar. IComparable, yalnzca aadaki metodu ierdii iin
kolaylkla uygulanr:
int CompareTo(object v)
Bu metot, metodu aran nesneyi v deeri ile karlatrr. arda bulunan nesne vden
bykse sfrdan byk bir deer dndrlr. Eer iki nesne eitse sfr dndrlr. arda
bulunan nesne vden kk ise sfrdan kk bir deer dndrlr.
IConvertible Arayz
IConvertible arayz, deer tipindeki yaplarn tm tarafndan uygulanr.
IConvertible eitli tip dnmlerini belirtir. Normal olarak, sizin oluturduunuz
snflarn bu arayz uygulamalar gerekmeyecektir.

HERKES N C#
KISIM II C# KTPHANESN KEFETMEK

570
ICloneable Arayz
ICloneable arayzn uygulayarak bir nesnenin kopyasnn karlmasn mmkn
klarsnz. ICloneableda yalnzca tek bir metot tanmldr: Clone(). Bu metot aada
gsterilmitir:
object Clone()
Bu metot, metodu aran nesnenin bir kopyasn kartr. Clone()u uygulama ekliniz
kopyann ne ekilde yaplacan belirler. Genel olarak iki tr kopya mevcuttur: Derin ve s.
Derin kopyalama yaplrken kopya ve orijinal nesne birbirinden tamamen bamszdr. Bylece,
eer orijinal nesne O adnda baka bir nesneye bir referans ieriyorsa Onun da bir kopyas
karlacaktr. S kopyalamada ise yeler kopyalanr, fakat yelerin referansta bulunduu
nesneler kopyalanmaz. Eer bir nesne O adnda baka bir nesneye referansta bulunuyorsa, s
kopyalamadan sonra hem kopya hem de orijinal nesne ayn O nesnesine referansta
bulunacaklardr ve O zerinde gerekletirilen her trl deiiklik hem kopyay hem orijinali
etkileyecektir. Genellikle derin kopyalama gerekletirmek istediinizde Clone()u
uygulayacaksnz. S kopyalamalar, Object iinde tanml olan MemberrwiseClone()
kullanlarak yaplabilir.
te ICloneable gsteren bir rnek. Bu program, X adnda bir snfa bir referans ieren
Test adnda bir snf oluturur. Test, derin kopya oluturmak iin Clone()u kullanr.
// ICloneable kullanimini gosterir.

using System;

class X {
public int a;

public X(int x) { a = x; }
}

class Test : ICloneable {
public X o;
public int b;

public Test(int x, int y) {
o = new X(x);
b = y;
}

public void show(string name) {
Console.Write(name + values are );
Console.WriteLine(o.a: {0}, b: {1}, o.a, b);
}

// Cagrida bulunan nesnenin derin kopyasini cikart.
public object Clone() {
Test temp = new Test(o.a, b);
BLM 19: SYSTEM SM UZAYI

HERKES N C#
571
return temp;
}
}

class CloneDemo {
public static void Main() {
Test ob1 = new Test(10, 20);
ob1.show(ob1);

Console.WriteLine(Make ob2 a clone of ob1.);
Test ob2 = (Test) ob1.Clone();
ob2.show(ob2);

Console.WriteLine(Changing ob1.o.a to 99 and ob1.b to 88.);
ob1.o.a = 99;
ob1.b = 88;

ob1.show(ob1);
ob2.show(ob2);
}
}
kt aada gsterilmitir:
ob1 values are o.a: 10, b: 20
Make ob2 a clone of ob1.
ob2 values are o.a: 10, b: 20
Changing ob1.o.a to 99 and ob1.b to 88.
ob1 values are o.a: 99, b: 88
ob2 values are o.a: 10, b: 20
ktdan grld gibi, ob2 ob1in klonudur, fakat ob1 ve ob2 tamamen ayr
nesnelerdir. Birini deitirmek dierini etkilemez. Bu durum, kopya iin yeni bir X nesnesi
ayrarak ve buna orijinal nesne iindeki Xin deerini vererek gerekletirilir.
S kopyalamay uygulamak iin Clone()un, Object tarafndan tanmlanan
MemberwiseClone()u armasn salamanz yeterlidir. rnein, yukardaki programdaki
Clone()u u ekilde deitirmeyi deneyin:
// Cagiran nesnenin bir sig kopyasini olustur.
public object Clone() {
Test temp = (Test) MemberwiseClone();
return temp;
}
Bu deiiklii yaptktan sonra programn kts aadaki gibi grnecektir:
ob1 values are o.a: 10, b: 20
Make ob2 a clone of ob1.
ob2 values are o.a: 10, b: 20
Changing ob1.o.a to 99 and ob1.b to 88.
ob1 values are o.a: 99, b: 88
ob2 values are o.a: 99, b: 20

HERKES N C#
KISIM II C# KTPHANESN KEFETMEK

572
Dikkat ederseniz, ob1 iindeki o ile ob2 iindeki o ayn X nesnesine referansta
bulunmaktadrlar. Elbette her birinin b adndaki int alan her eye ramen ayrdr, nk deer
tipleri referanslar araclyla eriilemezler.
IFormatProvider ve IFormattable
IFormatProvider arayz GetFormat() adnda tek bir metot tanmlamaktadr.
GetFormat(), verilerin insanlarn okuyabildii bir karakter katarna dntrlerek
biimlendirilmesini kontrol eden bir nesne dndrr. GetFormat() genel olarak u ekilde
kullanlr:
object GetFormat(Type fmt)
Burada fmt, elde edilecek biim nesnesini belirtir. Biimlendirme Blm 20de
anlatlmaktadr.
IFormattable arayz, ktnn insanlarn okuyabilecei ekilde biimlendirilmesini
destekler. IFormattableda u metot tanmldr:
string ToString(string fmt, IFormatProvider fmtpvdr)
Burada fmt, biimlendirme komutlarn belirtir; fmtpvdr ise biim salaycy belirtir.
Biimlendirme ayrntl olarak Blm 20de anlatlmaktadr.



Y R M N C B L M


KARAKTER KATARLARI
VE BMLENDRME





















20

HERKES N C#
KISIM II C# KTPHANESN KEFETMEK

574
Bu blmde String snf incelenmektedir. Btn programclarn bildii gibi, karakter
katarlarn dzenleme ilemi hemen hemen her programn bir parasdr. Bu nedenle String
snf, karakter kararlarnn kurulumunu ve ilenmesini ayrntl olarak kontrol etmenizi
salayan birtakm ok kapsaml metotlar, zellikler ve alanlar tanmlar. Verileri insanlarn
okuyabildii bir ekilde biimlendirmek, karakter katarlarn dzenleme ilemiyle yakndan
ilgilidir. Biimlendirme alt sistemini kullanarak C#n nmerik tiplerini, tarih ve saati ve
numaralandrmalar biimlendirebilirsiniz.
C#ta Karakter Katarlar
C#n karakter katarlarn dzenleme ileminin bir zeti Blm 7de sunulmutu;
bahsedilen konular burada tekrarlanmamtr. Ancak, String snfn incelemeden nce
karakter katarlarnn nasl uygulandn gzden geirmekte fayda vardr.
Tm bilgisayar dillerinde bir karakter katar bir dizi karakter demektir, fakat bu karakter
sekansnn tam olarak ne ekilde uyguland dilden dile deiiklik gsterir. C++ gibi baz
bilgisayar dillerinde karakter katarlar, karakter dizileridir. Ancak C#ta byle bir durum sz
konusu deildir. Bunun yerine, C#n karakter katarlar, standart string veri tipinde
nesnelerdir. Bu nedenle, string bir referans tipidir. stelik, string C#n standart .NET
string tipi System.String iin verdii bir isimdir. Bylece, bir C# karakter katar String
tarafndan tanml tm metot, zellik, alan ve operatrlere eriim hakkna sahiptir.
Bir karakter katar bir kez oluturulduktan sonra, karakter katarn oluturan karakter
sekans deitirilemez. Bu kstlama C#n, karakter katarlarn daha verimli uygulamasna
imkan verir. Bu kstlama belki de ciddi bir dezavantaj gibi grnmektedir, fakat deildir.
Mevcut bir karakter katar zerinde baz deiiklikler yaplm bir karakter katarna ihtiyacnz
olduunda, yalnzca istenilen deiiklikleri ieren yeni bir karakter katar oluturmanz ve eer
orijinale artk ihtiyacnz yoksa onu gz ard etmeniz yeterlidir. Kullanlmayan karakter katar
nesneleri otomatik olarak anlamsz veri kapsamnda topland iin gz ard edilen karakter
katarlarna ne olduunu dert etmenize gerek yoktur. Ancak bir konunun netlik kazanmas
gereklidir: string referans deikenleri elbette referansta bulunduklar nesneleri
deitirebilirler. Deitirilmeyen yalnzca, spesifik bir string nesnesi oluturulduktan sonra
sz konusu nesnenin karakter sekansdr.
Deitirilebilen bir karakter katar oluturmak iin C#, StringBuilder adnda bir snf
sunmaktadr. StringBuilder, System.Text isim uzayndadr. Ancak, birok ama iin
StringBuilder yerine stringi kullanmak isteyeceksiniz.
String Snf
String, System isim uzaynda tanmldr. String; IComparable, ICloneable,
IConvertible ve IEnumerable arayzlerini uygular. string bir sealed snftr; yani,
kaltm yoluyla aktarlamaz. String, C# iin karakter katarlarn dzenleyici bir ilevsellik
BLM 20: KARAKTER KATARLARI VE BMLENDRME

HERKES N C#
575
salar. String, C#n standart string tipinin altnda yatar ve .NET Frameworkn bir
parasdr. Sonraki birka balk altnda, String snf ayrntl olarak incelenmektedir.
String Yaplandrclar
String snfnda bir karakter katarn eitli yollardan kurmanza imkan veren birka
yaplandrc tanmldr. Bir karakter dizisinden bir karakter katar oluturmak iin aadaki
yaplandrclardan birini kullann:
public String(char[] karakterler)
public String(char[] karakterler, int start, int toplam)
lkinde, karakterler iindeki karakterleri ieren bir karakter katar yaplandrlr. kinci-
sinde ise start ile belirtilen indeksten balayarak karakterler iinden toplam sayda karakter
kullanlr.
Aadaki yaplandrcy kullanarak belirli bir karakteri birka kez tekrarlayarak ieren bir
karakter katar oluturabilirsiniz:
public String(char karakter, int toplam)
Burada karakter, toplam sayda tekrarlanacak olan karakteri belirtir.
Bir karakter dizisine iaret eden bir iareti verildiinde, aadaki yaplandrclardan
birini kullanarak bir karakter katar oluturabilirsiniz:
unsafe public String(char* karktr)
unsafe public String(char* karktr, int start, int toplam)
lk ifadede karktr tarafndan iaret edilen karakterleri ieren bir karakter katar kurulur.
karktrn null sonlardrmal bir diziye iaret ettii varsaylr. Bu dizi kendi btnl iinde
kullanlr. kinci ifadede start ile belirtilen indeksten balayarak karktr tarafndan iaret
edilen diziden toplam sayda karakter kullanlr.
Bir byte dizisine iaret eden bir iareti verildiinde aadaki yaplandrclardan birini
kullanarak bir karakter katar yaplandrabilirsiniz:
unsafe public String(sbyte* karktr)
unsafe public String(sbyte* karktr, int start, int toplam)
unsafe public String(sbyte* karktr, int start,
int toplam, Encoding en)
lk ifade ile karktr tarafndan iaret edilen karakterleri ieren bir karakter katar kurulur.
karktrn null sonlandrmal bir diziye iaret ettii varsaylr. Bu dizi kendi btnl iinde
kullanlr. kinci ifade start ile belirtilen indeksten balayarak karktr tarafndan iaret
edilen diziden toplam sayda karakter kullanr. nc ifade bytelarn nasl kodlanacan
belirtmenize olanak tanr.

HERKES N C#
KISIM II C# KTPHANESN KEFETMEK

576
Varsaylan kodlama ASCIIEncodingdir. Encoding snf System.Text isim uzay
iindedir.
Bir karakter katar literali otomatik olarak bir karakter katar nesnesi oluturur. Bu nedenle,
bir string nesnesi genellikle kendisine bir karakter katar literali atanarak ilk kullanma
hazrlanr. Bunun bir rnei aada gsterilmitir:
string str = a new string;
String Alan, ndeksleyici ve zellik
String snfnda, aada gsterildii gibi, tek bir alan tanmldr:
public static readonly string Empty
Empty, bo bir karakter katar belirtir. Bo karakter katar, hi karakter iermeyen bir
stringdir. Bu, null String referansndan farkldr. null String referans hi bir
nesneye atfta bulunmaz.
String iin yalnzca bir adet salt okunur indeksleyici mevcuttur. Sz konusu indeksleyici
aada gsterilmitir:
public char this[int idx] { get; }
Bu indeksleyici, belirtilen indeksteki karakteri elde etmeye imkan verir. Tpk diziler gibi,
karakter katarlar iin de indeksleme sfrdan balar. String nesneleri deitirilemez olduklar
iin String snfnn tek bir salt okunur indeksleyiciyi desteklemesi mantkldr.
Ayrca, yalnzca tek salt okunur zellik mevcuttur:
public int Length { get; }
Length, karakter katar iindeki karakter saysn dndrr.
String Operatrleri
String snf iki operatr ar ykler: == ve !=. ki karakter katarnn eitliini test
etmek iin == operatrn kullann. Normal olarak == operatr nesne referanslarna
uygulandnda her iki referansn da ayn nesneye atfta bulunup bulunmadn belirler. ==, iki
string referansna uygulandnda ise karakter katarlarnn ierikleri eitlik iin karlatrlr.
Ayn durum != operatr iin de geerlidir: String nesneleri karlatrlrken karakter
katarlarnn ierikleri karlatrlr. Ancak, dier ilikisel operatrler, soz gelii <, > ya da =,
referanslar tpk dier nesne tiplerini karlatrr gibi karlatrrlar. Bir karakter katarnn
dierinden daha byk ya da kk olduunu belirlemek iin String snf iinde tanml olan
Compare() metodunu kullann.

BLM 20: KARAKTER KATARLARI VE BMLENDRME

HERKES N C#
577
String Metotlar
String snf iinde ok sayda metot tanmldr. stelik, metotlarn birou iki ya da daha
fazla ar yklenmi ekle sahiptir. Bu nedenle, bu metotlarn tmn listelemek ne pratiktir ne
de kullanldr. Bunun yerine, en ok kullanlan metotlardan birka, kullanmlarn gsteren
rneklerle birlikte sunulacaktr.
Karakter Katarlarn Karlatrmak
Karakter katar ilemlerinden belki de en sk kullanlan bir karakter katarn bir dieri ile
karlatrmaktr. neminden tr String, ok sayda karlatrma metodu salar. Bu
metotlar Tablo 20.1de gsterilmitir. Bu metotlar iinde en ok ynl olan Compare()dir.
Compare(), iki karakter katarn btnyle ya da paralar halinde karlatrabilir. Byk-
kk harf ayrm yaparak karlatrma yapabilir ya da harfin bykln dikkate
almayabilir. Genel olarak karakter katar karlatrmalarnda bir karakter katarnn dierinden
daha byk, kk ya da ikisinin eit olup olmadn belirlemek iin szlk sras kullanlr.
Karlatrmay etkileyen kltrel bilgileri de ayrca belirtebilirsiniz.
Aadaki programda Compare()in birka versiyonu gsterilmektedir:
// Karakter katarlarini karsilastirir.

using System;

class CompareDemo {
public static void Main() {
string str1 = one;
string str2 = one;
string str3 = ONE;
string str4 = two;
string str5 = one, too;

if{String.Compare(str1, str2) == 0)
Console.WriteLine(str1 + and + str2 + are equal.);
else
Console.WriteLine(str1 + and + str2 +
are not equal.);

if(String.Compare(str1, str3) == 0)
Console.WriteLine(str1 + and + str3 + are equal.);
else
Console.WriteLine(str1 + and + str3 +
are not equal.);

if(String.Compare(str1, str3, true) == 0)
Console.WriteLine(str1 + and + str3 +
are equal ignoring case.);
else
Console.WriteLine(str1 + and + str3 +
are not equal ignoring case.);


HERKES N C#
KISIM II C# KTPHANESN KEFETMEK

578
if(String.Compare(str1, str5) == 0)
Console.WriteLine(str1 + and + str5 + are equal.);
else
Console.WriteLine(str1 + and + str5 +
are not equal.);

if(String.Compare(str1, 0, str5, 0, 3) == 0)
Console.WriteLine(First part of + str1 + and +
str5 + are equal.);
else
ConsoLe.WriteLine(First part of + str1 + and +
str5 + are not equal.);

int result = String.Compare(str1, str4);
if(result < 0)
Console.WriteLine(str1 + is less than + str4);
else if(result > 0)
Console.WriteLine(str1 + is greater than + str4);
else
Console.WriteLine(str1 + equals + str4);
}
}
kt aadaki gibidir:
one and one are equal.
one and ONE are not equal.
one and ONE are equal ignoring case.
one and one, too are not equal.
First part of one and one, too are equal.
one is less than two
TABLO 20.1: String Karlatrma Metotlar


Metot Anlam
public static int Compare(string
str1, string str2)
str1 tarafndan referansta bulunulan karakter
katarn str2 ile karlatrr. str1, str2den
bykse sfrdan byk bir deer dndrr;
str1, str2den kkse sfrdan kk bir
deer dndrr; str1 ile str2 eitse sfr
dndrr.

public static int Compare(string
str1, string str2, bool ignoreCase)
str1 tarafndan referansta bulunulan karakter
katarn str2 ile karlatrr. strl, str2den
bykse sfrdan byk bir deer dndrr;
strl, str2den kkse sfrdan kk bir
deer dndrr; strl ile str2 eitse sfr
dndrr. Eer ignoreCase true ise
karlatrma byk-kk harf ayrmn dikkate
almaz. Aksi halde, harflerin bykl
nemlidir.
BLM 20: KARAKTER KATARLARI VE BMLENDRME

HERKES N C#
579
public static int Compare(string
str1, string str2, bool ignoreCase,
CultureInfo ci)
str1 tarafndan referansta bulunulan karakter
katarn str2 ile karlatrr. strl, str2den
bykse sfrdan byk bir deer dndrr;
strl, str2den kkse sfrdan kk bir
deer dndrr; strl ile str2 eitse sfr
dndrr. Eer ignoreCase true ise
karlatrma byk-kk harf ayrmn dikkate
almaz. Aksi halde, harflerin bykl
nemlidir. CultureInfo snf
System.Globalization isim uzaynda
tanmldr.

public static int Compare(string
str1, int start1, string str2, int
start2, int count)
strl ve str2 tarafndan referansta bulunulan
karakter katarlarnn paralarn karlatrr.
Karlatrma str1[startl] ile
str2[start2]tan balar ve count sayda
karakter iin geerlidir. str1, str2den
bykse sfrdan byk bir deer dndrr;
str1, str2den kkse sfrdan kk bir de-
er dndrr; str1 ile str2 eitse sfr
dndrr.

public static int Compare(string
str1, int start1, string str2, int
start2, int count, bool ignoreCase)
str1 ve str2 tarafndan referansta bulunulan
karakter katarlarnn paralarn karlatrr.
Karlatrma str1[startl] ile
str2[start2]tan balar ve count sayda
karakter iin geerlidir. str1, str2den
bykse sfrdan byk bir deer dndrr;
str1, str2den kkse sfrdan kk bir
deer dndrr; str1 ile str2 eitse sfr
dndrr. Eer ignoreCase true ise
karlatrma byk-kk harf ayrmn dikkate
almaz. Aksi halde, harflerin bykl
nemlidir.

public static int Compare(string
str1, int start1, string str2, int
start2, int count, bool ignoreCase,
CultureInfo ci)
str1 ve str2 tarafndan referansta bulunulan
karakter katarlarnn paralarn karlatrr.
Karlatrma str1[startl] ile
str2[start2]tan balar ve count sayda
karakter iin geerlidir. str1, str2den
bykse sfrdan byk bir deer dndrr;
str1, str2den kkse sfrdan kk bir de-
er dndrr; str1 ile str2 eitse sfr
dndrr. Eer ignoreCase true ise
karlatrma byk-kk harf ayrmn dikkate
almaz. Aksi halde, harflerin bykl
nemlidir. CultureInfo snf
System.Globalization isim uzaynda
tanmldr.


HERKES N C#
KISIM II C# KTPHANESN KEFETMEK

580
public static int
CompareOrdinal(string str1, string
str2)
Kltr, blge ya da dilden bamsz olarak str1
tarafndan referansta bulunulan karakter katarn
str2 ile karlatrr. str1, str2den bykse
sfrdan byk bir deer dndrr; str1,
str2den kkse sfrdan kk bir deer
dndrr; str1 ile str2 eitse sfr dndrr.

public static int
CompareOrdinal(string str1, int
start1, string str2, int start2, int
count)
Kltr, blge ya da dilden bamsz olarak str1
ve str2 tarafndan referansta bulunulan karakter
katarlarnn paralarn karlatrr. Karla-
trma str1[startl] ile str2[start2]tan
balar ve count sayda karakter iin geerlidir.
str1, str2den bykse sfrdan byk bir
deer dndrr; str1, str2den kkse
sfrdan kk bir deer dndrr; str1 ile
str2 eitse sfr dndrr.

public int CompareTo(object str) arda bulunan karakter katar ile str
karlatrr. arda bulunan karakter katar
strdan bykse sfrdan byk bir deer
dndrlr; strdan kkse sfrdan kk bir
deer dndrlr; her ikisi de eitse sfr
dndrlr.

public int CompareTo(string str) arda bulunan karakter katar ile str
karlatrr. arda bulunan karakter katar
strdan bykse sfrdan byk bir deer
dndrlr; strdan kkse sfrdan kk bir
deer dndrlr; her ikisi de eitse sfr
dndrlr.

Karakter Katarlarn Bititirmek
ki ya da daha fazla karakter katarn bititirmek iin iki yntem mevcuttur. Birincisi,
Blm 7de gsterildii gibi + operatrn kullanabilirsiniz. kincisi, String tarafndan
tanmlanan eitli ekleme metotlarndan birini kullanabilirsiniz. Birok durumda + kullanmak
en kolay yaklam olmasna ramen ekleme metotlar size ilave seenekler sunarlar.
Bititirme ilemini gerekletiren metot Concat() olarak adlandrlr. Bu metodun en
basit ekli aada gsterilmitir:
public static string Concat(string str1, string str2)
Bu metot, str1in sonuna str2 eklendikten sonra oluan yeni karakter katar dndrr.
Concat()n bir baka ekli, aada gsterildii gibi, karakter katarn bititirir:
public static string Concat(string str1, string str2, string str3)
Bu versiyonda str1, str2 ve str3n pe pee eklenmesiyle elde edilen karakter katar
dndrlr. Akas, bu ilemleri gerekletirmek iin Concat() metodunu kullanmak yerine
+ operatrn kullanmak daha kolaydr.
BLM 20: KARAKTER KATARLARI VE BMLENDRME

HERKES N C#
581
Concat()n bir dier kullanl versiyonu keyfi sayda karakter katarn pe pee ekler:
public static string Concat(params string[] strs)
Burada strs, bititirilen, deien sayda argmana referansta bulunmaktadr. Ekleme ile
elde edilen sonu dndrlr. Aadaki program Concat()n bu versiyonunu
gstermektedir:
// Concat()i gosterir.

using System;

class ConcatDemo {
public static void Main() {

string result = String.Concat(This , is , a ,
test , of , the ,
String , class.);

Console.WriteLine(result: + result);
}
}
kt aada gsterilmitir:
result: This is a test of the String class.
Concat() metodunun baz versiyonlar string referanslar yerine object referanslarn
alrlar. Bunlar, birlikte arldklar nesnelerin karakter katar olarak gsterimlerini elde ederler
ve bu karakter katarlarnn bititirilmi eklini ieren bir karakter katar dndrrler.
Concat()n bu versiyonlar aada gsterilmitir:
public static string Concat(object v1, object v2)
public static string Concat(object v1, object v2, object v3)
public static string Concat(params object[] v)
lk ifade, v1in karakter katar gsteriminin peine v2nin karakter katar gsteriminin
eklenmi eklini ieren bir karakter katar dndrr. kinci ifade; v1, v2 ve v3n karakter
katar gsterimlerinin bititirilmi eklini ieren bir karakter katar dndrr. nc ifade, v
iinde aktarlan argmanlarn karakter katar gsterimlerinin bititirilmi eklini ieren bir
karakter katar dndrr. Bu metotlarn ne kadar kullanl olabileceklerini grmek iin
aadaki program ele aln:
// Concat()i gosterir.

using System;

class ConcatDemo {
public static void Main() {

string result = String.Concat(hi , 10, ,
20.0, ,

HERKES N C#
KISIM II C# KTPHANESN KEFETMEK

582
false, ,
23.45M);

Console.WriteLine(result: + result);
}
}
kt aada gsterilmitir:
result: hi 10 20 False 23.45
Bu rnekte Concat() eitli tiplerdeki verilerin karakter katar gsterimlerini pe pee
eklemektedir. Her argman iin bir karakter katar gsterimi elde etmek amacyla sz konusu
argmanla ilikili ToString() metodu arlr. Bylece, 10 deeri iin Int32.ToString()
arlr. Concat() daha sonra bu karakter katarlarn pe pee ekler ve soncu dndrr.
Concat()n bu ekli ok kullanldr, nk sizi ekleme ncesinde karakter katar
gsterimlerini elle elde etmek zorunda kalmaktan kurtarmaktadr.
Karakter Katar inde Arama Yapmak
String, bir karakter katar iinde arama yapmanza olanak tanyan iki metot kmesi
sunmaktadr. Bir alt karakter katar ya da bir karakter arayabilirsiniz. kisinden birine ilk ya da
son kez rastlanlan konumu da arayabilirsiniz. Karakter ya da alt karakter katarna ilk
rastlanlan konumu aramak iin IndexOf() metodunu kullann. Bunun iki kullanm ekli ite
yledir:
public int IndexOf(char karktr)
public int IndexOf(String str)
lk ifade, arda bulunan karakter katar iinde karktr karakterine ilk rastlanlan konum-
daki indeksi dndrr. kincisinde ise, str karakter katarna ilk rastlanlan konumdaki indeksi
dndrlr. Aranlan e bulunmazsa her iki ifade de -1 dndrr.
Bir karaktere ya da alt karakter katarna son kez rastlanlan konumu aramak iin
LastIndexOf() metodunu kullann. Bunun iki kullanm ekli ite yledir:
public int LastIndexOf(char karktr)
public int LastIndexOf(string str)
lk ifade, arda bulunan karakter katarnn iinde karktr karakterine son kez rastlanlan
konumdaki indeksi dndrr. kinci ifade, str karakter katarna son kez rastlanlan konumdaki
indeksi dndrr. Aranlan ge bulunmazsa her ikisi de -1 dndrr.
String, iki enteresan ilave arama metodu sunar: IndexOfAny() ve
LastIndexOfAny(). Bu metotlar, bir karakter kmesinin herhangi bir esiyle elenen ilk ya
da son karakteri ararlar. Bunlarn en basit ekilleri yledir:
public int IndexOfAny(char[] a)
public int LastIndexOfAny(char[] a)
BLM 20: KARAKTER KATARLARI VE BMLENDRME

HERKES N C#
583
IndexOfAny(), ann iindeki herhangi bir karakterin metodu aran karakter katar
iinde ilk rastlanld konumdaki indeksini dndrr. LastIndexOfAny(), ann iindeki
herhangi bir karakterin metodu aran karakter katar iinde son rastlanld konumdaki
indeksini dndrr. Hi eleme bulunamazsa her iki metot da -1 dndrr.
Karakter katarlaryla alrken bir karakter katarnn belirli bir alt karakter kataryla
balayp balamadn ya da sona erip ermediini bilmek genellikle yararldr. Bu grevleri
gerekletirmek iin aada gsterilen StartsWith() ve EndsWith() metotlarn kullann:
public bool StartsWith(string str)
public bool EndsWith(string str)
Metodu aran karakter katar, str rerinden aktarlan karakter katar ile balyorsa
StartsWith() true dndrr. arda bulunan karakter katar, str zerinden aktarlan
karakter katar ile sona eriyorsa EndsWith() true dndrr. Baarszlk durumunda her
ikisi de false dndrr,
Aada, karakter katar arama yntemlerinden birkan gsteren bir program grlyor:
// Karakter katarlarini ara.

using System;

class StringSearchDemo {
public static void Main() {
string str = C# has powerful string handling.;
int idx;

Console.WriteLine(str: + str);

idx = str.IndexOf(h);
Console.WriteLine(Index of first h: + idx);

idx = str.LastIndexOf(h);
Console.WriteLine(Index of last h: + idx);

idx = str.IndexOf(ing);
Console.WriteLine(Index of first \ing\: + idx);

idx = str.LastIndexOf(ing);
Console.WriteLine(Index of last \ing\: + idx);

char[] chrs = { a, b, c };
idx = str.IndexOfAny(chrs);
Console.WriteLine(Index of first a, b, or c: + idx);

if(str.StartsWith(C# has))
Console.WriteLine(str begins with \C# has\);

if(str.EndsWith(ling.))
Console.WriteLine(str ends with \ling.\);
}

HERKES N C#
KISIM II C# KTPHANESN KEFETMEK

584
}
Programn kts aada gsterilmitir:
str: C# has powerful string handling.
Index of first h: 3
Index of last h: 23
Index of first ing: 19
Index of last ing: 28
Index of first a, b, or c: 4
str begins with C# has
str ends with ling.
Arama metotlarnn birka, aramaya belirli bir indeksten balamanza ya da arama yapla-
cak bir aralk belirtmenize olanak tanyan ek biimlere de sahiptirler. String arama metotlar-
nn tm versiyonlar Tablo 20.2de gsterilmitir.

TABLO 20.2: String Tarafndan Sunulan Arama Metotlar


Metot Anlam
public bool EndWith(string str) arda bulunan nesne, str rerinden aktarlan
karakter katar ile sona eriyorsa true dndrr.
Aksi halde, false dndrr.

public int IndexOf(char ch) arda bulunan karakter katar iinde chin
bulunduu ilk konumun indeksini dndrr, ch
bulunamazsa -1 dndrr.

public int IndexOf(string str) arda bulunan karakter katar iinde strn
bulunduu ilk konumun indeksini dndrr.
str bulunamazsa -1 dndrr.

public int IndexOf(char ch, int start) arda bulunan karakter katar iinde chin
bulunduu ilk konumun indeksini dndrr.
Arama start ile belirtilen indeksten balar. ch
bulunamazsa -1 dndrr.

public int IndexOf(string str, int
start)
arda bulunan karakter katar iinde strn
bulunduu ilk konumun indeksini dndrr.
Arama start ile belirtilen indeksten balar.
str bulunamazsa -1 dndrr.

public int IndexOf(char ch, int start,
int count)
arda bulunan, karakter katar iinde chin
bulunduu ilk konumun indeksini dndrr.
Arama start ile belirtilen indeksten balar ve
count eleman iin srdrlr. ch bulunamazsa
-1 dndrr.

BLM 20: KARAKTER KATARLARI VE BMLENDRME

HERKES N C#
585
public int IndexOf(string str, int
start, int count)
arda bulunan karakter katar iinde strn
bulunduu ilk konumun indeksini dndrr.
Arama start ile belirtilen indeksten balar ve
count eleman iin srdrlr. str
bulunamazsa -1 dndrr.

public int IndexOfAny(char[] a) a iindeki herhangi bir karakterin, metodu
aran karakter katar iinde ilk rastlanlan
konumdaki indeksini dndrr. Hi eleme
bulunamazsa -1 dndrlr.

public int IndexOfAny(char[] a, int
start)
a iindeki herhangi bir karakterin, metodu
aran karakter katar iinde ilk rastlanlan
konumdaki indeksini dndrr. Arama start
ile belirtilen indeksten balar. Hi eleme
bulunamasa -1 dndrlr.

public int IndexOfAny(char[] a, int
start, int count)
a iindeki herhangi bir karakterin, metodu
aran karakter katar iinde ilk rastlanlan
konumdaki indeksini dndrr. Arama start
ile belirtilen indeksten balar ve count eleman
iin geerlidir. Hi eleme bulunamazsa -1
dndrlr.
public int LastIndexOf(char ch) arda bulunan karakter katar iinde chn
bulunduu son konumun indeksini dndrr. ch
bulunamazsa -1 dndrr.

public int LastIndexOf(string str) arda bulunan kaakter katar iinde strn
bulunduu son konumun indeksini dndrr.
str bulunamazsa -1 dndrr.

public int LastIndexOf(char ch, int
start)
arda bulunan karakter katarnn bir blm
iinde chin bulunduu son konumun indeksini
dndrr. Arama, start ile belirtilen indeksten
balayp sfrda sona erecek ekilde ters srada
gerekletirilir. ch bulunamasa -1 dndrlr.

public int LastIndexOf(string str, int
start)
arda bulunan karakter katarnn bir blm
iinde strn bulunduu son konumun
indeksini dndrr. Arama, start ile belirtilen
indeksten baslayp sfrda sona erecek seklide
ters srada gerekletirilir. str bulunamazsa -1
dndrlr.

public int LastIndexOf(char ch, int
start, int count)
arda bulunan karakter katar iinde chin
bulunduu son konumun indeksini dndrr.
Arama, start ile belirtilen indeksten balayp,
count sayda eleman zerinde ters srada
gerekletirilir. ch bulunamazsa -1 dndrlr.


HERKES N C#
KISIM II C# KTPHANESN KEFETMEK

586
public int LastIndexOf(string str, int
start, int count)
arda bulunan karakter katar iinde strn
bulunduu son konumun indeksini dndrr.
Arama, start ile belirtilen indeksten balayp,
count sayda eleman zerinde ters srada
gerekletirilir. str bulunamazsa -1
dndrlr.

public int LastIndexOfAny(char[ ] a) a iindeki herhangi bir karakterin, metodu
aran karakter katar iinde son rastlanlan
konumdaki indeksini dndrr. Hi eleme
bulunamazsa -1 dndrlr,

public int LastIndexOfAny(char[ ] a,
int start)
a iindeki herhangi bir karakterin, metodu
aran karakter katar iinde son rastlanlan
konumdaki indeksini dndrr. Arama, start
ile belirtilen indeksten balayp sfrda sona
erecek ekilde ters srada gerekletirilir. Hi
eleme bulunamazsa -1 dndrlr.

public int LastIndexOfAny(char[ ] a,
int start, int count)
a iindeki herhangi bir karakterin, metodu
aran karakter katar iinde son rastlanlan
konumdaki indeksini dndrr. Arama, start
ile belirtilen indeksten balar ve count sayda
eleman zerinde ters srada gerekletirilir. Hi
eleme bulunamazsa -1 dndrlr.

public bool StartWith(string str) arda bulunan karakter katar str rerinden
aktarlan karakter katar ile balyorsa true
dndrr. Aksi halde, false dndrr.

Karakter Katarlarn Ayrmak ve Birletirmek
ki temel karakter katar ilemi ayrma ve birletirmedir. Ayrma, bir karakter katarn
kendisini oluturan paralara ayrr. Birletirme ise birtakm paralardan bir karakter katar
kurar. Bir karakter katarn ayrmak iin Stringde Split() tanmldr. Birtakm paralar
birletirmek iin String, Join()i salar.
Split()in genel olarak kullanm u ekildedir:
public string[] split(params char[] seps)
pblic string[] split(params char[] seps, int toplam)
lk ifade, metodu aran karakter katarn paralara ayrr ve bu alt karakter katarlarn ie-
ren bir dizi dndrr. Alt karakter katarlarn ayran karakterler seps iinde aktarlr. Eer
seps null ise, bu durumda ayrc olarak boluk (whitespace) kullanlr. kinci ifadede,
toplamdan daha fazla alt karakter katar dndrlmeyecektir.
Join() metodunun iki kullanm ekli aada gsterilmitir:
public static string Join(string sep, string[ ] strs)
public static string Join(string sep, string[ ] strs,
int start, int toplam)
BLM 20: KARAKTER KATARLARI VE BMLENDRME

HERKES N C#
587
lk ifader strs iindeki karakter katarlarnn pe pee eklenmi eklini ieren bir karakter
katar dndrr. kinci ifade, strs[start]tan balayarak strs iindeki toplam sayda
karakter katarnn pe pee eklenmesi ile elde edilen karakter katarn dndrr. Her iki
versiyonda her karakter katar bir sonrakinden sep ile belirtilen karakter katar ile ayrlr.
Aadaki program Split() ve Join()i gstermektedir:
// Split and join strings.

using System;

class SplitAndJoinDemo {
public static void Main() {
string str = One if by land, two if by sea.;
char[] seps = { , ., , };

// Karakter katarini iki parcaya ayir.
String[] parts = str.Split(seps);
Console.WriteLine(Pieces from split: );

for(int i = 0; i parts.Length; i++)
Console.WriteLine(parts[i]);

// Simdi, parcalari birlestir.
string whole = String.Join( | , parts);
Console.WriteLine(Result of join: );
Console.WriteLine(whole);
}
}
kt aadadr:
Pieces from split:
One
if
by
land

two
if
by
sea

Result of join:
One | if | by | land | | two | if | by | sea |
Bir karakter katarn ayrmak, karakter katar dzenlemeleriyle ilgili nemli bir
prosedrdr, nk bu yntem bir karakter katarn oluturan simgelerin (token) tek tek elde
edilmesi iin ska kullanlmaktadr. rnein, bir veri taban program, 100den byk tm
bteleri gster eklindeki bir sorgulamay 100 ve gster eklinde paralara ayrmak iin
Split() kullanabilir. Bu ilem srasnda ayrclar ortadan kaldrlr. Bylece, gster yerine
gster (bata ve sonda boluk olmadan) elde edilir. Aadaki program bu kavram

HERKES N C#
KISIM II C# KTPHANESN KEFETMEK

588
gstermektedir. Program, 10 + 5 gibi ikili matematiksel ilemler ieren karakter katarlarn
simgelere ayrr. Sonra matematiksel ilemi gerekletirir ve sonucu ekranda grntler.
// Karakter katarlarini simgelere ayir.

using System;

class TokenizeDemo {
public static void Main() {
string[] input = {
100 + 19,
100 / 3.3,
-3 * 9,
100 87
};
char[] seps = { };

for(int i = 0; i < input.Length; i++) {
// karakter katarini parcalara ayir
string[] parts = input[i].Split(seps);
Console.Write(Command: );

for(int j = 0; j < parts.Length; j++)
Console.Write(parts[i] + );

Console.Write(, Result: );
double n = Double.Parse(parts[0]);
double n2 = Double.Parse(parts[2]);

switch(parts[1]) {
case +:
Console.WriteLine(n + n2);
break;
case -:
Console.WriteLine(n - n2);
break;
case *;
Console.WriteLine(n * n2);
break;
case /:
Console.WriteLine(n / n2);
break;
}
}
}
}
kt yledir:
Command: 100 + 19 , Result: 119
Command: 100 / 3.3 , Result: 30.3030303030303
Command: -3 * 9 , Result: -27
Command: 100 - 87 , Result: 13
BLM 20: KARAKTER KATARLARI VE BMLENDRME

HERKES N C#
589
Karakter Katarlarn Doldurmak ve Budamak
Kimi zaman bir karakter katarnn bandaki ve sonundaki boluklar ortadan kaldrmak
isteyeceksiniz. Budama (trimming) olarak adlandrlan bu tr bir ilem genellikle komut
ilemciler iin gerekli otur. rnein, bir veri taban print szcn tanyor olabilir. Ancak,
kullanc bu komutu banda ya da sonunda bir ya da daha fazla boluk olacak ekilde girebilir.
Karakter katarnn veri taban tarafndan tannabilmesinden nce bu tr boluklarn her biri
ortadan kaldrlmaldr. Kart olarak, kimi zaman da bir karakter katarnn belirli bir minimal
uzunlua erimesi iin karakter katarn boluk ile doldurmak isteyeceksiniz. rnein,
biimlendirilmi kt hazrlyorsanz, hizay korumak iin her satrn belirli bir uzunlukta olma-
sn garanti etmeniz gerekebilir. Neyse ki, C# bu tr ilemleri kolaylatran metotlar iermekte-
dir.
Bir karakter katarn budamak iin aadaki Trim() metotlarndan birini kullann:
public string Trim()
public string Trim(params char[] karktrler)
lk ifade, metodu aran karakter katarnn banda ya da sonundaki boluklar
(whitespace) ortadan kaldrr. kinci ifade, karktrler tarafndan belirtilen karakterleri
karakter katarnn bandan ya da sonundan yok eder. Her iki durumda da sonuta elde edilen
karakter katar dndrlr.
Bir karakter katarnn ya sol tarafndan ya da sa tarafndan karakterler eklemek suretiyle
karakter katarn doldurabilirsiniz. Bir karakter katarn sol taraftan doldurmak iin aada
gsterilen metotlardan birini kullann:
public string PadLeft(int uzunluk)
public string PadLeft(int uzunluk, char karakter)
lk ifade, metodu aran karakter katarnn toplam uzunluu uzunluka eit olana kadar
karakter katarna sol taraftan gerekli sayada boluk ekler. kinci ifade, metodu aran karakter
katarnn toplam uzunluu uzunluka eit olmas iin karakter tarafndan belirtilen karakteri
gerekli olduka sz konusu karakter katarna ekler. Her iki durumda da sonuta elde edilen ka-
rakter katar dndrlr.
Bir karakter katarn sadan doldurmak iin aadaki metotlardan birini kullann:
public string PadRight(int uzunluk)
public string PadRight(int uzunluk, char karakter)
lk ifade, metodu aran karakter katarnn toplam uzunluu uzunluka eit olana kadar
karakter katarna sa taraftan gerekli sayda boluk ekler. kinci ifade, metodu aran karakter
katarnn toplam uzunluu uzunluka eit olmas iin karakter tarafndan belirtilen karakteri
gerekli olduka sz konusu karakter katarna ekler Her iki durumda da sonuta elde edilen ka-
rakter katar dndrlr.
Aadaki program budama ve doldurma ilemlerini gstermektedir:

HERKES N C#
KISIM II C# KTPHANESN KEFETMEK

590
// Budama ve doldurma.

using System;

class TrimPadDemo {
public static void Main() {
string str = test;

Console.WriteLine(Original string: + str);

// Sol taraftan bosluk doldur.
str = str.PadLeft(10);
Console.WriteLine(| + str + |);

// Sag taraftan bosluk doldur.
str = str.PadRight(20);
Console.WriteLine(| + str + |);

// Bosluklari doldur.
str = str.Trim();
Console.WriteLine(| + str + |);

// Sol taraftan # doldur.
str = str.PadLeft(10, #);
Console.WriteLine(| + str + |);

// Sag taraftan # doldur.
str = str.PadRight(20, #);
Console.WriteLine(| + str + |);

// #leri buda.
str = str.Trim(#);
Console.WriteLine(| + str + |);
}
}
kt aada gsterilmitir:
Original string: test
| test|
| test |
|test|
|######test|
|######test##########|
|test|
Ekleme, kartma ve Deitirme
Aada gsterilen Insert() metodunu kullanarak bir karakter katarn dierine
ekleyebilirsiniz:
public string Insert(int start, string str)
BLM 20: KARAKTER KATARLARI VE BMLENDRME

HERKES N C#
591
Burada str, start ile belirtilen indekste metodu aran karakter katarna eklenir. Elde
edilen karakter katar dndrlr.
Remove() kullanarak bir karakter katarnn bir blmn katardan karabilirsiniz.
Remove() u ekildedir:
public string Remove(int start, int toplam)
kartlacak karakterlerin says toplam ile belirtilir. kartmann balayaca indeks
start ile belirtilir. Elde edilen sonu dndrlr.
Replace() kullanarak bir karakter katarnn bir parasn deitirebilirsiniz.
Replace()in aadaki kullanmlar mevcuttur:
public string Replace(char ch1, char ch2)
public string Replace(string str1, string str2)
lk ifade, metodu aran karakter katar iinde ch1in getii yerlerin tmnde ch1i ch2
ile deitirir. kinci ifade ise, arda bulunan karakter katar iinde str1in getii yerlerin
tmnde str1i str2 ile deitirir. Her iki durumda da sonuta elde edilen karakter katar
dndrlr.
te, Insert(), Remove() ve Replece()i gsteren bir rnek:
// Ekler, degistirir ve cikartir

using System;

class InsRepRevDemo {
public static void Main() {
string str = This test;

Console.WriteLine(Original string: + str);

// Ekle
str = str.Insert(5, is a );
Console.WriteLine(str);

// Karakter katarini degistir
str = str.Replace(is, was);
Console.WriteLine(str);

// Karakterleri degistir
str = str.Replace(a, X);
Console.WriteLine(str);

// Cikart
str = str.Remove(4, 5);
Console.WriteLine(str);
}
}

HERKES N C#
KISIM II C# KTPHANESN KEFETMEK

592
kt aada gsterilmitir:
Original string: This test
This is a test
Thwas was a test
ThwXs wXs X test
ThwX X test
Harf Kipini Deitirmek
String, bir karakter katar iindeki harflerin kiplerini deitirmenizi mmkn klan iki
kullanl metot sunar. Bu metotlar ToUpper() ve ToLower() olarak adlandrlrlar ve
aada gsterilmilerdir:
public string ToLower()
public string ToUpper()
ToLower(), metodu aran karakter katarnn iindeki tm harfleri kk harf olarak
deitirir. ToUpper() ise metodu aran karakter katarnn iindeki tm harfleri byk harf
olarak deitirir. Sonuta elde edilen karakter katar dndrlr. Bu metotlarn ayrca kltrel
ayarlamalar belirtmenize imkan veren versiyonlar da mevcuttur.
Substring() Metodunun Kullanm
Substring() metodunu kullanarak bir karakter katarnn bir parasn elde edebilirsiniz.
Substring() metodunun iki kullanm mevcuttur:
public string Substring(int idx)
public string Substring(int idx, int toplam)
lk ifadede alt karakter katar idx ile belirtilen indeksten balar ve arda bulunan
karakter katarnn sonuna kadar srer. kinci ifadede, alt karakter katar idx ile belirtilen
indeksten balar ve toplam sayda karakter ile snrldr. Her iki durumda da sz konusu alt
karakter katar dndrlr.
Aadaki program Substring() metodunu gstermektedir:
// Substring()i kullanir.

using System;

class SubstringDemo {
public static void Main() {
string str = ABCDEFGHIJKLMNOPQRSTUVWXYZ;

Console.WriteLine(str: + str);

Console.Write(str.Substring(15): );
string substr = str.Substring(15);
Console.WriteLine(substr);

BLM 20: KARAKTER KATARLARI VE BMLENDRME

HERKES N C#
593
Console.Write(str.Substring(0, 15): );
substr = str.Substring(0, 15);
Console.WriteLine(substr);
}
}
Aadaki kt retilir:
Str: ABCDEFGHIJKLMNOPQRSTUVWXYZ
Str.Substring(15): PQRSTUVWXYZ
str.Substring(0, 15): ABCDEFGHIJKLMNO
Biimlendirme
int ya da double gibi standart bir tipin insanlarn okuyabildii formda olmasna gerek
duyulunca bir karakter katar gsterimi oluturulmaldr. C# bu tr bir gsterim iin otomatik
olarak varsaylan bir biim salyor olsa da kendi setiiniz bir biimi belirtmeniz de ayrca
mmkndr. rnein, Ksm Ide grdnz gibi dolar ve cent biimini kullanarak nmerik
verilerin ktsn almak mmkndr. Console.WriteLine(), String.Format() ve
nmerik yap tipleri iin tanmlanm ToString() metodu da dahil olmak zere birka sayda
metot verileri biimlendirir. Bu metotlarn de biimlendirme iin ayn yaklam
kullanrlar; bunlardan birinin verileri nasl biimlendirdiini bir kez rendikten sonra bunu
dierlerine de uygulayabilirsiniz.
Biimlendirmeye Genel Bak
Biimlendirme iki bileen tarafndan ynetilir: biim belirleyicileri (format specifiers) ve
biim salayclar (format providers). Bir deerin karakter katar olarak gsteriminin alaca
biim bir biim belirleyicisinin kullanm ile kontrol edilir. Bylece, verinin insanlar tarafndan
okunabilir biiminin nasl grneceini dikte eden biim belirleyicisidir. rnein, bilimsel
notasyon kullanarak bir nmerik deerin ktsn almak iin E biim belirleyicisini
kullanacaksnz.
Bir ok durumda bir deerin doru biimi, programn altrld kltr ve dilden
etkilenecektir. Sz gelii, Birleik Devletlerde para dolar ile simgelenir. Avrupada ise, euro ile
temsil edilir. Kltrel ve dilsel farkllklar kontrol altna almak iin C# biim salayclarn
kullanmakladr. Biim salaycs, biim belirleyicisinin nasl yorumlanacan tanmlar. Biim
salaycs IFormatProvider arayz uygulanarak oluturulur. Biim salayclar, standart
nmerik tipler iin ve .NET Framework iindeki birok dier tip iin nceden tanmldr. Genel
olarak, bir biim salaycs belirtmek iin kayg duymak zorunda kalmadan da verilerinizi
biimlendirebilirsiniz. Biim salayclarna bu kitapta daha fazla yer ayrlmamtr.
Verileri biimlendirmek iin biimlendirmeyi destekleyen bir metoda arda bulunurken
biim belirleyicisini de dahil edersiniz. Biim belirleyicilerinin kullanm Blm 3te
tantlmt, fakat burada yeniden gzden geirmeye deer. Aadaki anlatmda WriteLine()

HERKES N C#
KISIM II C# KTPHANESN KEFETMEK

594
kullanlmtr, ama ayn temel yaklam biimlendirmeyi destekleyen dier metotlara da
uygulanabilir.
WriteLine() kullanarak verileri biimlendirmek iin WriteLine()n aada
gsterilen versiyonunu kullann:
WriteLine(biimlendirme karakter katar, arg0, arg1, ... argN);
Bu versiyonda WriteLine()a aktarlan argmanlar + yerine virgl ile ayrlr.
biimlendirme karakter katar iki e ierir: Olduu gibi grntlenen dzgn, bask
karakterleri ve biim komutlar.
Biim komutlar genel olarak u ekildedir:
{argno, genilik: fmt}
Burada argno, grntlenecek argman saysn (sfrdan balayarak) belirtir. Alann
minimum genilii genilik ile belirtilir. Biim belirleyicisi ise fmt ile simgelenir.
genilik ve fmtnin her ikisi de istee baldr. Bylece, en basit ekliyle bir biim komutu
yalnzca hangi argmann grntleneceine iaret eder. Sz gelii, {0} arg0a iaret eder,
{1} arg1e iaret eder vs.
Programn almas srasnda, biim karakter katar iinde bir biim komutu ile
karlanca karlk gelen (argno ile belirtilen) argman yerine konulur ve ekranda
grntlenir. Bylece, elenen verilerin nerede grntleneceini belirleyen biim karakter
katar iindeki biim belirleyicinin konumudur,
Eer fmt mevcut ise, bu durumda veriler, belirtilen biim kullanlarak grntlenir. Aksi
halde, varsaylan biim kullanlr. Eer genilik mevcut ise, minimum alan geniliine
ulaldn garanti etmek iin kt boluk karakteri ile doldurulur. genilik pozitif ise kt
saa hizal gsterilir. genilik negatif ise, kt sola hizaldr.
Bu blmn kalannda biimlendirme ve biim belirleyicileri ayrntl olarak
incelenmektedir.
Nmerik Biim Belirleyicileri
Nmerik veriler iin birka biim belirleyicisi tanmlanmtr. Bunlar Tablo 20.3te
gsterilmilerdir. Her biim belirleyicisi, istee bal olarak duyarlk (precision) belirleyicisi de
ierebilir. rnein, bir deerin iki ondalk basama olan sabit noktal bir deer olarak
simgelenmesi gerektiini belirtmek iin F2 kullann.
nceden akland gibi, belirli biim belirleyicilerinin tam etkisi kltrel ayarlamalara
baldr. rnein, para birimi belirleyicisi olan C, bir deeri otomatik olarak seili olan
kltrn para biriminde grntler. Birok kullanc iin varsaylan kltrel bilgi, kullanclarn
kendi yerel bilgileri ve dili ile eleir. Bylece, programn altrld kltrel ereveyi dert
etmeye gerek kalmadan ayn biim belirleyicisi kullanlabilir.
BLM 20: KARAKTER KATARLARI VE BMLENDRME

HERKES N C#
595
Nmerik biim belirleyicilerinden birkan gsteren bir program aada yer almaktadr:
// Cesitli bicim belirleyicilerini gosterir.

using System;

class FormatDemo {
public static void Main() {
double v = 17688.65849;
double v2 = 0.15;
int x = 21;

Console.WriteLine({0:F2}, v);

Console.WriteLine({0:N5}, v);

Console.WriteLine({0:e}, v);

Console.WriteLine({0:r}, v);

Console.WriteLine({0:p}, v2);

Console.WriteLine({0:X}, x);

Console.WriteLine({0:D12}, x);

Console.WriteLine({0:C}, 189.99);
}
}
kt aada gsterilmitir:
17688.66
17,688.65849
1.768866e+004
17688.65849
15.00 %
15
000000000021
$189.99
Biimlerin birkanda yer alan duyarlk belirleyicisinin etkisine dikkat edin.
TABLO 20.3: Biim Belirleyicileri


Belirleyici Biim Duyarlk Belirleyicisinin Anlam
C Para birimi(yani, parasal deer). Ondalk basamaklarn saysn belirtir.
c C ile ayn.

HERKES N C#
KISIM II C# KTPHANESN KEFETMEK

596
D Tamsay nmerik veri. (Yalnzca
tamsaylarla kullanlr.)
En az basamak says. Gerekirse, sonucu
doldurarak tamamlamak iin ba tarafta
sfrlar kullanabilir.
d D ile ayn.
E Bilimsel notasyon (Byk harf E
kullanlr).
Ondalk basamaklarn saysn belirtir.
Varsaylan deer altdr.
e Bilimsel notasyon (Kk harf e
kullanlr).
Ondalk basamaklarn saysn belirtir.
Varsaylan deer altdr.
F Sabit noktal notasyon. Ondalk basamaklarn saysn belirtir.
f F ile ayn.
G E ya da F biiminden ksa olan kullanlr. E ve Fye bakn.
g e ya da f biiminden ksa olan kullanlr. e ve fye bakn.
N Sabit noktal notasyon. Ayrc olarak
virgl kullanlr.
Ondalk basamaklarn saysn belirtir.
n N ile ayn.
P Yzde Ondalk basamaklarn saysn belirtir.
p P ile ayn.
R ya da r Parse() kullanlarak edeer dahili
ekline geri ayrtrlan nmerik deer.
(Buna round-trip biim denir.)
Kullanlmaz.
X Onaltlk (A ile F arasndaki -A ile F dahil-
byk harfler kullanlr).
En az basamak says. Gerekirse, sonucu
doldurarak tamamlamak iin ba tarafta
sfrlar kullanabilir.
x Onaltlk (a ile f arasndaki -a ile f dahil-
kk harfler kullanlr).
En az basamak says. Gerekirse, sonucu
doldurarak tamamlamak iin ba tarafta
sfrlar kullanabilir.
Verileri Biimlendirmek iin String.Format() ve
ToString() Kullanm
WriteLine() iine biim komutlarn gmmek kty biimlendirmek iin kullanl bir
yntem olmasna ramen, kimi zaman biimlendirilmi kty ieren bir karakter katar
oluturmak isleyeceksiniz, fakat bu karakter katarn hemen ekranda grntlemek
istemeyeceksiniz. Bu ekilde davranmak, verileri daha sonra biimlendirmenize imkan vererek,
kty daha sonra tercih ettiiniz cihazdan almanza olanak tanr. Bu tr bir yaklam zellikle
konsol tabanl I/Onun ender olarak kullanld Windows gibi bir GUI ortamnda kullanldr.
Genel olarak bir deerin biimlendirilmi karakter katar ile gsterimi iki yoldan elde
edilir. Bir yol String.Format() kullanmaktr. Dieri ise, standart nmerik tiplere zg
BLM 20: KARAKTER KATARLARI VE BMLENDRME

HERKES N C#
597
ToString() metoduna bir biim belirleyicisi aktarmaktr. Her iki yaklam da burada
incelenmektedir.
Deerleri Biimlendirmek in String.Format()
Kullanm
String tarafndan tanml Format() metotlarndan birini ararak biimlendirilmi bir
deer elde edebilirsiniz. Bunlar Tablo 20.4te gsterilmitir. Format(), WriteLine()a ok
benzer ekilde alr. Tek fark, Format()n biimlendirilmi kty konsola gndermek
yerine bunu karakter katar olarak dndrmesidir.
TABLO 20.4: Format Metotlar


Metot Tanm
public static string Format(string
str, object v)
str iindeki ilk biim komutuna gre vyi
biimlendirir. Biimlendirilmi verinin biim
komutunun yerine yerletirildii strn bir
kopyasn dndrr.
public static string Format(string
str, object v1, object v2)
str iindeki ilk biim komutuna gre v1i ve
ikinci biim komutuna gre v2yi
biimlendirir. Biimlendirilmi verinin biim
komutunun yerine yerletirildii strn bir
kopyasn dndrr.
public static string Format(string
str, object v1, object v2, object v3)
v1, v2 ve v3 str iinde karlk gelen
biim komutlarna gre biimlendirir.
Biimlendirilmi verinin biim komutlarnn
her biri yerine yerletirildii strn bir
kopyasn dndrr.
public static string Format(string
str, params object[ ] v)
v zerinden aktarlan deerleri str iindeki
biim komutlarna gre biimlendirir.
Biimlendirilmi verinin biim komutlarnn
her biri yerine yerletirildii strn bir
kopyasn dndrr.
public static string
Format(IFormatProvider fmtpvdr, string
str, params object[ ] v)
v zerinden aktarlan deerleri fmtpvdr
tarafndan belirtilen biim salaycsn
kullanarak str iindeki biim komutlarna
gre biimlendirir. Biimlendirilmi verinin
biim komutlarnn her biri yerine
yerletirildii strn bir kopyasn dndrr.
Biimleri gsteren nceki programn String.Format() kullanlarak yeniden yazlm
ekli aadadr. Program, nceki versiyon ile ayn kty retmektedir.
// Bir degeri bicimlendirmek icin String.Format() kullanir.

using System;

HERKES N C#
KISIM II C# KTPHANESN KEFETMEK

598

class FormatDemo [
public static void Msin() {
double v = 17688.65849;
double v2 = 0.15;
int x = 21;

string str = String.Format({0:F2}, v);
Console.WriteLine(str);

str = String.Format({0:N5}, v);
Console.WriteLine(str);

str = String.Format({0:e}, v);
Console.WriteLine(str) ;

str = String.Format({0:r}, v);
Console.WriteLine(str);

str = String.Format({0:p}, v2);
Console.WriteLine(str);

str = String.Format({0:X}, x);
Console.WriteLine(str);

str = String.Format({0:D12}, x);
Console.WriteLine(str);

str = String.Format({0:C}, 189.99);
Console.WriteLine(str);
}
}
Tpk WriteLine() gibi String.Format() da sradan metinleri biim belirleyicileriyle
birlikte kullanmanza imkan verir. Ayrca, birden fazla biim belirleyicisi ve deer de
kullanabilirsiniz. rnein, 1den 10a kadar saylarn aamal olarak toplamlarn ve
arpmlarn grntleyen aadaki program ele aln:
// Format()a daha yakindan bir bakis.

using System;

class FormatDemo2 {
public static void Main() {
int i;
int sum = 0;
int prod = 1;
string str;

/* 1 ile 10 arasindaki sayilarin asamali olarak
toplamlarini ve carpimlarini ekranda gosterir. */
for(i = 1; i <= 10; i++) {
sum += i;
prod *= i;
BLM 20: KARAKTER KATARLARI VE BMLENDRME

HERKES N C#
599
str = String.Format(Sum:{0,3:D} Product:{1,8:D},
sum, prod);
Console.WriteLine(str);
}
}
}
kt aada gsterilmitir:
Sum: 1 Product: 1
Sum: 3 Product: 2
Sum: 6 Product: 6
Sum: 10 Product: 24
Sum: 15 Product: 120
Sum: 21 Product: 720
Sum: 28 Product: 5040
Sum: 36 Product: 40320
Sum: 45 Product: 362880
Sum: 55 Product: 3628800
Programdaki u ifadeye zellikle dikkat edin:
str = String.Format(Sum:{0,3:D} Product:{1,8:D),
sum, prod);
Format()a yaplan bu ar, sum ve prod iin birer adet olmak zere iki biim
belirleyicisi iermektedir. Argman numaralarnn WriteLine() ile kullanrken belirtildikleri
ekliyle belirtildiklerine dikkat edin. Ayrca, Sum: gibi sradan metinlerin de dahil edildiini
dikkate aln. Bu metin, kt karakter katar araclyla aktarlr ve kt karakter katarnn bir
paras halini alr.
Verileri Biimlendirmek in ToString() Kullanm
Int32 ya da Double gibi standart nmerik yap tiplerinin tm iin, sz konusu deerin
biimlendirilmi karakter katar gsterimini elde etmek amacyla ToString()
kullanabilirsiniz. Bunun iin ToString()in u versiyonunu kullanacaksnz:
public string ToString (string fmt)
Bu ifade, metodu aran nesnenin karakter katar gsterimini, fmt zerinden aktarlan
biim belirleyicisi ile belirtilen ekliyle dndrr. rnein, aadaki program 188.99
deerinin para birimi olarak gsterimini C biim belirleyicisini kullanarak oluturur:
string str = 189.99.ToString(C);
Biim belirleyicisinin ToString()e dorudan aktarl ekline dikkat edin.
WriteLine() ya da Format() tarafndan kullanlan gml biim komutlarnn bir argman
numaras ve alan genilii bileeni salamasndan farkl olarak ToString() yalnzca biim
belirleyicisinin kendisini gerektirir.

HERKES N C#
KISIM II C# KTPHANESN KEFETMEK

600
Biimlendirilmi karakter katarlar elde etmek amacyla ToString() kullanan nceki
biim programnn yeniden yazlm versiyonu aadadr. Bu program da nceki versiyonlarla
ayn kty retir.
// Degerleri bicimlendirmek icin ToString() kullanir.

using System;

class ToStringDemo {
public static void Main() {
double v = 17688.65849;
double v2 = 0.15;
int x = 21;

string str = v.ToString(F2);
Console.WriteLine(str);

str = v.ToString(N5);
Console.WriteLine(str);

str = v.ToString(e);
Console.WriteLine(str);

str = v.ToString(r);
Console.WriteLine(str);

str = v2.ToString(p);
Console.WriteLine(str);

str = x.ToString(X);
Console.WriteLine(str);

str = x.ToString(D12);
Console.WriteLine(str);

str = 189.99.ToString(C);
Console.WriteLine(str);
}
}
zel Bir Nmerik Biim Oluturmak
nceden tanml biim belirleyicileri gayet kullanl olmalarna ramen C#, kimi zaman
resim biimi (picture format) olarak adlandrlan bir zellii kullanarak kendinize ait biim
tanmlamanza frsat verir. Resim biimi terimi u gerekten gelir: ktnn nasl grnmesini
istiyorsanz, bunu bir rnekle (yani, resim) belirterek kendi biiminizi oluturursunuz. Bu
yaklam Ksm Ide ksaca bahsedilmiti. Burada ayrntlaryla incelenmektedir.


BLM 20: KARAKTER KATARLARI VE BMLENDRME

HERKES N C#
601
zel Biim Yer Tutucu Karakterleri
Kendi biiminizi olutururken verinin nasl grnmesini istiyorsanz bunun bir rneini (ya
da resmini) oluturarak biiminizi belirtirsiniz. Bunun iin Tablo 20.5te gsterilen karakterleri
yer tutucu olarak kullanrsnz. Bu karakterlerin her biri srayla incelenmitir.
Nokta, ondalk noktann nereye konumlandrlacan belirtir.
# yer tutucusu bir basamak konumunu belirtir. #, ondalk noktann solunda ya da sanda
veya tek bana yer alabilir. Ondalk noktann sanda bir ya da daha fazla # bulunursa bunlar
grntlenecek olan ondalk basamaklarn saysn belirtirler. Deer, gerekirse, yuvarlanr. #,
ondalk noktann solunda bulunursa sz konusu deerin tamsay ksm iin basamak
konumlarn belirtir. Gerektiinde deerin ba tarafna sfr eklenecektir. Eer deerin tamsay
ksm mevcut #lerden daha fazla basamaa sahipse tamsay ksmn btn grntlenir. Hi
bir durumda tamsay ksmn kesilmesi sz konusu deildir. Eer ondalk nokta yoksa #, sz
konusu deerin karlk gelen tamsay deere yuvarlanmasna neden olur. nemli olmayan sfr
deerleri, sz gelii deerin sonundaki sfrlar, grntlenmeyecektir. Bu kimi zaman tuhaf bir
duruma neden olur; eer biimlendirilen deer sfr ise ##.## gibi bir biim ekranda hi bir ey
gstermeyecektir. Sfr deerinin ktsn almak iin az sonra anlatlan 0 yer tutucusunu
kullann.
0 yer tutucusu, minimum sayda basaman mevcut olacan garanti etmek iin deerin
bana ya da sonuna 0 eklenmesine neden olur. Ondalk noktann hem sanda hem de solunda
kullanlabilir. rnein,
Console.WriteLine({0:00##.#00}, 21.3);
aadaki kty gsterir:
0021.300
Daha ok basamak ieren deerler ondalk noktann sol tarafnda tam olarak ve sa
tarafnda ise yuvarlanm olarak gsterileceklerdir.
# sekans iine virgl dahil eden bir model belirterek byk saylara virgl ekleyebilirsiniz.
rnein, u ifade
Console.WriteLine({0:#,###.#}, 3421.3);
unu gsterir:
3,421.3.
Her virgl konumu iin virgl belirtmeniz art deildir. Tek bir virgl belirtmeniz soldan
itibaren her basamakta bir bir virgl eklenmesine neden olur. rnein,
Console.WriteLine({0:#,###.#}, 8763421.3);
u kty retir:

HERKES N C#
KISIM II C# KTPHANESN KEFETMEK

602
8,703,421.3.
Virgllerin ikinci bir anlam daha vardr. Ondalk noktann hemen solunda bulunurlarsa
lekleme faktr olarak davranrlar. Her virgl, deerin 1,000e blnmesine neden olur.
rnein,
Console.WriteLine(Value in thousands: {0:#,###,.#}, 8763421.3);
u kty retir:
Value in thousands: 8,763.4
ktdan grld gibi, deer binlik oranda leklenmitir.
Yer tutuculara ek olarak kendi oluturduunuz biim belirleyicisi, dier karakterleri de
ierebilir. Dier karakterler, biim belirleyicisi iinde nasl grnyorlarsa biimlendirilmi ka-
rakter katar iinde de tamamen ayn ekilde grnerek aktarlrlar. rnein, u WriteLine()
ifadesi
Console.WriteLine(Fuel efficiency is {0:##.# mpg}, 21.3);
u kty retir:
Fuel efficiency is 21.3 mpg
Ayrca, eer gerekliyse, \t ya da \n gibi ka sekanslarn da kullanabilirsiniz.
E ve e yer tutucular, deerin bilimsel notasyonda grntlenmesine neden olurlar. E ya da
enin peinden en az bir adet, belki daha fazla, 0 gelmelidir. 0lar grntlenecek olan ondalk
basamak saysna iaret ederler. Ondalk bileen biime uymas iin yuvarlanacaktr. Byk
harf E kullanmak byk harf Enin grntlenmesine neden olur; kk harf e kullanmak ise
kk harf enin grntlenmesine neden olur. stn ncesinde bir iaret karakterinin
bulunmasn garanti etmek iin E+ ya da e+ biimlerini kullann. Yalnzca negatif deerler iin
iaret karakterini gstermek iin E, e, E- ya da e- kullann.
; pozitif, negatif ve sfr deerleri iin farkl biimler belirtmenizi mmkn klan bir
ayrcdr. ; kullanan ve kendi oluturduunuz biim belirleyicisi genel olarak u ekildedir:
pozitif-fmt;negatif-fmt;sfr-fmt
te bir rnek:
Console.WriteLine({0:#.##;(#.##);0.00}, num);
num eer pozitif ise deer iki ondalk basamak ile gsterilir. num, negatif ise deer, iki
ondalk basamak ile ve parantez iinde gsterilir. num, sfr ise 0.00 karakter katar gsterilir.
Ayrclar kullanrken btn paralarn yer almasna gerek yoktur. Yalnzca pozitif ve negatif
deerlerin nasl grneceini belirtmek istiyorsanz, sfr biimini dahil etmeyin. Negatif
deerler iin varsaylan biimi kullanmak amacyla negatif biimi dahil etmeyin. Bu durumda,
pozitif biim ve sfr biimi iki noktal virgl ile ayrlacaktr.
BLM 20: KARAKTER KATARLARI VE BMLENDRME

HERKES N C#
603
Aadaki program sizin oluturabileceiniz olas birok biimden yalnzca birkan
gstermektedir:
// ozel bicimleri kullanir.

using System;

class PictureFormatDemo {
public static void Main() {
double num = 64354.2345;

Console.WriteLine(Default format: + num);

// 2 ondalik basamakla goster.
Console.WriteLine(Value with two decimal places: +
{0:#.##}, num);

// Virgul ve 2 ondalik basamak ile gosterir.
Console.WriteLine(Add commas: {0:#,###.##}, num);

// Bilimsel notasyon kullanarak gosterir.
Console.WriteLine(Use scientific notation: +
{0:#.###e+00}, num);

// Degeri 1000 ile lcekler.
Console.WriteLine(Value in 1,000s: + {0:#0,}, num);

/* Pozitif, negatif ve sifir degerlerini farkli
farkli gosterir. */
Console.WriteLine(Display positive, negative, +
and zero values differently.);
Console.WriteLine({0:#.#;(#.##);0.00}, num);
num = -num;
Console.WriteLine({0:#.##;(#.##);0.00}, num);
num = 0.0;
Console.WriteLine({0:#.##;(#.##);0.00}, num);

// Yuzde gosterir.
num = 0.17;
Console.WriteLine(Display a percentage: {0:#%}, num);
}
}
kt aada gsterilmitir:
Default format: 64354.2345
Value with two decimal places: 64354.23
Add commas: 64,354.23
Use scientific notation: 6.435e+04
Value in 1,000s: 64
Display positive, negative, and zero values differently.
64354.2
(64354.23)
0.00
Display a percentage: 17%

HERKES N C#
KISIM II C# KTPHANESN KEFETMEK

604
TABLO 20.5: zel Biim Yer Tutucu Karakterleri


Yer Tutucu Anlam
# Rakam.
. Ondalk nokta.
, Binlik ayrc.
% Yzde.
0 Deerin bana ya da sonuna sfr doldurur.
; Pozitif, negatif ve sfr deerleri iin biimi tarif eden ayr blmler.
E0 E+0 E-0 e0 e+0 e-0 Bilimsel notasyon.
Tarih ve Saati Biimlendirmek
Nmerik deerleri biimlendirmeye ek olarak biimlendirmenin ska uyguland bir
dier veri tipi de DateTimedr Blm 19da akland gibi, DateTime tarih ve saati
simgeler. Tarih ve saat deerleri eitli ekillerde gsterilebilir. te bu rneklerden birka:
02/25/2002
Monday, February 25, 2002
12:59:00
12:59:00 PM
Ayrca, tarih ve saat gsterimleri lkeden lkeye deiiklik gsterebilir. Bu nedenlerden
tr, C# tarih ve saat deerleri iin ok kapsaml biimlendirme alt sistemi salamaktadr.
Tarih ve saatin biimlendirilmesi biim belirleyicileri araclyla ele alnr. Tarih ve saat
iin biim belirleyicileri Tablo 20.6da gsterilmitir. Spesifik tarih ve saat gsterimi lkeden
lkeye, dilden dile deiebildii iin, hazrlanan kusursuz gsterim, bilgisayarn kltrel
ayarlamalarndan etkilenecektir.
TABLO 20.6: Tarih ve Saat Biim Belirleyicileri


Belirleyici Biim
D Uzun biimde tarih.
d Ksa biimde tarih.
T Uzun biimde saat.
t Ksa biimde saat.
F Uzun biimde tarih ve saat.
f Ksa biimde tarih ve saat.
G Tarih ksa biimde, saat uzun biimde.
BLM 20: KARAKTER KATARLARI VE BMLENDRME

HERKES N C#
605
g Tarih uzun biimde, saat ksa biimde.
M Ay ve gn.
m M ile ayn.
R Tarih ve saat standart, GMT biiminde.
r R ile ayn.
s Tarih ve saat sralanabilir biimde.
U Uzun; evrensel sralanabilir biimde tarih ve saat; saat UTC olarak gsterilir.
u Ksa; evrensel sralanabilir biimde tarih ve saat.
Y Ay ve yl.
y Y ile ayn.
te, tarih ve saat biim belirleyicilerini gsteren bir program:
// Tarih ve saat bilgilerini bicimlendir.

using System;

class TimeAndDateFormatDemo {
public static void Main() {
DateTime dt = DateTime.Now; // su anki saati al

Console.WriteLine(d format: {0:d}, dt);
Console.WriteLine(D format: {0:D}, dt);

Console.WriteLine(t format: {0:t}, dt);
Console.WriteLine(T format: {0:T}, dt);

Console.WriteLine(f format: {0:f}, dt);
Console.WriteLine(F format: {0:F}, dt);

Console.WriteLine(g format: {0:g}, dt);
Console.WriteLine(G format: {0:G}, dt);

Console.WriteLine(m format: {0:m}, dt);
Console.WriteLine(M format: {0:M}, dt);

Console.WriteLine(r format: {0:r}, dt);
Console.WriteLine(R format: {0:R}, dt);

Console.WriteLine(s format: {0:s}, dt);

Console.WriteLine(u format: {0:u}, dt);
Console.WriteLine(U format: {0:U}, dt);

Console.WriteLine(y format: {0:y}, dt);
Console.WriteLine(Y format: {0:Y}, dt);
}
}

HERKES N C#
KISIM II C# KTPHANESN KEFETMEK

606
rnek kt aada gsterilmitir:
d format: 2/28/2002
D format: Thursday, February 28, 2002
t format: 9:32 AM
T format: 9:32:34 AM
f format: Thursday, February 28, 2002 9:32 AM
F format: Thursday, February 28, 2002 9:32:34 AM
g format: 2/28/2002 9:32 AM
G format: 2/28/2002 9:32:34 AM
m format: February 28
M format: February 28
r format: Thu, 28 Feb 2002 09:32:34 GMT
R format: Thu, 28 Feb 2002 09:32:34 GMT
s format: 2002-02-28T09:32:34
u format: 2002-02-28 09:32:34Z
U format: Thursday, February 28, 2002 3:32:34 PM
y format: February, 2002
Y format: February, 2002
Bir sonraki program ok basit bir saat gelitirmektedir. Zaman saniyede bir gncellenir.
Her saat ba bilgisayarn zili alar. Biimlendirilmi saatin ktsn almadan nce deerini
elde etmek amacyla DateTimen ToString() metodu kullanlr. Eer saat ba olduysa,
biimlendirilmi saate zilin almasn salayan alarm karakteri (\a) eklenir.
// Basit bir saat.

using System;

class SimpleClock {
public static void Main() {
string t;
int seconds;

DateTime dt = DateTime.Now;
seconds = dt.Second;

for(;;) {
dt = DateTime.Now;

// saniyeler degisirse saati guncelle
if(seconds != dt.Second) {
seconds = dt.Second;

t = dt.ToString(T);

if(dt.Minute == 0 && dt.Second == 0)
t = t + \a; // saat basinda zili cal

Console.WriteLine();
}
}
}
}
BLM 20: KARAKTER KATARLARI VE BMLENDRME

HERKES N C#
607
zel Tarih ve Saat Biiminizi Oluturmak
Standart tarih ve saat biim belirleyicileri olaylarn byk ounluuna uygulanacak
olmasna ramen zel biimler de oluturabilirsiniz. Bu sre, daha nce bahsedilen, nmerik
tipler iin kendi biimlerinizi oluturmaya benzer. Aslnda, basite tarih ve saat bilgisinin nasl
grnmesini istiyorsanz, o ekilde bir rnek (resim) oluturursunuz. Kendinize zg bir tarih
ve saat biimi oluturmak iin Tablo 20.7de gsterilen yer gstericilerinden bir ya da daha
fazla kullanacaksnz.
Tablo 20.7yi incelerseniz, d, f, g, m, M, s ve t yer tutucularnn Tablo 20.6da gsterilen
tarih ve saat biim belirleyicileriyle ayn olduunu greceksiniz. Genel olarak, bu
karakterlerden biri olduu gibi kullanlrsa, biim belirleyicisi olarak yorumlanr Aksi halde,
bunun bir yer tutucu olduu varsaylr. Bu karakterlerden birinin olduu gibi kullanlmasn,
ancak yer tutucu olarak yorumlanmasn istiyorsanz, karakterin nnde % iaretini kullann.
Aadaki program, istenilen ekilde oluturulan tarih ve saat biimlerinden birkan
gstermektedir:
// Tarih ve saat bilgilerini bicimle.

using System;

class CustomTimeAndDateFormatsDemo {
public static void Main() {
DateTime dt = DateTime.Now;

Console.WriteLine(Time is {0:hh:mm tt}, dt);
Console.WriteLine(24 hour time is {0:hh:mm}, dt);
Console.WriteLine(Date is {0:ddd MMM dd, yyyy}, dt);

Console.WriteLine(Era: {0:gg}, dt);

Console.WriteLine(Time with seconds: +
{0:HH:mm:ss tt}, dt);

Console.WriteLine(Use m for day of month: {0:m}, dt);
Console.WriteLine(use m for minutes: {0:%m}, dt);
}
}
kt aada gsterilmitir:
Time is 01:49 PM
24 hour time is 01:49
Date is Thu Feb 28, 2002
Era: A.D.
Time with seconds: 13:49:28 PM
Use m far day of month: February 28
use m for minutes: 49


HERKES N C#
KISIM II C# KTPHANESN KEFETMEK

608
TABLO 20.7: zel Tarih ve Saat Yer Tutucu Karakterleri


Yer Tutucu Ne le Yer Deitirecei
d 1 ile 31 arasnda bir say olarak ayn gn.
dd 1 ile 31 arasnda bir say olarak ayn gn. 1 ile 9 arasndaki
deerlerin nne 0 eklenir.
ddd Haftann gnnn ksaltlm ismi.
dddd Haftann gnnn ksaltlmam ismi.
f, ff, fff, ffff,
fffff, ffffff, fffffff
Kesirli saniyeler. Ondalk basamak says flerin says ile belirtilir.
g a.
h 1 ile 12 arasnda bir say olarak saat.
hh 1 ile 12 arasnda bir say olarak saat. 1 ile 9 arasndaki deerlerin
nne 0 eklenir.
H 0 ile 23 arasnda bir say olarak saat.
HH 0 ile 23 arasnda bir say olarak saat. 0 ile 9 arasndaki deerlerin
nne 0 eklenir.
m Dakika. 0 ile 9 arasndaki deerlerin nne 0 eklenir.
mm Dakika.
M 1 ile 12 arasnda bir say olarak ay.
MM 1 ile 12 arasnda bir say olarak ay. 1 ile 9 arasndaki deerlerin nne
0 eklenir.
MMM Ksaltlm ay ismi.
MMMM Ksaltlmam ay ismi.
s Saniye
ss Saniye. 0 ile 9 arasndaki deerlerin nne 0 eklenir.
t A ya da P, A.M. ya da P.M. iin.
tt A.M. ya da P.M.
y Yalnzca tek rakam gerekmiyorsa, iki rakam ile belirtilen yl.
yy ki rakam ile belirtilen yl. 0 ile 9 arasndaki deerlerin nne 0
eklenir.
yyyy Drt rakam kullanlarak yl.
z Saat dilimi fark, saat cinsinden.
zz Saat dilimi fark, saat cinsinden. 0 ile 9 arasndaki deerlerin nne 0
eklenir.
BLM 20: KARAKTER KATARLARI VE BMLENDRME

HERKES N C#
609
zzz Saat dilimi fark, saat ve dakika cinsinden.
: Saat bileenleri iin ayrc.
/ Tarih bileenleri iin ayrc.
%fmt fmt ile ilikili standart biim.
Numaralandrmalar Biimlendirmek
C#, bir numaralandrma tarafndan tanmlanan deerleri biimlendirmenize olanak tanr.
Numaralandrma deerleri, genel olarak, kendi isimleri ya da deerleri kullanlarak
grntlenebilir. Numaralandrmalar iin biim belirleyicileri Tablo 20.8de gsterilmitir. G ve
F biimlerine zellikle dikkat edin. Bit alanlarn simgelemek iin kullanlacak
numaralandrmalarn nne Flags niteleyicisi yerletirilmelidir. Tipik olarak; bit alanlar,
bitleri ayr ayr simgeleyen deerleri tutarlar ve ikinin kuvvetleri olarak dzenlenirler. Flags
niteleyicisi mevcut ise, G belirleyicisi, sz konusu deerin geerli olduu varsaymyla, deeri
oluturan dier tm deerlerin isimlerini grntleyecektir. Eer sz konusu deer
numaralandrma ile tanmlanan iki ya da daha fazla alana VEYA uygulanmas ile
kurulabiliyorsa, F belirleyicisi deeri oluturan dier tm deerlerin isimlerini
grntleyecektir.
Aadaki program numaralandrma belirleyicilerini gstermektedir:
// Numaralandirmayi bicimlendirir.

using System;

class EnumFmtDemo {
enum Direction { North, South, East, West }
[Flags] enum Status { Ready = 0x1, OffLine = 0x2,
Waiting = 0x4, TransmitOK = 0x8,
RecieveOK = 0x10, OnLine = 0x20 }

public static void Main() {
Direction d = Direction.West;

Console.WriteLine({0:G}, d);
Console.WriteLine({0:F}, d);
Console.WriteLine({0:D}, d);
Console.WriteLine({0:X}, d);

Status s = Status.Ready | Status.TransmitOK;

Console.WriteLine({0:G}, s);
Console.WriteLine({0:F}, s);
Console.WriteLine({0:D}, s);
Console.WriteLine({0:X}, s);
}
}
kt aada gsterilmitir:

HERKES N C#
KISIM II C# KTPHANESN KEFETMEK

610
West
West
3
00000003
Ready, TransmitOK
Ready, TransmitOK
00000009

TABLO 20.8: Numaralandrma Biim Belirleyicileri


Belirleyici Anlam
G Szkonusu deerin ismini grntler. Numaralandrmann ncesinde Flags
niteleyicisi yer alyorsa, sz konusu deerin (deerin geerli olduu varsaymyla)
bir paras olan tm isimler ekranda gsterilecektir.
g G ile ayn.
F Szkonusu deerin ismini grntler. Ancak, eer deer numaralandrma ile
tanmlanan iki ya da daha fazla deere VEYA uygulanmas ile oluturulabiliyorsa,
sz konusu deerin bir paras olan tm isimler ekranda gsterilecektir. Bu
durum, Flags niteleyicisi belirtmi olsun ya da olmasn geerlidir.
f F ile ayn.
D Deeri onluk tabanda bir tamsay olarak gsterir.
d D ile ayn.
X Deeri onaltlk tabanda bir tamsay olarak gsterir. En az sekiz basamak
gsterildiini garanti etmek iin deerin ba tarafna sfrlar eklenebilir.
x X ile ayn.



Y R M B R N C B L M


OK KANALLI
PROGRAMLAMA





















21

HERKES N C#
KISIM II C# KTPHANESN KEFETMEK

612
C# birok yeni zellik iermesine ramen bu zelliklerden en heyecan verici olan C#n
ok kanall programlamay (multithreaded programming) standart olarak desteklemesidir. ok
kanall bir program paralel zamanl altrlabilen iki ya da daha fazla para ierir. Bu tr bir
programn her parasna kanal (thread) denir ve her kanal farkl bir alma yolu tanmlar.
Bylece; ok kanalllk, ok grevliliin (multitasking) zelletirilmi bir eklidir.
ok kanall programlama, C# dili ve .NET Framework iindeki snflar tarafndan
tanmlanan zelliklerin bir kombinasyonuna dayanr. ok kanalllk destei C#ta standart
olarak mevcut olduu iin dier dillerdeki ok kanalllkla ilgili problemlerin birou C#ta
minimize edilmi ya da tamamen ortadan kaldrlmtr.
ok Kanalllkla lgili Esaslar
ki ayr tipte ok grevlilik mevcuttur: Proses tabanl ve kanal tabanl. Her ikisi arasndaki
fark anlamak nemlidir. Bir proses aslnda almakta olan bir programdr. Bu nedenle, proses
tabanl ok grevlilik (process-based multitasking), bilgisayarnzn iki ya da daha fazla
program ezamanl olarak altrmasna olanak tanyan bir zelliktir. rnein, bir elektronik
form kullanrken ya da Internette gezinirken ayn anda kelime ilemcinizi de altrmanza
imkan veren, proses tabanl ok grevliliktir. Proses tabanl ok grevlilikte bir program,
planlayc (scheduler) tarafndan ileme gnderilen en kk kod birimidir.
Bir kanal ileme gnderilebilen altrlabilir kod birimidir. smi, alma kanal
kavramndan gelir. Kanal tabanl ok grevlilik (thread-based multitasking) ortamnda tm
proseslerin en az bir kanal vardr, fakat daha fazla kanallar da olabilir. Bu, tek bir program bir
kerede iki ya da daha fazla grev gerekletirebilir, demektir. Sz gelii, bir metin editr
metni basarken, ayn anda biimlendirebilir. Elbette her iki faaliyet iki ayr kanal tarafndan
gerekletirildii srece bu geerlidir.
Proses tabanl ve kanal tabanl ok grevlilik arasndaki farklar u ekilde zetlenebilir:
Proses tabanl ok grevlilik, programlarn ezamanl olarak altrlmasn kontrol altna alr.
Kanal tabanl ok grevlilik ise ayn programn paralarnn ezamanl olarak altrlmasyla
ilgilenir.
ok kanallln balca avantaj ok verimli programlar yazmanz mmkn klmasdr,
nk ok kanalllk, pek ok programda mevcut olan bo zaman deerlendirmenize imkan
verir. Muhtemelen biliyorsunuzdur, I/O cihazlarnn birou, ister a portu, ister disk srcs
ya da klavye olsun, CPUdan ok daha yavatr. Bu nedenle, bir program alma zamannn
byk ounluunu bir cihaza bilgi gndermek ya da cihazdan bilgi almak iin beklemekle
harcayacaktr. ok kanalllk sayesinde, bu bo zamanda programnz bir baka grevi
altrabilir. Sz gelii, programnzn bir blm Internet zerinden bir dosya gnderirken, bir
baka blm klavyeden girdi okuyabilir, dier bir blm de gnderilecek bir sonraki veri
blounu tampona yerletirebilir.
Bir kanal birka durumdan birinde olabilir. Kanal alyor olabilir. CPU zamann ele
geirir geirmez almaya hazr olabilir. almakta olan bir kanal, almas geici olarak
BLM 21: OK KANALLI PROGRAMLAMA

HERKES N C#
613
durdurularak askya alnm olabilir. almasn daha sonra kald yerden srdrebilir. Bir
kayna bekliyorken bloke edilmi olabilir. Ya da sonlandrlm olabilir; bu durumda kanaln
almas biter ve kanal srdrlemez.
.NET Framework iki tip kanal tanmlar: n plan (foreground) ve arka plan (background).
Bir kanal oluturduunuzda, bu varsaylan deeri ile bir n plan kanaldr. Fakat bunu arka plan
kanala evirebilirsiniz. n plan ve arka plan kanallar arsndaki tek fark, bir arka plan kanaln
kendi prosesindeki tm n plan kanallar durduktan sonra otomatik olarak sonlandrlmasdr.
Kanal tabanl ok grevlilikler birlikte senkronizasyon (synchronization) denilen zel tipte
bir zellie gereksinim duyulmaktadr. Senkronizasyon, iyi tanmlanm belirli yntemlerle
kanallarn almasnn koordine edilmesine olanak tanr. C#, senkronizasyona adanm komple
bir alt sisteme sahiptir ve bu sistemin temel zellikleri de ayrca burada anlatlmaktadr.
Tm prosesler en azndan bir alma kanalna sahiptir. Bu kanal genellikle temel kanal
(main thread) olarak adlandrlr, nk programnz baladnda altrlacak olan, bu kanal-
dr. yleyse, bu kitaptaki nceki rnek programlarn tmnde kullanlmakta olan kanal, temel
kanaldr. Temel kanaldan dier kanallar oluturabilirsiniz.
C# ve .NET Framework hem proses tabanl ok grevlilii hem de kanal tabanl ok
grevlilii destekler. Bylece, C# kullanarak hem prosesleri hem de kanallar oluturup,
ynetebilirsiniz. Ancak, yeni bir proses balatmak iin biraz programlama yapmanz
gerekmektedir, nk her proses bir sonrakinden fazlasyla farkldr. Aslnda, nemli olan
C#n ok kanalllk desteidir. ok kanalllk destei sistemde standart olarak mevcut olduu
iin C#, yksek performansa sahip ok kanall programlarnn kurulumunu, C++ (ok kanalllk
iin standart bir destek iermez) gibi dier dillere kyasla daha da kolaylatrmaktadr.
ok kanall programlamay destekleyen snflar System.Threading isim uzaynda
tanmldr. Bu nedenle, aadaki ifadeyi genellikle ok kanall programlarn bana dahil
edeceksiniz:
using System.Threading;
Thread Snfnn Kullanm
C#n ok kanalllk sistemi, alma kanallarn paketleyen Thread snf zerine
kurulmutur. Thread snf sealed niteliindedir; yani, kaltm yoluyla aktarlamaz. Thread
snfnda kanallar ynetmeye yardmc olacak birka metot ve zellik tanmldr. Bu blm
iinde bu snfn en ok kullanlan yelerinden birka incelenecektir.
Bir Kanal Oluturmak
Bir kanal oluturmak iin Thread tipinde bir nesne rneklersiniz. Thread aadaki
yaplandrcy tanmlar:
public Thread(ThreadStart giriNoktas)

HERKES N C#
KISIM II C# KTPHANESN KEFETMEK

614
Burada giriNoktas, kanaln almasna balamas iin arlacak metodun addr.
ThreadStart, aada gsterildii ekliyle, .NET Framework tarafndan tanmlanan bir
delegedir:
public delegate void ThreadStart()
Yani, giri noktas niteliindeki metodunuz void dn deerine sahip olmal ve hi arg-
man almamaldr.
Bir kez oluturulduktan sonra yeni kanal, siz onun Start() metodunu arana kadar
almaya balamayacaktr. Start(), Thread tarafndan tanmlanmtr; u ekildedir:
public void Start()
Bir kez almaya baladktan sonra kanal, giriNoktas ile belirtilen metot dnene
kadar almaya devam edecektir. Bylece, giriNoktas dnnce kanal otomatik olarak
durur. Zaten almaya balam bir kanal zerinde Start() armay denerseniz bir
ThreadStateException frlatlacaktr.
Threadin System.Threading isim uzaynda tanmlandn hatrnzdan karmayn.
te, yeni bir kanaln oluturulduu ve altrld bir rnek:
// Bir calisma kanali olustur.

using System;
using System.Threading;

class MyThread {
public int count;
string thrdName;

public MyThread(string name) {
count = 0;
thrdName = name;
}

// kanalin giris noktasi.
public void run() {
Console.WriteLine(thrdName + starting.);

do {
Thread.Sleep(500);
Console.WriteLine(In + thrdName +
, count is + count);
count++;
} while(count < 10);

Console.WriteLine(thrdName + terminating.);
}
}

class MultiThread {
BLM 21: OK KANALLI PROGRAMLAMA

HERKES N C#
615
public static void Main() {
Console.WriteLine(Main thread starting.);

// Once, bir MyThread nesnesi yapilandir.
MyThread mt = new MyThread(Child #1);

// Sonra, bu nesneden bir kanal olustur.
Thread newThrd = new Thread(new ThreadStart(mt.run));

// Son olarak, kanali calistirmaya basla.
newThrd.Start();

do {
Console.Write(.);
Thread.Sleep(100);
} while (mt.count != 10);

Console.WriteLine(Main thread ending.);
}
}
imdi gelin bu programa yakndan bakalm. MyThread, ikinci bir alma kanal
oluturmak iin kullanlacak bir snf tanmlar. MyThreadin run() metodu iinde 0dan 9a
kadar sayan bir dng kurulur. Sleep()e yaplan arya dikkat edin. Sleep(), Thread
tarafndan tanmlanan static bir metottur. Sleep() metodu, iinden arld kanaln
almasnn belirtilen milisaniye sresince askya alnmasna neden olur. Programda kullanlan
ekli aada gsterilmitir:
public static void Sleep(int milisaniye)
Askda kalma sresi milisaniye ile belirtilir. Eer milisaniye sfr ise, arlan kanal
yalnzca bekleyen kanaln almasna imkan verecek kadar askda kalr.
Main() iinde, aadaki ifade sekans tarafndan yeni bir Thread nesnesi oluturulur:
// Once, bir MyThread nesnesi yapilandir.
My Thread mt = new MyThread(Child #1);

// Sonra, bu nesneden bir kanal olustur.
Thread newThrd = new Thread(new ThreadStart(mt.run));

// Son olarak, kanali calistirmaya basla.
newThrd.Start();
Aklamalarn gsterdii gibi, nce bir MyThread nesnesi oluturulur. Bu nesne daha
sonra bir Thread nesnesi yaplandrmak iin kullanlr. Bunun iin mt.run() metodu giri
noktas olarak aktarlr. Son olarak, Start() arlarak yeni kanaln almas balatlr. Bu,
ocuk kanaln run() metodunun balamasna neden olur. Start() ardktan sonra temel
kanaln almas Main()e dner ve Main()in do dngsne girer. Her iki kanal da
dngleri sona erene kadar CPUyu paylaarak almalarm srdrrler. Bu program
tarafndan retilen kt aadaki gibidir:

HERKES N C#
KISIM II C# KTPHANESN KEFETMEK

616
Main thread starting.
Child #1 starting.
......In Child #1, count is 0
.....In Child #1, count is 1
.....In Child #1, count is 2
.....In Child #1, count is 3
.....In Child #1, count is 4
.....In Child #1, count is 5
.....In Child #1, count is 6
.....In Child #1, count is 7
.....In Child #1, count is 8
.....In Child #1, count is 9
Child #1 terminating.
Main thread ending.
ok kanall bir programda genellikle, almas biten en son kanaln temel kanal olmasn
isteyeceksiniz. Bir program teknik olarak, tm n plan kanallar sona erene kadar almaya
devam eder. Bylece, temel kanaln almasn en son bitiren kanal olmasn salamak bir
gereklilik deildir. Yine de, bu uyulmasnda fayda olan bir uygulamadr, nk programnzn
biti noktasn net olarak tanmlamaktadr. nceki program temel kanaln en son olarak sona
ereceini garanti etmektedir, nk do dngs count 10a eit olunca durmaktadr. count,
ancak newThrd sona erdikten sona 10a eit olaca iin temel kanal en son olarak sona erer.
Bu blmn ileriki sayfalarnda bir kanaln bir dierinin sona ermesini beklemesiyle ilgili daha
iyi yntemler greceksiniz.
Baz Basit Yenilikler
nceki program kusursuz olmasna ramen baz kolay yenilikler bunu daha da verimli
klacaktr. ncelikle, bir kanaln oluturulur oluturulmaz almaya balamas mmkndr.
MyThread rneinde bu, MyThreadin yaplandrcs iinde bir Thread nesnesi rneklenerek
gerekletirilmektedir. kincisi, MyThreadin kanaln ismini saklamasna gerek yoktur, nk
Thread bu ama iin kullanlabilecek Name adnda bir zellik tanmlamaktadr. Name u
ekilde tanmlanmaktadr:
public string Name { get; set; }
Name salt okunur bir zellik olduu iin bir kanala isim vermek ya da kanaln ismini almak
iin bunu kullanabilirsiniz.
te, nceki program zerinde bu gelimeler uygulanarak elde edilen yeni versiyon:
// Bir kanali baslatmak icin alternatif yontem.

using System;
using System.Threading;

class MyThread {
public int count;
public Thread thrd;

BLM 21: OK KANALLI PROGRAMLAMA

HERKES N C#
617
public MyThread(string name) {
count = 0;
thrd = new Thread(new ThreadStart(this.run));
thrd.Name = name; // kanala isim ver.
thrd.Start(); // kanali baslat.
}

// Kanalin giris noktasi.
void run() {
Console.WriteLine(thrd.Name + starting.);

do {
Thread.Sleep(500);
Console.WriteLine(In + thrd.Name +
, count is + count);
count++;
} while(count < 10);

Console.WriteLine(thrd.Name + terminating.);
}
}

class MultiThreadImproved {
public static void Main() {
Console.writeLine(Main thread starting.);

// Once, bir MyThread nesnesi yapilandir.
MyThread mt = new MyThread(Child #1);
do {
Console.Write(.);
Thread.Sleep(100);
} while (mt.count != 10);

Console.WriteLine(Main thread ending.);
}
}
Bu versiyon nceki ile ayn kty retir. Kanal nesnesinin MyThread iinde thrdde
saklandna dikkat edin.
Birden Fazla Kanal Oluturmak
nceki rnekler yalnzca tek ocuk kanal oluturmulard. Ancak, sizin programnz
gerektii kadar ok sayda kanal retebilir. rnein, aadaki program ocuk kanal
oluturmaktadr:
// Birden fazla calisma kanali olustur.

using System;
using System.Threading;

class MyThread {
public int count;

HERKES N C#
KISIM II C# KTPHANESN KEFETMEK

618
public Thread thrd;

public MyThread(string name) {
count = 0;
thrd = new Thread(new ThreadStart(this.run));
thrd.Name = name;
thrd.Start();
}

// Kanalin giris noktasi.
void run() {
Console.WriteLine(thrd.Name + starting.);

do {
Thread.Sleep(500);
Console.WriteLine(In + thrd.Name +
, count is + count);
count++;
} while(count < 10);

Console.WriteLine(thrd.Name + terminating.);
}
}

class MoreThreads {
public static void Main() {
Console.WriteLine(Main thread starting.);

// Uc kanal yapilandir.
MyThread mt1 = new MyThread(Child #1);
MyThread mt2 = new MyThread(Child #2);
MyThread mt3 = new MyThread(Child #3);

do {
Console.Write(.);
Thread.Sleep(100);
} while (mt1.count 10 ||
mt2.count 10 ||
mt3.count 10);

Console.WriteLine(Main thread ending.);
}
}
Bu programn rnek kts aada gsterilmitir;
.
Main thread starting.
.Child #1 starting.
Child #2 starting.
Child #3 starting.
....In Child #1, count is 0
In Child #2, count is 0
In Child #3, count is 0
.....In Child #1, count is 1
In Child #2, count is 1
BLM 21: OK KANALLI PROGRAMLAMA

HERKES N C#
619
In Child #3, count is 1
.....In Child #1, count is 2
In Child #2, count is 2
In Child #3, count is 2
.....In Child #1, count is 3
In Child #2, count is 3
In Child #3, count is 3
.....In Child #1, count is 4
In Child #2, count is 4
In Child #3, count is 4
.....In Child #1, count is 5
In Child #2, count is 5
In Child #3, count is 5
.....In Child #1, count is 6
In Child #2, count is 6
In Child #3, count is 6
.....In Child #1, count is 7
In Child #2, count is 7
In Child #2, count is 7
.....In Child #1, count is 8
In Child #2, count is 8
In Child #3, count is 8
.....In Child #1, count is 9
Child #1 terminating.
In Child #2, count is 9
Child #2 terminating.
In Child #3, count is 9
Child #3 terminating.
Main thread ending.
Grdnz gibi, bir kez almaya baladktan sonra ocuk kanallarn de CPUyu
paylamaktadrlar. Sistem konfigrasyonlar, iletim sistemleri ve dier evresel etmenler
arasndaki farkllklar yznden programnz altrdnzda sizin greceiniz kt burada
gsterilenden bir para farkl olabilir.
alma Kanalnn Ne Zaman Sona Ereceini
Belirlemek
Bir alma kanalnn ne zaman sona ermi olduunu bilmek genellikle yararldr. nceki
rneklerde bu, count deikeni izlenerek gerekletirilmiti - bu hemon hemen hi tatmin
edici ya da genelletirilebilir bir zm deildir. Neyse ki; Thread, bir kanaln sona erip
ermediini belirleyebilmeniz iin iki yntem salamaktadr. Birincisi, sz konusu kanal iin,
salt okunur bir zellik olan IsAlive sorgulayabilirsiniz. Bu zellik u ekilde tanmlanr:
public bool IsAlive { get; }
IsAliven zerinde arld alma kanal halen alyor ise IsAlive, true
dndrr. Aksi halde false dndrr. IsAlive denemek iin MoreThreadsin u
versiyonunu nceki programda gsterilenle deitirin:

HERKES N C#
KISIM II C# KTPHANESN KEFETMEK

620
// Kanallarin sona ermelerini beklemek iin IsAlive kullanin.
class MoreThreads {
public static void Main() {
Console.WriteLine(Main thread starting.);

// Uc kanal yapilandir.
MyThread mt1 = new MyThread(Child #1);
MyThread mt2 = new MyThread(Child #2);
MyThread mt3 = new MyThread(Child #3);

do {
Console.Write(.);
Thread.Sleep(100);
}

while (mt1.thrd.IsAlive &&
mt2.thrd.IsAlive &&
mt3.thrdIsAlive);

Console.WriteLine(Main thread ending.);
}
}
Bu versiyon nceki ile ayn kty retir. kisi arasndaki tek fark, ocuk kanallarn sona
ermelerini beklemek iin bu versiyonda IsAlive kullanlmasdr.
Bir alma kanalnn sona ermesini beklemek iin bir baka yol Join()i armaktr.
Bunun en basit ekli aada gsterilmitir:
public void Join()
Join(), kendisinin zerinde arld kanal sona erene kadar bekler. Join (katlma)
ismi u kavramdan gelmektedir: arda bulunan kanal, belirtilen kanal kendisine katlana
kadar bekler.
Eer sz konusu kanal balatlmamsa bir ThreadStateException frlatlacaktr.
Join()in ilave biimleri, belirtilen kanaln sona ermesi iin beklemek istediiniz maksimum
sreyi belirtmenize olanak tanr.
Temel kanaln sona eren en son kanal olduunu garanti etmek iin Join() kullanan bir
program aada gsterilmitir:
// Join{) kullanir.

using System;
using System.Threading;

class MyThread {
public int count;
public Thread thrd;

public MyThread(string name) {
count = 0;
BLM 21: OK KANALLI PROGRAMLAMA

HERKES N C#
621
thrd = new Thread(new ThreadStart(this.run));
thrd.Name = name;
thrd.Start();
}

// Kanalin giris noktasi.
void run() {
Console.WriteLine(thrd.Name + starting.);

do {
Thread.Sleep(500);
Console.WriteLine(In + thrd.Name +
, count is + count);
count++;
}

while(count < 10);

Console.WriteLine(thrd.Name + terminating.);
}
}

// Kanallarin sona ermesini beklemek icin Join() kullan.
class JoinThreads {
public static void Main() {
Console.WriteLine(Main thread starting.);

// Uc kanal yapilandir.
MyThread mt1 = new MyThread(Child #1);
MyThread mt2 = new MyThread(Child #2);
MyThread mt3 = new MyThread(Child #3);

mt1.thrd.Join();
Console.WriteLine(Child #1 joined.);

mt2.thrd.Join();
Console.WriteLine(Child #2 joined.);

mt3.thrd.Join();
Console.WriteLine(Child #3 joined.);

Console.WriteLine(Main thread ending.);
}
}
Bu programdan elde edilen rnek kt aada gsterilmitir. Program denediinizde sizin
ktnzn biraz farkl olabileceini hatrlayn.
Main thread starting.
Child #1 starting.
Child #2 starting.
Child #3 starting.
In Child #1, count is 0
In Child #2, count is 0
In Child #3, count is 0

HERKES N C#
KISIM II C# KTPHANESN KEFETMEK

622
In Child #1, count is 1
In Child #2, count is 1
In Child #3, count is 1
In Child #1, count is 2
In Child #2, count is 2
In Child #3, count is 2
In Child #1, count is 3
In Child #2, count is 3
In Child #3, count is 3
In Child #1, count is 4
In Child #2, count is 4
In Child #3, count is 4
In Child #1, count is 5
In Child #2, count is 5
In Child #3, count is 5
In Child #1, count is 6
In Child #2, count is 6
In Child #3, count is 6
In Child #1, count is 7
In Child #2, count is 7
In Child #3, count is 7
In Child #1, count is 8
In Child #2, count is 8
In Child #3, count is 8
In Child #1, count is 9
Child #1 terminating.
In Child #2, count is 9
Child #2 terminating.
In Child #3, count is 9
Child #3 terminating.
Child #1 joined.
Child #2 joined.
Child #3 joined.
Main thread ending.
Grdnz gibi, Join()e yaplan arlar geri dndkten sonra kanallar almay
durdurmulardr.
IsBackground zellii
nceden bahsedildii gibi, .NET Framework iki tr kanal tanmlamaktadr: n plan ve arka
plan. Bu ikisi arasndaki tek fark udur: Bir proses tm n plan kanallar sona erene kadar
sonlanmayacaktr; fakat, arka plan kanallar, tm n plan kanallar durduktan sonra sona erer.
Bir kanaln varsaylan oluturulma ekli n plan kanal biimindedir. Fakat bu, Thread tarafn-
dan tanmlanan ve aada gsterilen IsBackground zellii kullanlarak arka plan kanalna
dntrlebilir:
public bool IsBackground { get; set; }
Bir kanal arka plan kanal olarak ayarlamak iin yalnzca IsBackgrounda true deeri
atamanz yeterlidir. false deeri n plan kanalna iaret eder.
BLM 21: OK KANALLI PROGRAMLAMA

HERKES N C#
623
Kanal ncelikleri
Her alma kanal kendisiyle ilintili bir ncelik ayarlamasna sahiptir. Bir kanaln ncelii,
ksmen, bir kanaln ne kadar CPU zaman alacan belirler. Genel olarak, dk ncelikli
kanallar az CPU zaman alrlar. Yksek ncelikli kanallar ok CPU zaman gerektirirler.
Tahmin edebileceiniz gibi, bir kanaln ne kadar CPU zaman ald kanaln alma
zelliklerini ve sistemde halen almakta olan dier kanallarla etkileimini derinden etkiler.
Bir kanaln ne kadar CPU zaman alacan kanaln nceliinden baka etmenlerin de
etkileyebileceini kavramak nemlidir. Sz gelii, yksek ncelikli bir kanal eer bir kayna,
belki klavyeden gelecek girdiyi bekliyorsa, bu kanal bloke edilecek ve daha dk ncelie
sahip bir kanal alacaktr. Bylece, bu durumda dk ncelikli kanal, belirli bir sre iinde
yksek ncelikli kanala kyasla daha fazla CPU eriimi kazanabilir.
Bir ocuk kanal balatlnca bu kanal bir varsaylan ncelik ayarlamas alr. Bir kanaln
nceliini, Threadin bir yesi olan Priority zellii araclyla deitirebilirsiniz. Bu
zelliin genel olarak kullanm u ekildedir:
public Thread Priority Priority{ get; set; }
ThreadPriority, aadaki be ncelik ayarlamasn tanmlayan bir numaralandrmadr:
ThreadPriority.Highest
ThreadPriority.AboveNormal
ThreadPriority.Normal
ThreadPriority.BelowNormal
ThreadPriority.Lowest
Bir kanal iin varsaylan ncelik ThreadPriority.Normaldir.
nceliklerin, kanallarn almasn nasl etkilediini anlamak iin biri dierinden daha
yksek ncelie sahip iki kanal altran bir rnek kullanacaz. Sz konusu kanallar
MyThread snfnn rnekleri olarak oluturulurlar. run() metodu tekrarlamalarn saysn
sayan bir dng ierir. Dng ya toplam 1,000,000,000a ulanca ya da static deiken
stop, true deerine sahip olunca durur Balangta stop, false olarak ayarlanr.
1,000.000,000a sayan ilk kanal stopa true deerini verir. Bu durum ikinci kanaln bir
sonraki zaman diliminde sona ermesine neden olur. Dngnn her tekrarnda currentName
iindeki karakter katar, almakta olan kanaln ismi ile karlatrlr. Eer bunlar
elemiyorsa, bir grev deiimi meydana geldi demektir. Her grev deiikliinde yeni
kanaln ismi ekranda grntlenir ve currentNamee yeni kanaln ad verilir. Bu, her kanaln
CPUya hangi sklkla eritiini izlemenize imkan verir. Her iki kanal da durduktan sonra her
dngnn tekrar says ekranda gsterilir.
// Kanal onceliklerini gosterir.

using System;
using System.Threading;


HERKES N C#
KISIM II C# KTPHANESN KEFETMEK

624
class MyThread {
public int count;
public Thread thrd;

static bool stop = false;
static string currentName;

/* Yeni bir kanal yapilandir. Dikkat ederseniz,
bu yapilandirici aslinda calismakta olan
kanallari baslatmiyor. */
public MyThread(string name) {
count = 0;
thrd = new Thread(new ThreadStart(this.run));
thrd.Name = name;
currentName = name;
}

// Yeni kanalin calismasini baslat.
void run() {
Console.WriteLine(thrd.Name + starting.);
do {
count++;

if(currentName != thrd.Name) {
currentName = thrd.Name;
Console.WriteLine(In + currentName);
}
} while(stop == false && count < 1000000000);
stop = true;

Console.WriteLine(thrd.Name + terminating.);
}
}

class PriorityDemo {
public static void Main() {
MyThread mt1 = new MyThread(High Priority);
MyThread mt2 = new MyThread(Low Priority);

// Oncelik sirasini ayarla.
mt1.thrd.Priority = ThreadPriority.AboveNormal;
mt2.thrd.Priority = ThreadPriority.BelowNormal;

// Kanallari baslat.
mt1.thrd.Start();
mt2.thrd.Start();

mt1.thrd.Join();
mt2.thrd.Join();

Console.WriteLine();
Console.WriteLine(mt1.thrd.Name + thread counted to +
mt1.count);
Console.WriteLine(mt2.thrd.Name + thread counted to +
mt2.count);
BLM 21: OK KANALLI PROGRAMLAMA

HERKES N C#
625
}
}
Program, 1 GHz Pentium tabanl bir bilgisayarda, Windows 2000 iletim sistemi altnda
altrldnda aadaki kt elde edilmitir:
High Priority starting.
In High Priority
Low Priority starting.
In Low Priority
In High Priority
In Low Priority
In High Priority
In Low Priority
In High Priority
In Low Priority
In High Priority
In Low Priority
In High Priority
High Priority terminating.
Low Priority terminating.

High Priority thread counted to 1,000,000,000
Low Priority thread counted to 25,600,064
Programn bu almasnda yksek ncelikli kanal, CPU zamannn yaklak yzde 98ini
elinde bulundurdu. CPUnuzun hzna ve sistemde almakta olan dier grevlerin saysna
bal olarak sizin grdnz tam kt elbette farkllk gsterebilir. Windowsun hangi
versiyonunu altrdnz bile sonucu etkileyebilmektedir.
ok kanall kod farkl ortamlarda farkl davranabildii iin, kodunuzu asla tek bir ortamn
alma zelliklerine dayandrmamalsnz. rnein, nceki rnekte yksek ncelikli kanal
sona ermeden nce dk ncelikli kanaln daima, en azndan, ksa bir sre alacan
varsaymak yanl olur. Farkl bir ortamda, rnein dk ncelikli kanal henz bir kez bile
almadan nce yksek ncelikli kanal almasn tamamlayabilir.
Senkronizasyon
Birden fazla alma kanal kullanlrken iki ya da daha fazla kanaln faaliyetlerinin bir
program tarafndan koordine edilmesi kimi zaman gerekli olabilir. Bu tr bir durumun elde
edildii sre senkronizasyon (synchronization) olarak adlandrlr. Senkronizasyon
kullanmnn en yaygn gerekesi, bir anda yalnzca tek bir kanal tarafndan kullanlabilen bir
kaynaa iki ya da daha fazla kanaln erimeleri gerektiinde ortaya kar. rnein, bir kanal bir
dosyaya yazarken, ikinci bir kanaln ayn anda ayn ilemi gerekletirmesi nlenmelidir.
Senkronizasyonun gerekli olduu bir baka durum, bir kanaln baka bir kanaln neden olduu
bir olay beklemesidir. Bu durumda, olay meydana gelene kadar ilk kanal asl durumda
tutabilecek baz yntemler gereklidir. Sonra, bekleyen kanal almasn srdrmelidir.

HERKES N C#
KISIM II C# KTPHANESN KEFETMEK

626
Senkronizasyonun en temel zellii kilit (lock) kavramdr. Kilit, bir nesne iindeki kod
blouna eriimi kontrol eder. Bir nesne bir kanal tarafndan kilitlenince dier kanallarn hibiri
kilitli kod blouna eriim elde edemez. Sz konusu kanal kilidi kaldrnca nesne bir baka
kanaln kullanmna hazrdr.
Kilit zellii C# diline entegre standart bir zelliktir. Bu sayede, tm nesneler senkronize
edilebilir. Senkronizasyon lock anahtar kelimesi ile desteklenir. Senkronizasyon, C#n en
banda tasarlanm olduu iin, kullanm beklediinizden ok daha kolaydr. Aslnda,
program iin nesnelerin senkronizasyonu hemen hemen aktr.
lockun genel olarak kullanm aada gsterilmitir:
lock(nesne) {
// senkronize edilecek ifadeler
}
Burada nesne, senkronize edilmekte olan nesneye bir referanstr. Yalmzca tek bir ifadeyi
senkronize etmek istiyorsanz, kme parantezlerine gerek yoktur. lock ifadesi, verilen nesne
iin kilit ile korunan kod blmnn yalnzca kilidi alan kanal tarafndan kullanlabileceini
garanti eder. Kilit kaldrlana kadar dier tm kanallar bloke edilir. Kilit, bloktan klnca
kaldrlr.
Aadaki program, sumIt() adnda bir metoda eriimi kontrol ederek senkronizasyonun
kullanmn gstermektedir. sumIt(), bir tamsay dizisinin elemanlarn toplar:
// Bir nesneye erisimi senkronize etmek icin kilit kullanir.

using System;
using System.Threading;

class SumArray {
int sum;

public int sumIt(int[] nums) {
lock(this) { // butun metodu kilitle.
sum = 0; // toplami sifirla.

for(int i = 0; i nums.Length; i++) {
sum += nums[i];
Console.WriteLine(Running total for +
Thread.CurrentThread.Name +
is + sum);
Thread.Sleep(10); // gorev degisimine olanak tani.
}
return sum;
}
}

class MyThread {
public Thread thrd;
int[] a;
int answer;
BLM 21: OK KANALLI PROGRAMLAMA

HERKES N C#
627

/* MyThreadin tum ornekleri icin bir SumArray nesnesi
olustur. */
static SumArray sa = new SumArray();

// Yeni bir kanal yapilandir.
public MyThread(string name, int[] nums) {
a = nums;
thrd = new Thread(new ThreadStart(this.run));
thrd.Name = name;
thrd.Start(); // kanali baslat.
}

// Yeni kanalin calismasini baslat.
void run() {
Console.WriteLine(thrd.Name + starting.);
answer = sa.sumIt(a);

Console.WriteLine(Sum for + thrd.Name +
is + answer);

Console.WriteLine(thrd.Name + terminating.);
}
}

class Sync {
public static void Main() {
int[] a = {1, 2, 3, 4, 5};

MyThread mt1 = new MyThread(Child #1, a);
MyThread mt2 = new MyThread(Child #2, a);

mt1.thrd.Join();
mt2.thrd.Join();
}
}
Programn kts aada gsterilmitir:
Child #1 starting.
Running total for Child #1 is 1
Child #2 starting.
Running total for Child #1 is 3
Running total for Child #1 is 6
Running total for Child #1 is 10
Running total for Child #1 is 15
Running total for Child #2 is 1
Sum for Child #1 is 15
Child #1 terminating.
Running total for Child #2 is 3
Running total for Child #2 is 6
Running total for Child #2 is 10
Running total for Child #2 is 15
Sum for Child #2 is 15
Child #2 terminating.

HERKES N C#
KISIM II C# KTPHANESN KEFETMEK

628
ktdan da grld gibi, her iki kanal da doru toplam, 15i hesaplamaktadrlar.
Gelin imdi program ayrntl olarak inceleyelim. Program, snf oluturur. lki
SumArraydir. SumArray, bir tamsay dizisinin elemanlarn toplayan sumIt() metodunu
tanmlar. kinci snf MyThreaddir. MyThread, SumArray tipinde sa olarak adlandrlan
static bir nesne kullanr. Bylece, SumArrayin yalnzca bir nesnesi MyThread tipindeki
tm nesneler tarafndan paylalr. Bu nesne, bir tamsay dizisinin elemanlarnn toplamn elde
etmek amacyla kullanlr. Dikkat ederseniz; SumArray, ara toplamlar sum adnda bir alanda
saklamaktadr. Bylece, eer iki kanal sumIt()i ezamanl olarak kullanrsa bu kanallarn her
ikisi de sum ara toplam tutmas iin kullanmaya alacaktr. Bu durum hatalara neden
olaca iin sumIt()e eriim senkronize edilmelidir. Son olarak, Sync snf iki alma
kanal oluturur ve bu kanallara tamsay dizisinin toplamn hesaplatr.
sumIt()in iinde lock ifadesi, metodun farkl kanallar tarafndan ezamanl kullanmn
nler. lockun senkronize edilecek nesne olarak thisi kullandna dikkat edin. arda
bulunan nesne kilitlenecei zaman lock normal olarak bu ekilde arlr. Sleep(), eer
mmknse - bu rnekte mmkn deildir - kasten bir grev deiimine olanak tanmak iin
arlr. sumIt()in iindeki kod kilitli olduu iin bir anda yalnzca tek bir kanal tarafndan
kullanlabilir. Bylece, ikinci ocuk kanal almaya balaynca birinci ocuk kanaln
sumIt()le ii bitene kadar ikinci ocuk kanal sumIt()e girmez. Bu, doru sonucun
retilmesini garanti eder.
lockun etkilerini tam olarak anlamak iin sumIt()in gvdesinden bunu kartmay
deneyin. Bunu gerekletirdikten sonra, sumIt() artk senkronize edilemez ve bunu herhangi
bir sayda kanal ayn nesne zerinde ezamanl olarak kullanabilir. Buradaki problem udur:
sum iinde saklanan ara toplamlar sumIt()i aran kanallarn her biri tarafndan
deitirilecektir. Bylece, iki alma kanal sumIt()i ayn anda ayn nesne zerinde
arnca, hatal sonular retilir, nk sum, her iki kanaln birbirine karm toplamlarn
yanstmaktadr.
rnein, sumIt()ten lock kaldrldktan sonra programdan alnan rnek kt yledir:
Child #1 starting.
Running total for Child #1 is 1
Child #2 starting.
Running total for Child #2 is 1
Running total for Child #1 is 3
Running total for Child #2 is 5
Running total for Child #1 is 8
Running total for Child #2 is 11
Running total for Child #1 is 15
Running total for Child #2 is 19
Running total for Child #1 is 24
Running total for Child #2 is 29
Sum for Child #1 is 29
Child #1 terminating.
Sum for Child #2 is 29
Child #2 terminating.
BLM 21: OK KANALLI PROGRAMLAMA

HERKES N C#
629
ktdan da grld gibi, her iki ocuk kanal da sumIt()i ayn anda ayn nesne
zerinde kullanyorlar ve sumn deeri bozuluyor.
lockun etkileri aada zetlenmitir:
1. Verilen herhangi bir nesne iin, bir kod blmne bir kez bir kilit yerletirildikten
sonra artk nesne kilitlenmitir ve dier kanallarn hibiri kilidi ele geiremez.

2. Ayn nesne zerindeki kilidi ele geirmeye alan dier kanallar kodun kilidi zlene
kadar bekleme durumuna gireceklerdir.

3. Bir kanal kilitli blou terk edince nesnenin kilidi zlr.
lock ile ilgili anlalmas gereken bir dier husus udur: lock yalnzca private ya da
internal nesneler zerinde kullanlmaldr. Eer bu tr bir durum sz konusu deilse,
programnzn dndaki herhangi bir program kanal kilidi ele geirip, brakmayabilir.
Alternatif Yaklam
Bir metodun kodunu kilitlemek, nceki rnekte gsterildii gibi, senkronizasyonu
salamak iin kolay ve etkin bir yol olmasna ramen her durumda almayabilir. Sz gelii,
kendinizin oluturmad bir snfn senkronize edilmemi bir metoduna eriimi senkronize
etmek isteyebilirsiniz. nc parti bir snf kullanmak isterseniz ve bu snfn kaynak koduna
eriim iznine sahip deilseniz byle bir durum ortaya kabilir. Bylece, sz konusu snfn
iindeki ilgili metoda bir lock ifadesi eklemeniz mmkn olmayabilir. Bu snfn bir nesnesine
eriim nasl senkronize edilebilir? Neyse ki, bu problemin zm basittir: Nesneyi bir lock
ifadesi iinde belirterek nesnenin dndaki kodun nesneye eriimini kilitleyin. rnein, nceki
programn alternatif uygulamas aada yer almaktadr. Dikkat ederseniz, sumIt()in iindeki
kod artk kilitli deildir. Bunun yerine, MyThread iinden sumIt()e yaplan arlar
kilitlenmitir.
/* Nesnenin erisimini senkronize etmek icin kilit kullaniminin
bir baska sekli. */

using System;
using System.Threading;

class SumArray {
int sum;

public int sumIt(int[] nums) {
sum = 0; // toplami sifirla.

for(int i = 0; i < nums.Length; i++) {
sum += nums[i];
Console.WriteLine(Running total for +
Thread.CurrentThread.Name +
is + sum);
Thread.Sleep(10); // gorev degisimine olanak tani.

HERKES N C#
KISIM II C# KTPHANESN KEFETMEK

630
}

return sum;
}
}

class MyThread {
public Thread thrd;
int[] a;
int answer;

/* MyThreadin tum ornekleri icin bir SumArray nesnesi
olustur. */
static SumArray sa = new SumArray();

// Yeni bir kanal yapilandir.
public MyThread(string name, int[] nums) {
a = nums;
thrd = new Thread(new ThreadStart(this.run));
thrd.Name = name;

thrd.Start(); // kanali baslat.
}

// Yeni kanalin calismasini baslat.
void run() {
Console.WriteLine(thrd.Name + starting.);

// sumIt()e yapilan cagrilari kilitle.
lock(sa) answer = sa.sumIt(a);

Console.WriteLine(Sum for + thrd.Name +
is + answer);

Console.WriteLine(thrd.Name + terminating.);
}
}
class Sync {
public static void Main() {
int[] a = {1, 2, 3, 4, 5};

MyThread mt1 = new MyThread(Child #1, a);
MyThread mt2 = new MyThread(Child #2, a);

mt1.thrd.Join();
mt2.thrd.Join();
}
}
Burada sumIt()in iindeki kodun kendisinin yerine sa.sumIt()e yaplan ar
kilitlenmitir. Bunu gerekletiren kod aada gsterilmitir:
// sumIt()e yapilan cagrilari kilitle.
lock(sa) answer = sa.sumIt(a);
BLM 21: OK KANALLI PROGRAMLAMA

HERKES N C#
631
Program, orijinal yaklamla ayn doru sonular retmektedir.
Bir Statik Metodu Kilitlemek
lock, bir nesne ile birlikte alt iin ilk bakta bir static metot iindeki kodu
kilitleyemeyeceinizi dnebilirsiniz, nk kilitlenecek bir nesne yoktur. Ancak bu yanltr.
Bir static metodu kilitlemek iin aadaki lock eklini kullann:
lock(typeof(snf)) {
// kilitlenen blok
}
Burada snf, static metodu ieren snfn addr.
Monitr Snf ve lock
C#n lock anahtar kelimesi aslnda Monitor snf tarafndan tanmlanan senkronizasyon
zelliklerini kullanmak iin yalnzca bir kestirme yoldur. Monitor, System.Threading isim
uzaynda tanmlanmtr. Monitor snfnda senkronizasyonu kontrol eden ya da yneten
birka metot tanmldr. rnein, bir nesne zerindeki kilidi elde etmek iin Enter() arn.
Bir kilidi kaldrmak iin Exit()i arn. Bu metotlar aada gsterilmitir;
public static void Enter(object senkNes)
public static void Exit(object senkNes)
Burada senkNes, senkronize edilmekte olan nesnedir. Enter() arld zaman sz
konusu nesne hazr deilse, arda bulunan kanal nesne hazr olana dek bekleyecektir.
Microsoft, bir lock blounun, Enter() ve sonra Exit()i armakla "tamamen edeer"
olduunu bildirmektedir. lock, C# iinde standart olarak mevcuttur. Bu nedenle lock, C# ile
programlama yaparken bir nesne zerinde kilit elde etmek iin tercih edilen bir metottur.
Monitor iindeki kullanl metotlardan biri TryEnter()dr. Bu metodun kullanm
ekillerinden biri aada gsterilmitir:
public static bool TryEnter(object senkNes)
arda bulunan alma kanal senkNes zerinde bir kilit elde ederse metot true
dndrr. Aksi halde, false dndrr. arda bulunan kanal hi bir durumda beklemez.
stenilen nesnenin hazr olmad durumlarda bu metodu bir alternatif olarak kullanabilirsiniz.
Monitorde ayrca u metot da tanmldr: Wait(), Pulse() ve PulseAll(). Bu
metotlar aada anlatlmtr.



HERKES N C#
KISIM II C# KTPHANESN KEFETMEK

632
Wait(), Pulse() ve PulseAll() Kullanarak Kanal
letiimi
yle bir durum dnn. T adnda bir alma kanal bir lock blou iinde alyor ve
geici olarak kullanma hazr R adnda bir kaynaa erimek istiyor. T ne yapmaldr? Eer T,
Ryi bekleyen bir tr yoklama dngsne girerse, bu durumda T, nesneyi balar ve dier
kanallarn nesneye eriimini de bloke eder. Bu, optimal zm kadar iyi bir zm deildir,
nk ok kanalllk ortam iin gerekletirilen programlamann avantajlarn ksmen
mahveder. Daha iyi bir zm, Tnin geici olarak nesnenin kontroln elinden brakarak, bir
baka kanaln almasna olanak tanmasdr. R elverili olduunda T durumdan haberdar
edilir ve almasn kald yerden srdrebilir. Byle bir yaklam, kanallar aras bir tr
iletiime dayanr. Bu iletiimde, bir kanal bloke edildiini bir dierine haber verebilir ve
almasn srdrebilecei zaman kendisi durumdan haberdar edilebilir. C# kanallar arasndaki
iletiimi Wait(), Pulse() ve PulseAll() metotlaryla destekler.
Wait(), Pulse() ve PulseAll() metotlar Monitor snf tarafndan tanmlanmtr.
Bu metotlar yalnzca kilitli kod blou iinden arlabilirler. u ekilde kullanlrlar: Bir
alma kanalnn almas geici olarak bloke edilmise, kanal Wait()i arr. Bu, kanaln
uykuya gemesine neden olur ve ilgili nesnenin kilidi kaldrlr. Bylece, bir baka kanaln
nesneyi kullanmasna imkan verilmi olur. Daha sonraki bir aamada, bir baka kanal ayn
kilide girmeye alnca ve Pulse() ya da PulseAll() arnca uyuyan kanal uyandrlr.
Pulse()a yaplan bir ar, kilidi bekleyen alma kanallar kuyruundaki ilk kanaln
almasn kald yerden srdrmesini salar. PulseAll()a yaplan bir ar, kildin
kaldrldn bekleyen kanallarn tmne iaret eder.
Wait()in en yaygn olarak kullanlan iki ekli yledir:
public static bool Wait(object bekleNes)
public static bool Wait(object bekleNes, int milisaniye)
lk ifadedeki Wait(), kendisine haber verilene kadar bekler. kinci ifadedeki Wait() ise,
haber verilene kadar ya da belirtilen milisaniye sresi dolana kadar bekler. Her ikisi iin de
bekleNes, zerinde beklenilecek olan nesneyi belirtir.
Pulse() ve PulseAll()n genel kullanmlar u ekildedir:
public static void Pulse(object bekleNes)
public static void PulseAll(object bekleNes)
Burada bekleNes, serbest braklmakta olan nesnedir.
Eer Wait(), Pulse() ya da PulsaAll() bir lock bloun iinde olmayan koddan
arlrlarsa bir SynchronizationLockException frlatlacaktr.
BLM 21: OK KANALLI PROGRAMLAMA

HERKES N C#
633
Wait() ve Pulse() Kullanan Bir rnek
Wait() ve Pulse() iin duyulan gereksinimi ve bunlarn uygulamalarn anlamak iin
ekranda Tick ve Tock szcklerini grntleyerek bir saatin almasn canlandran bir
program gelitireceiz. Bunu gerekletirmek iin iki metot ieren TickTock adnda bir snf
oluturacaz. Sz konusu metotlar tick() ve tock() olacak. tick() metodu, Tick
szcn ve tock() da Tock szcn ekranda gsterecek. Saati altrmak iin biri
tick()i aran ve dieri de tock()u aran iki alma kanal oluturulur. Burada ama
udur: ki kanalnn ileyiini yle ayarlamaldr ki, ekranda program kts olarak tutarl ve
srekli bir Tick Tock grnts - yani, her Tickten sonra bir Tock"un geldii tekrarlayan
bir desen - elde edilebilsin.
// Tikleyen bir saat olusturmak icin Wait() ve Pulse() kullanir.

using System;
using.System.Threading;

class TickTock {

public void tick(bool running) {
lock(this) {
if(!running) { // saati durdur
Monitor.Pulse(this); // bekleyen kanallari haberdar et
return;
}

Console.Write(Tick );
Monitor.Pulse(this); // tock()un calismasina izin ver

Monitor.Wait(this); // tock()un tamamlanmasini bekle
}
}

public void tock(bool running) {
lock(this) {
if(!running) { // saati durdur
Monitor.Pulse(this); // bekleyen kanallari haberdar et
return;
}

Console.WriteLine(Tock);
Monitor.Pulse(this); // tick()in calismasina izin ver

Monitor.Wait(this); // tick()in tamamlanmasini bekle
}
}
}

class MyThread {
public Thread thrd;
TickTock ttOb;


HERKES N C#
KISIM II C# KTPHANESN KEFETMEK

634
// Yeni bir kanal yapilandir.
public MyThread(String name, TickTock tt) {
thrd = new Thread(new ThreadStart(this.run));
ttOb = tt;
thrd.Name = name;
thrd.Start();
}

// Yeni kanalin calismasini baslat.
void run() {
if(thrd.Name == Tick) {
for(int i = 0; i < 5; i++) ttOb.tick(true);
ttOb.tick(false);
}
else {
for(int i = 0; i < 5; i++) ttOb.tock(true);
ttOb.tock(false);
}
}
}

class TickingClock {
public static void Main() {
TickTock tt = new TickTock();
MyTnread mt1 = new MyThread(Tick, tt);
MyThread mt2 = new MyThread(Tock, tt);

mt1.thrd.Join();
mt2.thrd.Join();
Console.WriteLine(Clock Stopped);
}
}
Programn rettii kt u ekildedir:
Tick Tock
Tick Tock
Tick Tock
Tick Tock
Tick Tock
Clock Stopped
Gelin imdi bu programa yakndan gz atalm. Main()de tt adnda bir TickTock
nesnesi oluturulur; iki alma kanalnn balamas iin bu nesne kullanlr. MyThreadin
run() metodu iinde, eer alma kanalnn ismi Tick ise tick()e arda bulunulur.
Kanaln ismi Tock ise tock() metodu arlr. Her metoda true deerinde bir argman
olarak aktarlan be ar yaplr. Saat, true aktarld srece alr.
Metotlarn her birine false deeri aktaran son ar saati durdurur.
Programn en nemli blm tick() ve tock() metotlarnda yer almaktadr. tick()
metodu ile balayacaz. Kolaylk olsun diye tick() metodu aada gsterilmitir:
BLM 21: OK KANALLI PROGRAMLAMA

HERKES N C#
635
public void tick(bool running) {
lock(this) {
if(!running) { // saati durdur
Monitor.Pulse(this); // bekleyen kanallari haberdar et
return;
}

Console.Write(Tick );

Monitor.Pulse(this); // tock()un calismasina izin ver

Monitor.Wait(this); // tock()un tamamlanmasini bekle
}
}
ncelikle, tick() iindeki kodun bir lock blou iinde yer aldna dikkat edin. Wait()
ve Pulse()n yalnzca senkronize edilmi bloklarn iinde kullanlabileceini hatrlayn.
Metot, almakta olan parametrenin deerini kontrol ederek balar. Bu parametre saatin
dzgn biimde kapatlmasn salamak iin kullanlr. Eer parametre false ise saat
durdurulmutur. Byle bir durum sz konusu ise, bekleyen herhangi bir kanaln almasn
mmkn klmak iin Pulse()a bir arda bulunulur. Bu noktaya birazdan geri dneceiz.
Saatin tick() gereklendiinde altn varsayarak ekranda Tick szc grntlenir ve
sonra Pulse()a bir arda bulunulur; bu ary Wait()e yaplan ar takip eder.
Pulse()a yaplan ar, ayn nesne rerinde bekleyen bir kanaln almasna olanak tanr.
Wait()e yaplan ar ise, bir baka kanal Pulse() arana kadar tick()in askda
kalmasna neden olur. Bylece, tick() arld zaman ekranda tek bir Tick gsterir, bir
baka kanaln almasna izin verir, sonra da askya alnr.
tock() metodu, tick()in birebir kopyasdr; yalnzca, ekranda Tick yerine Tock
grntler. Bu nedenle, tock() metoduna girilince, metot ekranda Tock szcn
grntler. Pulse() arr ve sonra bekler. ift olarak bakldnda tick()e yaplan
ary yalnzca tock()a yaplan ar takip edebilir; tock()a yaplan arnn ardndan da
yalnzca tick()e yaplan ar gelebilir vs. Bu sayede, her iki netot karlkl olarak
senkronize edilmi olur.
Saat durduunda Pulse()n arlmasnn nedeni, Wait()e yaplan son arnn
baaryla tamamlanmasna imkan vermektir. Hatrlarsanz, tick() ve tock()un her ikisi de
kendi mesajlarn grntledikten sonra Wait()e arda bulunurlar. Buradaki problem, saat
durduunda metotlardan birinin halen bekliyor olmasdr. Bu nedenle, bekleyen metodun
almas iin Pulse()a yaplan son ar gereklidir. Altrma olarak Pulse()a yaplan bu
ary kaldrmay deneyin ve ne olduunu izleyin. Greceksiniz ki, program askda
kalacaktr. kmak iin CTRL-C tularna basmak zorunda kalacaksnz. Bunun gerekesi,
tock()a yaplan son ar Wait()i ardnda, bu arya karlk gelen ve tock()un
sona ermesine imkan verecek bir Pulse() arsnn mevcut olmamasdr. Yani, tock()
sonsuza kadar bekleyerek orada ylece kalr.

HERKES N C#
KISIM II C# KTPHANESN KEFETMEK

636
Daha fazla ilerlemeden nce, saatin doru almasn salamak iin Wait() ve
Pulse() arlarnn gerekten gerekli olduu konusunda pheleriniz varsa TickTockun
aadaki versiyonunu nceki programdaki versiyonunun yerine yerletirin. Bu versiyonda
Wait()e ve Pulse()a yaplan tm arlar kaldrlmtr.
// TickTockun fonksiyonel olmayan versiyonu.
class TickTock {

public void tick(bool running) {
lock(this) {
if(!running) { // saati durdur
return;
}

Console.Write(Tick );
}
}

public void tock(bool running) {
lock(this) {
if(!running) { // saati durdur
return;
}

Console.WriteLine(Tock);
}
}
}
Bu deiikliin ardndan program tarafndan retilen kt aadaki gibi grnecektir:
Tick Tick Tick Tick Tick Tock
Tock
Tock
Tock
Tock
Clock Stopped
tick() ve tock() metotlarnn artk senkronize olmadklar aka grlmektedir!
Kilitlenme
ok kanall program gelitirirken kilitlenmeleri (deadlock) nlemek iin ok dikkatli
olmalsnz. Kilitlenme, adndan da anlalaca gibi, bir alma kanalnn bir eyler yapmak
iin baka bir kanal beklemesi, ancak dier kanaln da ilkini bekliyor olmas durumudur. Bu
yzden, her iki kanal birbirini bekleyerek askda kalr ve hibiri almaz. Bu durum, ar kibar
iki kiinin kapdan bir dierinin nce gemesi iin birbirlerine srar etmelerine benzer!
Kilitlenmeleri nlemek kolay gibi grnr fakat deildir. Sz gelii, kilitlenme ok
dolambal ekillerde ortaya kabilir. TickTock snfn ele aln. nceden akland gibi,
Pulse()a yaplan son ar tick() veya tock() tarafndan gereklenmezse, bu
BLM 21: OK KANALLI PROGRAMLAMA

HERKES N C#
637
metotlardan biri ya da dieri sonsuza kadar bekleyecektir; program kilitlenmitir. Genellikle
kilitlenmelerin nedeni programn kaynak koduna bakarak kolayca anlalmaz, nk programn
almas srasnda ezamanl olarak gereklenmekte olan kanallar karmak ekillerde
etkileebilirler. Kilitlenmeleri nlemek iin dikkatli programlama ve eksiksiz kontrol
gereklidir. Genel olarak, eer ok kanall bir program arada srada askda kalyorsa, byk
olaslkla bunun nedeni kilitlenmedir.
MethodImplAttribute Kullanm
MethodImplAttribute niteliini kullanarak btn bir metodu senkronize etmek
mmkndr. Bu yaklam, bir metodun btn ieriinin kilitlenmesi gereken durumlarda lock
ifadesine alternatif olarak kullanlabilir. MethodImplAttribute,
System.Runtime.CompilerServices isim uzaynda tanmlanmtr. Senkronizasyona
uygulanan yaplandrc aada gsterilmitir:
public MethodImplAttribute(MethodImplOptions opt)
Burada opt, uygulama niteliini belirtir. Bir metodu senkronize etmek iin
MethodImplOptions.Synchronized belirtin. Bu nitelik, btn metodun kilitlenmesine
neden olur.
TickTock snfnn senkronizasyon salamak iin MethodImplAttributeu kullanacak
ekilde yeniden yazlm versiyonu aadaki gibidir:
// Bir metodu senkronize etmek icin MethodImplAttribute kullanir.

using System;
using System.Threading;
using System.Runtime.CompilerServices;

class TickTock {

/* Asagidaki nitelik, butun tick() metodunu senkronize eder. */
[MethodImplAttribute(MethodImplOptions.Synchronized)]
public void tick(bool running) {
if(!running) { // saati durdur
Monitor.Pulse(this); // bekleyen kanallari haberdar et
return;
}

Console.Write(Tick );
Monitor.Pulse(this); // tock()un calismasina izin ver

Monitor.Wait(this); // tock()un tamamlanmasini bekle
}

/* Asagidaki nitelik, butun tick() metodunu senkronize eder. */
[MethodImplAttribute(MethodImplOptions.Synchronized)]
public void tock(bool running) {
if(!running) { // saati durdur

HERKES N C#
KISIM II C# KTPHANESN KEFETMEK

638
Monitor.Pulse(this); // bekleyen kanallari haberdar et
return;
}

Console.WriteLine(Tock);
Monitor.Pulse(this); // tick()in calmasna izin ver

Monitor.Wait(this); // tick()in tamamlanmasini bekle
}
}

class MyThread {
public Thread thrd;
TickTock ttOb;

// Yeni bir calisma kanali yapilandir.
public MyThread(string name, TickTock tt) {
thrd = new Thread(new ThreadStart(this.run));
ttOb = tt;

thrd.Name = name;
thrd.Start();
}

// Yeni kanalin calismasini baslat.
void run() {
if(thrd.Name == Tick) {
for(int i = 0; i < 5; i++) ttOb.tick(true);
ttOb.tick(false);
}
else {
for(int i = 0; i < 5; i++) ttOb.tock(true);
ttOb.tock(false);
}
}
}

class TickingClock {
public static void Main() {
TickTock tt = new TickTock();
MyThread mt1 = new MyThread(Tick, tt);
MyThread mt2 = new MyThread(Tock, tt);

mt1.thrd.Join();
mt2.thrd.Join();
Console.WriteLine(Clock Stopped);
}
}
TickTocktan elde edilen doru kt ncekiyle ayndr.
Btn bir metodu kilitlerken lock ya da MethodImplAttribute kullanma tercihi size
kalmtr. Her ikisi de ayn sonucu verir. lock, C#ta standart olarak tanml bir anahtar kelime
olduu iin bu kitaptaki rneklerde bu yaklam kullanlacaktr.
BLM 21: OK KANALLI PROGRAMLAMA

HERKES N C#
639
Kanallar Askya Almak, Srdrmek ve Durdurmak
Bir kanaln almasn askya almak kimi zaman yararldr. rnein, gnn saatini
grntlemek iin bir alma kanal kullanlabilir. Eer kullanc saat istemiyorsa, saati
altran kanal askda kalabilir. Daha sonra, saat istenildiinde ilgili kanaln almas
srdrlebilir. Ne tr bir durum sz konusu olursa olsun bir kanal askya almak ya da
almasn srdrmek basit bir meseledir. Kimi zaman da bir kanal durdurmak isteyeceksiniz.
Bir alma kanaln durdurmak askya almaktan farkldr, nk durdurulan bir kanal
sistemden kartlr ve yeniden balatlmaz.
Bir alma kanaln askya almak iin Thread.Suspend()i kullann. Askya alnm bir
kanaln almasn srdrmek iin Thread.Resume()u kullann. Bu metotlarn genel
kullanm ekilleri aada gsterilmitir:
public void Suspend()
public void Resume()
Eer arda bulunan kanal doru durumda deilse, bu metotlarn her ikisi de bir
ThreadStateException frlatabilir. rnein, askda olmayan bir kanaln almasn
srdrmeye almak kural d bir durumla sonulanr.
Bir kanal durdurmak iin Thread.Abort()u kullann. Bu metodun en basit kullanm
aada gsterilmitir:
public void Abort()
Abort(), kendisini aran kanala bir ThreadAbortException frlatlmasna neden
olur. Bu kural d durum, sz konusu kanaln sona ermesine yol aar. Bu kural d durum sizin
kodunuz tarafndan da yakalanabilir (fakat kanal durdurmak iin otomatik olarak yeniden
frlatlr). Abort() bir kanal her zaman annda durduramayabilir. Bu nedenle, programnz
almasna devam etmeden nce eer bir alma kanalnn durdurulmas nemli ise, Abort()
arsn bir Join() ars ile takip etmeniz gerekecektir. Ayrca, ender durumlarda,
Abort()un bir kanal durduramamas da mmkndr. Bir finally blou sonsuz dngye
girerse byle bir durum ortaya kabilir.
Aadaki rnek, bir alma kanalnn nasl askya alnacan, almasnn
srdrleceini ve durdurulacan gstermektedir:
// Bir calisma kanaln askiya alma, surdurme ve durdurma.

using System;
using System.Threading;

class MyThread {
public Thread thrd;

public MyThread(string name) {
thrd = new Thread(new ThreadStart(this.run));

HERKES N C#
KISIM II C# KTPHANESN KEFETMEK

640
thrd.Name = name;
thrd.Start();
}

// Burasi, kanalin giris noktasidir.
void run() {
Console.WriteLine(thrd.Name + starting.);

for(int i = 1; i <= 1000; i++) {
Console.Write(i + );
if((i % 10) == 0) {
Console.WriteLine();
Thread.Sleep(250);
}
}
Console.WriteLine(thrd.Name + exiting.);
}
}

class SuspendResumeStop {
public static void Main() {
MyThread mt1 = new MyThread(My Thread);

Thread.Sleep(1000); // cocuk kanalin calismaya baslamasina
// izin ver
mt1.thrd.Suspend();
Console.WriteLine(Suspending thread.);
Thread.Sleep(1000);

mt1.thrd.Resume();
Console.WriteLine(Resuming thread.);
Thread.Sleep(1000);

mt1.thrd.Suspend();
Console.WriteLine(Suspending thread.);
Thread.Sleep(1000);

mt1.thrd.Resume();
Console.WriteLine(Resuming thread.);
Thread.Sleep(1000);

Console.WriteLine(Stopping thread.);
mt1.thrd.Abort();

mt1.thrd.Join(); // calisma kanalinin sona ermesini bekle

Console.WriteLine(Main thread terminating.);
}
}
Bu programn kts aada gsterilmitir:
My Thread starting.
1 2 3 4 5 6 7 8 9 10
11 12 13 14 15 16 17 18 19 20
BLM 21: OK KANALLI PROGRAMLAMA

HERKES N C#
641
21 22 23 24 25 26 27 28 29 30
31 32 33 34 35 36 37 38 39 40
Suspending thread.
41 42 43 44 45 46 47 48 49 50
Resuming thread.
51 52 53 54 55 56 57 58 59 60
61 62 63 64 65 66 67 68 69 70
71 72 73 74 75 76 77 78 79 80
81 82 83 84 85 86 87 88 89 90
Suspending thread.
91 92 93 94 95 96 97 98 99 100
Resuming thread.
101 102 103 104 105 106 107 108 109 110
111 112 113 114 115 116 117 118 119 120
121 122 123 124 125 126 127 128 129 130
131 132 133 134 135 136 137 138 139 140
Stopping thread.
Main thread terminating.
Alternatif Abort()
Baz durumlarda Abort()un ikinci eklini kullanl bulabilirsiniz. Genel olarak
kullanm aada gsterilmitir:
public void Abort(object bilgi)
Burada bilgi, bir kanal durdurulurken bu kanala aktarmak istediiniz herhangi bilgiyi
ierir. Bu bilgi, ThreadAbortExceptionn ExceptionState zellii araclyla
eriilebilir. Bunu, bir alma kanalna sonlandrma kodu aktarmak iin kullanabilirsiniz.
Aadaki program Abort()un bu kullanmn gstermektedir:
// Abort (object) kullanimini gosterir.

using System;
using System.Threading;

class MyThread {
public Thread thrd;

public MyThread(string name) {
thrd = new Thread(new ThreadStart(this.run));
thrd.Name = name;
thrd.Start();
}

// Buras, kanalin giris noktasidir.
void run() {
try {
Console.WriteLine(thrd.Name + starting.);

for(int i = 1; i <= 1000; i++) {
Console.Write(i + );
if((i % 10) == 0) {

HERKES N C#
KISIM II C# KTPHANESN KEFETMEK

642
Console.WriteLine();
Thread.Sleep(250);
}
}
Console.WriteLine(thrd.Name + exiting normally.);
}
catch(ThreadAbortException exc) {
Console.WriteLine(Thread aborting, code is +
exc.ExceptionState);
}
}
}

class UseAltAbort {
public static void Main() {
MyThread mt1 = new MyTnread(My Thread);

Thread.Sleep(1000); // cocuk kanalin calismaya baslamasna
// izin ver
Console.WriteLine(Stopping thread.);
mt1.thrd.Abort (100);

mt1.thrd.Join(); // calisma kanalinin sona ermesini bekle

Console.WriteLine(Main thread terminating.);
}
}
kt aadaki gibidir:
My Thread starting.
1 2 3 4 5 6 7 8 9 10
11 12 13 14 15 16 17 18 19 20
21 22 23 24 25 26 27 28 29 30
31 32 33 34 35 36 37 38 39 40
Stopping thread.
Thread aborting, code is 100
Main thread terminating.
ktdan da grld gibi, Abort()a 100 deeri aktarlmaktadr. Bu deer, daha sonra
ThreadAbortExceptionn ExceptionState zellii araclyla eriilir.
ThreadAbortException, alma kanal sona ererken kanal tarafndan yakalanr.
Abort()u ptal Etmek
Bir kanal, bir durdurma isteini devre d brakabilir. Bunun iin sz konusu kanal
ThreadAbortException yakalamal ve sonra ResetAbort()u armaldr. Bu, kanaln
kural d durum yneticisi sona erince kural d durumun otomatik olarak yeniden
frlatlmasna engel olur. ResetAbort() u ekilde deklare edilir:
public static void ResetAbort()
BLM 21: OK KANALLI PROGRAMLAMA

HERKES N C#
643
Eer sz konusu kanal, durdurma ilemini iptal etmek iin doru gvenlik ayarlarna sahip
deilse ResetAbort()a yaplan ar baarsz olabilir.
Aadaki program ResetAbort()u gstermektedir:
// ResetAbort() kullanimini gosterir.

using System;
using System.Threading;

class MyThread {
public Thread thrd;

public MyThread(string name) {
thrd = new Thread(new ThreadStart(this.run));
thrd.Name = name;
thrd.Start();
}

// Burasi, kanalin giris noktasidir.
void run() {
Console.WriteLine(thrd.Name + starting.);

for(int i = 1; i <= 1000; i++) {
try {
Console.Write(i + );
if(i % 10) == 0) {
Console.WriteLine();
Thread.Sleep(250);
}
} catch(ThreadAbortException exc) {
if((int)exc.ExceptionState == 0) {
Console.WriteLine(Abort Cancelled! Code is +
exc.ExceptionState);
Thread.ResetAbort();
}
else
Console.WriteLine(Thread aborting, code is +
exc.ExceptionState);
}
}
Console.WriteLine(thrd.Name + exiting normally.);
}
}

class ResetAbort {
public static void Main() {
MyThread mt1 = new MyThread(My Thread);
Thread.Sleep(1000); // cocuk kanalin calismaya baslamasina
// izin ver

Console.WriteLine(Stopping thread.);
mt1.thrd.Abort(0); // bu, kanali durdurmayacaktr


HERKES N C#
KISIM II C# KTPHANESN KEFETMEK

644
Thread.Sleep(1000); // cocugun biraz daha calismasina
// izin ver

Console.WriteLine(Stopping thread.);
mt1.thrd.Abort(100); // bu, kanali durduracaktir

mt1.thrd.Join(); // calisma kanalinin sona ermesini bekle

Console.WriteLine(Main thread terminating.);
}
}
kt aada gsterilmitir:
My Thread starting.
1 2 3 4 5 6 7 8 9 10
11 12 13 14 15 16 17 18 19 20
21 22 23 24 25 26 27 28 29 30
31 32 33 34 35 36 37 38 39 40
Stopping thread.
Abort Cancelled! Code is 0
41 42 43 44 45 46 47 48 49 50
51 52 53 54 55 56 57 58 59 60
61 62 63 64 65 66 67 68 69 70
71 72 73 74 75 76 77 78 79 80
Stopping thraad.
Thread aborting, code is 100
Main thread terminating.
Bu rnekte eer Abort(), sfr deerindeki bir argman ile arlrsa durdurma istei
alma kanal tarafndan ResetAbort() arlarak iptal edilir ve kanal almasna devam
eder. Herhangi baka bir deer kanaln sona ermesine neden olur.
alma Kanalnn Durumunu Belirlemek
Bir kanaln durumu, Thread tarafndan salanan ThreadState zelliinden elde
edilebilir. Bu zellik aada gsterilmitir;
public ThreadState ThreadState{ get; }
alma kanalnn durumu, ThreadState numaralandrmas iinde tanmlanan bir deer
olarak dndrlr. ThreadState numaralandrmas iinde u deerler tanmldr:
ThreadState.Aborted ThreadState.AbortRequested
ThreadState.Background ThreadState.Running
ThreadState.Stopped ThreadState.StopRequested
ThreadState.Suspended ThreadState.SuspendRequested
ThreadState.Unstarted ThreadState.WaitSleepJoin
BLM 21: OK KANALLI PROGRAMLAMA

HERKES N C#
645
Bunlardan biri haricinde dierlerini aklamaya gerek yoktur, kendileri zaten anlalrdr.
Aklama gerektiren ise ThreadState.WaitSleepJoindir. Wait(), Sleep() ya da
Join()e yaplan bir ardan dolay beklemekte olan bir alma kanal bu bekleme srasnda
bu duruma girer.
Temel Kanaln Kullanm
Bu blmn banda bahsedildii gibi, tm C# programlar, temel kanal (main thread)
denilen ve program almaya baladnda programa otomatik olarak verilen en azndan bir
adet kanala sahiptir. Temel kanal tpk dier kanallar gibi ele alnabilir.
Temel kanala erimek iin bu kanala referansta bulunan bir Thread nesnesi elde
etmelisiniz. Bunu, Threadin bir yesi olan CurrentThread zelliini kullanarak
gerekletirirsiniz. Bu zelliin genel kullanm aada gsterilmitir:
public static Thread CurrentThread{ get; }
Bu metot, iinde arld kanala bir referans dndrr. Bu nedenle, eer program temel
kanal iinde almasn srdrrken CurrentThreadi kullanrsanz, temel kanala bir
referans elde edeceksiniz. Bu referansa bir kez sahip olduktan sonra artk temel kanal tpk
dier kanallar gibi kontrol edebilirsiniz.
Aadaki program, temel kanal gsteren bir referans elde eder ve temel kanaln adn ve
ncelik srasn alr ve ayarlar:
// Temel kanali kontrol eder.

using System;
using System.Threading;

class UseMain {
public static void Main() {
Thread thrd;

// Temel kanali al.
thrd = Thread.CurrentThread;

// Temel kanalin adini goruntule.
if(thrd.Name == null)
Console.WriteLine(Main thread has no name.);
else
Console.WriteLine(Main thread is called: +
Thrd.Name);

// Temel kanalin oncelik sirasini goruntule.
Console.WriteLine(Priority: + thrd.Priority);

Console.WriteLine();

// Adini ve oncelik sirasini ayarla.

HERKES N C#
KISIM II C# KTPHANESN KEFETMEK

646
Console.WriteLine(Setting name and priority.\n);
thrd.Name = Main Thread;
thrd.Priority = ThreadPriority.AboveNormal;

Console.WriteLine(Main thread is now called: +
thrd.Name);

Console.WriteLine(Priority is now: + thrd.Priority);
}
}
Programn kts aadaki gibidir:
Main thread has no name.
Priority: Normal

Setting name and priority.

Main thread is now called: Main Thread
Priority is now: AboveNormal
Bir uyar: Temel kanal zerinde hangi ilemleri gerekletirdiiniz konusunda dikkatli
olmanz gereklidir. Sz gelii, Main()in sonuna aadaki Join() arsn eklerseniz
thrd.Join();
program asla sona ermez, nk temel kanaln sona ermesini bekleyecektir!
ok Kanalllk nerileri
ok kanalllktan verimli ekilde yararlanmann temel yolu seri olarak deil paralel olarak
dnmektir. rnein, bir program iinde paralel zamanl alabilen iki alt sisteme sahipseniz,
bunlar ayr birer kanal haline gelirin. Ancak, burada bir uyar yapmakta da yarar vardr. Eer
haddinden fazla kanal oluturmusanz, programnzn performansn artrmak yerine gerekte
drebilirsiniz. Hatrlarsanz, ierik dei tokuu ile ilintili bir ek yk sz konusudur. Eer
haddinden fazla kanal oluturursanz, programnz altrmak iin gerekli CPU zamanndan
daha fazlas ierik deitirmek iin harcanacaktr!
Ayr Bir Grevi Balatmak
C#ta programlama yaparken kanal tabanl ok grevlilik sizin en sk kullanacanz
yntem olmasna ramen, uygun olan yerlerde proses tabanl ok grevlilikten yararlanmak da
mmkndr. Proses tabanl ok grevlilikten yararlanrken ayn program iinde baka bir kanal
balatmak yerine bir program, bir dier programn almasn balatr. C#ta bunu Process
snfn kullanarak gerekletirirsiniz. Process, System.Diagnostics isim uzaynda
tanmldr. Bu blm noktalamak iin bir baka prosesi balatmak ve ynetmek konusuna
ksaca gz atmanz tavsiye edilir.
BLM 21: OK KANALLI PROGRAMLAMA

HERKES N C#
647
Bir baka prosesi balatmann en kolay yolu Process tarafndan tanmlanm Start()
metodunu kullanmaktr. Bunun en basit ekillerinden biri aadaki gibidir:
public static Process start(string isim)
Burada isim, altrlacak olan altrlabilir dosyann ismini ya da altrlabilir bir
dosya ile ilikili bir dosyann ismini belirtir.
Sizin oluturduunuz bir proses sona erdiinde bu proses ile ilintili bellei serbest
brakmak iin Close()u arn. Close() aada gsterilmitir:
public void Close()
Bir prosesi iki ekilde sona erdirebilirsiniz. Eer sz konusu proses bir Windows GUI
uygulamas ise, prosesi sonlandrmak iin, aada gsterildii gibi, CloseMainWindow()u
arn:
public bool CloseMainWindow()
Bu metot, prosese durmas gerektiini bildiren bir mesaj gnderir. Mesaj alnmsa metot
true dndrr. Eer uygulama bir GUI program deilse ya da bir ana pencereye sahip deilse
metot false dndrr. stelik; CloseMainWindow(), oturumu kapatmak iin yalnzca bir
istektir. Eer uygulama bu istei dikkate almazsa, uygulama sona ermeyecektir.
Bir prosesi gerekten sonlandrmak iin aada gsterildii gibi Kill()i arn:
public void Kill()
Kill()i dikkatli kulann. Kill(), sz konusu prosesin kontrolsz sonlandrlmasma
neden olur. Prosesle ilintili kaydedilmemi herhangi veri byk olaslkla kaybedilecektir.
WaitForExit()i ararak bir prosesin sona ermesini bekleyebilirsiniz. Bu metodun iki
ekli aada gsterilmitir:
public void WaitForExit()
public bool WaitForExit(int milisaniye)
lk ifade, proses sona erene kadar bekler. kinci ifade yalnzca belirtilen milisaniye
sresince bekler. Eer sz konusu proses sona ermise ikinci ifade true dndrr; proses
halen alyorsa metot false dndrr,
Aadaki program bir prosesin nasl oluturulacan, beklenileceini ve kapatlacan
gstermektedir. Program, Windowsun standart yardmc program olan WordPad.exeyi
altrmaktadr. Program daha sonra WordPadin sona ermesini bekler.
// Yeni bir proses baslatir.

using System;
using System.Diagnostics;

class StartProcess {

HERKES N C#
KISIM II C# KTPHANESN KEFETMEK

648
public static void Main() {
Process newProc = Process.Start(wordpad.exe);

Console.WriteLine(New process started.);

newProc.WaitForExit();

newProc.Clos(); // serbest kaynaklar

Console.WriteLine(New process ended.);
}
}
Bu program altrdnzda WordPad almaya balayacaktr ve siz de New process
started. mesajn ekranda greceksiniz. Program daha sonra siz WordPadi kapatana kadar
bekleyecektir. WordPad bir kez sona erdikten sonra artk son mesaj New process ended.
ekranda gsterilir.



Y R M K N C B L M


KOLEKSYONLARLA
ALIMAK





















22

HERKES N C#
KISIM II C# KTPHANESN KEFETMEK

650
C#ta bir koleksiyon, bir grup nesnedir. System.Collections isim uzay, eitli tiplerde
koleksiyonlar tanmlayan ve uygulayan ok sayda arayz ve snf ierir. Koleksiyonlar pek ok
programlama grevini kolaylatrrlar, nk ska kullanlan fakat kimi zaman gelitirilmesi
skc olan birka veri yaps iin taze zmler sunarlar. rnein, yn, kuyruk ve hash
tablolarn destekleyen, standart olarak sisteme entegre koleksiyonlar mevcuttur. Koleksiyonlar,
tm C# programclarnn yakn ilgisine layk en gelikin teknolojidir.
Koleksiyonlara Genel Bak
Koleksiyonlarn balca avantaj, nesne gruplarnn programlarnz tararndan ele alnn
standardize etmeleridir. Tm koleksiyonlar, net olarak tanmlanm birtakm arayzler etrafnda
tasarlanmtr. Bu arayzlerin, olduu gibi kullanabileceiniz birka standart uygulamas
mevcuttur; sz gelii, ArrayList, Hashtable, Stack ve Queue bu uygulamalardandr.
Ayrca, kendi koleksiyonunuzu da uygulayabilirsiniz, fakat buna ender olarak gerek
duyacaksnz.
.NET Framework, genel koleksiyon tipini destekler: Genel amal, zelletirilmi ve bit
tabanl. Genel amal koleksiyonlar, aralarnda dinamik dizi (dynamic array), yn (stack) ve
kuyruk (queue) da olan birka temel veri yapsn uygularlar. Ayrca, anahtar/deer iftlerini
saklayabileceiniz szlkler (dictionary) de ierirler. Bylece, her tipten veriyi saklamak iin
kullanlabilirler.
zel amal koleksiyonlar, belirli bir veri tipi zerinde ilem grrler ya da ilemlerini
benzersiz bir biimde gerekletirirler. rnein, karakter katarlar iin zelletirilmi
koleksiyonlar mevcuttur. Tek bal listeyi kullanan zelletirilmi koleksiyonlar da ayrca
vardr.
Bit tabanl koleksiyon snflar bir grup biti saklarlar. Bit tabanl koleksiyonlar, dier
koleksiyon tiplerine kyasla farkl birtakm ilemleri desteklerler. Sz gelii, balca bit tabanl
koleksiyonlardan biri, VE ya da VEYA gibi bit tabanl ilemleri destekleyen BitArraydir.
Tm koleksiyonlarn esas numaralandrc (enumerator) kavramna dayanr. Bu kavram,
IEnumerator ve IEnumerable arayzleri tarafndan desteklenir. Numaralandrc, bir
koleksiyon iindeki elere eriimin bir kerede bir eye eriilecek ekilde standardize edilmi
yntemlerinden biridir. Bylece, koleksiyonun ierii numaralandrlm olur. Her
koleksiyonun IEnumerable uygulamas gereklidir. Bu nedenle, herhangi bir koleksiyon
snfnn eleri IEnumerator tarafndan tanmlanan metotlar araclyla eriilebilir. Bir
koleksiyon tipi zerinde tekrarlayan kod, yalnzca kk deiikliklerle, bir bakas zerinde
tekrarlayacak ekilde kullanlabilir. in ilgin yan, foreach dngs, bir koleksiyonun
ierii rerinde tekrarlamak iin numaralandrc kullanr.
Son bir husus: Eer C++a ainaysanz, C# koleksiyon snflarnn C++ tarafndan tanmla-
nan Standart ablon Ktphanesi (STL - Standard Template Library) snflaryla ayn anlamda
olduunu bilmek sizin iin yararl olacaktr. C++n konteyner olarak adlandrdklarn C#
koleksiyon olarak armaktadr. Ayn durum Java iin de geerlidir. Eer Javann Collections
BLM 22: KOLEKSYONLARLA ALIMAK

HERKES N C#
651
Frameworkne ainaysamz, C# koleksiyonlarnn kullanmn renirken hi zorluk
yaamayacaksnz demektir.
Koleksiyon Arayzleri
System.Collectionsta ok sayda arayz tanmldr. Koleksiyon arayzleriyle
balamak gereklidir, nk tm koleksiyon snflarnda ortak olan ilevsellik bu arayzler
tarafndan belirlenmektedir. Koleksiyonlar alltan destekleyen arayzler Tablo 22.1de
zetlenmitir. Aadaki konularda her arayz ayrntl olarak incelenmektedir.
ICollection Arayz
ICollection arayz, zerine tm koleksiyonlarn ina edildii temel niteliindedir.
ICollectionda tm koleksiyonlarn sahip olaca ekirdek metotlar ve zellikler deklare
edilir. Ayrca IEnumerable arayz de kaltm yoluyla ICollectiona aktarlr.
Koleksiyonlarn ne ekilde altn net olarak anlamak iin ICollectionn anlalm
olmas gereklidir.
ICollectionda aadaki zellikler tanmldr:
zellik Anlam
int Count { get; } Koleksiyonda tutulan mevcut e says.
bool IsSynchronized { get; } Koleksiyon senkronize edilmise truedur;
senkronize edilmemise falsetur. Koleksiyonlar
varsaylan durumda senkronize edilmemilerdir. Buna
ramen, birok koleksiyonun senkronize edilmi bir
versiyonunu elde etmek mmkndr.
object SyncRoot { get; } zerinde bir koleksiyonun senkronize edilebilecei bir
nesne.
Count, bir koleksiyon iinde tutulan mevcut e saysn ierdii iin en sk kullanlan
zelliktir. Eer Count sfr ise koleksiyon bo demektir.
ICollectionda aadaki metot tanmldr:
void CopyTo(Array hedef, int startIdks)
CopyTo(), bir koleksiyonun ieriini, startIdks ile belirtilen indeksten balayarak
hedef ile belirtilen diziye kopyalar. Bylece, CopyTo() bir koleksiyon ile standart C# dizisi
arasnda kpr kurmu olur.
IEnumerable, kaltm yoluyla ICollectiona aktarld iin ICollection,
IEnumerable tarafndan tanmlanan tek metodu da ierir: GetEnumerator(). Bu metot
aada gsterilmitir:
IEnumerator GetEnumerator()

HERKES N C#
KISIM II C# KTPHANESN KEFETMEK

652
GetEnumerator(), koleksiyon iin bir numaralandnc dndrr.
TABLO 22.1: Koleksiyon Arayzleri


Arayz Aklama
ICollection Tm koleksiyonlarn sahip olmas gereken elemanlar tanmlar.
IEnumerable GetEnumerator() metodunu tanmlar. GetEnumerator()bir
koleksiyon snf iin bir numaralandrc tedarik eder.
IEnumerator Bir koleksiyonun ieriinin tek tek elde edilmesini mmkn klan
metotlar salar.
IList Bir indeksleyici zerinden eriilebilen bir koleksiyon tanmlar.
IDictionary Anahtar/deer iftlerinden oluan bir koleksiyon tanmlar.
IDictionaryEnumerator IDictionaryyi uygulayan bir koleksiyon iin numaralandrc
tanmlar.
IComparer Bir koleksiyonda sakl olan nesneleri karlatran Compare()
metodunu tanmlar.
IHashCodeProvider Bir hash fonksiyonu tanmlar.
IList Arayz
IList, kaltmla ICollectiondan tretilir ve elemanlarna sfr tabanl bir indeks
araclyla eriilmesine izin veren bir koleksiyonun davrann deklare eder.
ICollectionda tanml metotlara ek olarak IList, kendisine ait birka metot da tanmlar.
Bunlar Tablo 22.2de zetlenmitir. Bu rnetotlardan birka bir koleksiyonun zerinde yaplan
deiiklikleri iermektedir. Eer sz konusu koleksiyon salt okunur ya da sabit byklkte ise
bu metotlar bir NotSupportedException frlatacaklardr.

TABLO 22.2: IList Tarafndan Tanmlanan Metotlar


Metot Aklama
int Add(object obj) arda bulunan koleksiyona objyi ekler. Nesnenin
sakland konumun indeksini dndrr.
void Clear() arda bulunan koleksiyondaki tm elemanlar siler.
bool Contains(object obj) arda bulunan koleksiyon obj zerinden aktarlan
nesneyi ieriyorsa true dndrr; aksi halde false
dndrr.
int IndexOf(object obj)
obj, arda bulunan koleksiyon iinde yer alyorsa
objnin indeksini dndrr. obj mevcut deilse -1
dndrr.

BLM 22: KOLEKSYONLARLA ALIMAK

HERKES N C#
653
void Insert(int idx, object obj)
objyi idx ile belirtilen indekse ekler. idxteki ve
bunun altndaki tm elemanlar aa doru kaydrlarak
obj iin yer alr.
void Remove(object obj) arda bulunan koleksiyondan ilk rastlanlan objyi
kartr. kartlan elemannn olduu konumdaki ve
aasndaki elemanlar yukar doru kaydrlarak boluk
kapatlr.
void RemoveAt(int idx) arda bulunan koleksiyondan idx ile belirtilen
indeksteki nesneyi kartr. kartlan elemannn
olduu konumdaki ve aasndaki elemanlar yukar
doru kaydrlarak boluk kapatlr.
Bir IList koleksiyonuna nesneler Add() arlarak eklenir. Add()in object tipinde bir
argman aldna dikkat edin. object, tm tipler iin bir temel snf olduundan dolay
herhangi tipten object bir koleksiyonda saklanabilir. Deer tipleri bu kapsamda yer alr,
nk kutulama ve kutudan karma otomatik olarak ortaya kacaktr.
Remove() ya da RemoveAt()i kullanarak bir eyi kartabilirsiniz. Remove(),
belirtilen nesneyi kartr. RemoveAt(), belirtilen indeksteki nesneyi kartr. Koleksiyonu
boaltmak iin Clear() arn.
Contains()i ararak bir koleksiyonun belirli bir nesne ierip, iermediini
belirleyebilirsiniz. Bir nesnenin indeksini IndexOf()u ararak elde edebilirsiniz.
Insert()i ararak belirli bir indekse bir e ekleyebilirsiniz.
IListte aadaki zellikler tanmldr;
bool isFixedSize { get; }
bool IsReadOnly { get; }
Eer koleksiyon sabit byklkte ise, IsFixedSize truedur. Bu, eler eklenemez ya
da kartlamaz, demektir. Eer koleksiyon salt okunur ise, IsReadOnly true deerine
sahiptir. Bu koleksiyonun ierii deitirilemez demektir.
IListte aadaki indeksleyici tanmldr:
object this[int idks] { get; set; }
Bir enin deerini almak ya da ayarlamak iin bu indeksleyiciyi kullanacaksnz. Ancak,
koleksiyona yeni bir e eklemek iin bunu kullanamazsnz. Listeye bir e eklemek iin
Add()i arn. e eklenir eklenmez artk bu eye indeksleyici araclyla eriebilirsiniz.
IDictionary Arayz
IDictionary arayz, benzersiz anahtarlar, karlk gelen deerlerle eleyen bir
koleksiyonunun davrann tanmlar. Anahtar, daha sonraki bir tarihte bir deere erimek iin
kullanacanz bir nesnedir. Bylece, IDictionary arayz uygulayan bir koleksiyon,

HERKES N C#
KISIM II C# KTPHANESN KEFETMEK

654
anahtar/deer iftlerini saklar. Bir kez anahtar/deer ifti saklandktan sonra artk bu ifte kendi
anahtarn kullanarak eriebilirsiniz. IDictionary, kaltmla ICollectiondan tretilmitir.
IDictionary tarafndan tanmlanan metotlar Tablo 22.3te zetlenmitir. Bir null anahtar
belirtilmeye allnca metotlardan birka bir NotSupportedException frlatacaktr.
Bir IDictionary koleksiyona bir anahtar/deer ifti eklemek iin Add() kullann.
Anahtar ve anahtara karlk gelen deerin ayr ayr belirtildiine dikkat edin. Bir eyi
kartmak iin sz konusu nesnenin anahtarn Remove() ars iinde belirtin. Koleksiyonu
kartmak iin Clear() arn.
Bir koleksiyonun belirli bir nesneyi ierip, iermediini Contains()i istenilen enin
anahtar ile birlikte ararak belirleyebilirsiniz. GetEnumerator(), bir IDictionary
koleksiyonu ile uyumlu bir numaralandrc elde eder. Bu numaralandrc anahtar/deer iftleri
zerinde ilem yapar.
IDictionaryde aadaki zellikler tanmldr:
zellik Aklama
bool IsFixedSize { get; } Szlk sabit byklkte ise true deerindedir.

bool IsReadOnly { get; } Szlk salt okunur ise true deerindedir.

ICollection Keys { get; } Anahtarlarn koleksiyonunu elde eder.
ICollecticn values { get; } Deerlerin koleksiyonunu elde eder.

TABLO 22.3: IDictionary Tarafndan Tanmlanan Metotlar


Metot Aklama
void Add(object k, object v) k ve v ile belirtilen anahtar/deer iftini arda bulunan
koleksiyona ekler. k, null olmamaldr. k nceden
koleksiyonda saklanm ise bir ArgumentException
frlatlr.

void Clear() arda bulunan koleksiyondan tm anahtar/deer
iftlerini siler.
bool Contains(object k) arda bulunan koleksiyon anahtar olarak ky ieriyorsa
true dndrr. Aksi halde false dndrr.

IDictionaryEnumerator
GetEnumerator()
arda bulunan koleksiyon iinde numaralandrc
dndrr.
void Remove(object k) Anahtar kya eit olan kayd kartr.
Koleksiyon iinde yer alan anahtar ve deerlerin Keys ve Values zellikleri araclyla
ayr birer liste eklinde mevcut olduuna dikkat edin.
IDictionaryde aadaki indeksleyici tanmlanmtr:
BLM 22: KOLEKSYONLARLA ALIMAK

HERKES N C#
655
object this[object anahtar] { get; set; }
Bir enin deerini almak ya da ayarlamak iin bu indeksleyiciyi kullanabilirsiniz. Ayrca
koleksiyona yeni bir e eklemek iin de bunu kullanabilirsiniz. ndeksin aslnda bir indeks
olmadna, bunun yerine, sz konusu enin anahtar olduuna dikkat edin.
IEnumerable, IEnumerator ve IDictionaryEnumerator
IEnumerable, bir snfn, eer numaralandrmalar desteklemesi gerekiyorsa, uygulamas
gereken bir arayzdr. nceden akland gibi, IEnumerable kaltmla ICollectiondan
tretildii iin tm koleksiyon snflar IEnumerable uygulamak zorundadr. IEnumerable
tarafndan tanmlanan tek metot GetEnumerator()dr. GetEnumerator() aada
gsterilmitir:
IEnumerator GetEnumerator()
Bu metot sz konusu koleksiyon iin numaralandrc dndrr. Ayrca, IEnumerable
uygulamak koleksiyon ieriinin foreach dngs ile elde edilmesine olanak tanr.
IEnumerator, bir numaralandrcnn ilevselliini tanmlayan arayzdr.
IEnumeratorn metotlarn kullanarak koleksiyon ierii zerinde tekrarlayarak
ilerleyebilirsiniz. Anahtar/deer iftlerini (szlkler) saklayan koleksiyonlar iin
GetEnumerator(), IEnumerator yerine IDictionaryEnumerator tipinde bir nesne
dndrr. IDictionaryEnumerator, kaltm yoluyla IEnumeratordan trer; bir de,
szlklerin numaralandrlmasn kolaylatran ilevsellik katar.
IEnumerator tarafndan tanmlanan metotlar ve bunun kullanm iin gerekli teknikler bu
blmn ileri ki sayfalarnda anlatlmtr.
IComparer
IComparer arayznde, iki nesnenin karlatrlma yntemini tanmlayan Compare()
adnda hir metot tanmldr. Compare() aada gsterilmitir:
int Compare(object v1, object v2)
v1, v2den bykse Compare() sfrdan byk bir deer dndrmelidir; v1, v2den
kkse sfrdan kk bir deer, her iki deer eitse sfr dndrmelidir. Bu arayz,
koleksiyonun elemanlarnn ne ekilde sralanmas gerektiini belirtmek iin kullanlabilir.
IHashCodeProvider
IHashCodeProvider, GetHashCode()un zelletirilmi, bir versiyonunu belirtmek
istediinizde uygulanan arayzdr. Hatrlarsanz; tm nesneler, varsaylan durumda kullanlan
hash kod metodu olan Object.GetHashCode()dan tretilirler. IHashCodeProvider

HERKES N C#
KISIM II C# KTPHANESN KEFETMEK

656
uygulayarak alternatif bir metot belirtebilirsiniz. Normalde IHashCodeProvider
uygulamak iin hi bir neden yoktur.
The DictionaryEntry Yaps
System.Collections, DictionaryEntry adnda bir yap tipi tanmlar. Anahtar/deer
iftlerini tutan koleksiyonlar, bu iftleri bir DictionaryEntry nesnesi iinde saklarlar. Bu
yapda aadaki iki zellik tanmlanmtr:
public object Key { get; set; }
public object Value { get; set; }
Bu zellikler, bir giri ile ilikili anahtara ya da deere erimek iin kullanlrlar. Aadaki
yaplandrcy kullanarak bir DictionaryEntry nesnesi yaplandrabilirsiniz:
public DictionaryEntry(object k, object v)
Burada k, anahtar; v ise deerdir.
Genel Amal Koleksiyon Snflar
Artk koleksiyon arayzlerini tandnza gre, bu arayzleri uygulayan standart snflar
inceleyebiliriz. nceden de akland gibi, koleksiyon snflar temel alt blme
ayrlmtr: Genel amal, bit tabanl ve zel amal. Genel amal snflar, herhangi bir tipteki
nesneleri saklamak iin kullanlabilirler. Bit tabanl koleksiyonlar bitleri saklarlar. zel amal
koleksiyonlar ise tipe sk skya bal (belirli bir veri tipinde ileyecek ekilde tasarlanan) ya da
farkl bir ekilde zelletirilmi uygulamalar sunarlar. Burada genel amal koleksiyon snflar
incelenmektedir. Bit tabanl ve zelletirilmi koleksiyon snflar bu bolmde daha sonraki
sayfalarda anlatlmtr.
Genel amal koleksiyon snflar aada zetlenmitir:
zellik Aklama
ArrayList Dinamik dizi. Bu, gerektiinde genileyebilen bir dizidir.

Hashtable Anahtar/deer iftleri iin hash tablosu.
Queue lk giren- ilk kar ileyiine sahip liste.

SortedList Anahtar/deer iftlerinin sral listesi.

Stack lk giren- son kar ileyiine sahip liste.

Aada, bu koleksiyon snflar incelenmekte ve bunlarn kullanmlar gsterilmektedir.
ArrayList
ArrayList snf, istenildiinde genileyebilen ya da daralabilen dinamik dizileri
destekler. C#ta standart diziler sabit uzunluktadr; uzunluklar programn almas srasnda
BLM 22: KOLEKSYONLARLA ALIMAK

HERKES N C#
657
deitirilemez. Bu, dizinin ka adet eleman tutacan nceden bilmeniz gerektii anlamna
gelir. Ancak, kimi zaman ne kadar byk bir diziye gereksiniminiz olacan program
almaya balayana kadar tam olarak bilemeyebilirsiniz. Bu durumu kontrol altna almak iin
ArrayList kullann. ArrayList, bykl dinamik olarak artp azalabilen nesne
referanslarndan oluan deiken uzunlukta bir dizidir. ArrayList, balang bykl ile
birlikte oluturulur. Bu byklk alnca sz konusu koleksiyon otomatik olarak geniletilir.
Nesneler kartlnca dizi daraltlabilir. ArrayList belki de koleksiyonlarn en nemlisidir;
burada bunu derinlemesine inceleyeceiz
ArrayList; ICollection, IList, IEnumerable ve ICloneable arayzlerini uygular
ArrayList aada gsterilen yaplandrclar ierir:
public ArrayList()
public ArrayList(ICollection c)
public ArrayList(int kapasite)
lk yaplandrc, balang kapasitesi 16 olan bo bir ArrayList yaplandrr. kinci
yaplandrc, c ile belirtilen koleksiyonun eleman saysna ve kapasitesine sahip bir
ArrayList yaplandrr. nc yaplandrc ise belirtilen kapasiteye sahip bir dizi listesi
yaplandrr. Kapasite, elemanlar saklamak iin kullanlan altta yatan dizinin bykldr.
Elemanlar bir ArrayListe eklendike kapasite otomatik olarak byr. Listenin geniletilmesi
gerektiinde listenin kapasitesi ikiye katlanr.
Uygulad arayzler tarafndan tanmlanan metotlara ek olarak ArrayList, kendisi de
birka metot tanmlar. Bunlardan en yaygn olarak kullanlan birka Tablo 22.4te
gsterilmitir. Bir ArrayList, Sort() arlarak sralanabilir. Bir kez sralandktan sonra
BinarySearch() ile verimli biimde aranabilir. ArrayListin ierii Reverse()
arlarak tersine evrilebilir.
ArrayList, bir koleksiyon iindeki elemanlarn bir blm zerinde ilem yapan birka
metodu da destekler. InsertRange()i ararak bir ArrayListe bir baka koleksiyon
ekleyebilirsiniz. RemoveRange()i ararak bir blm listeden kartabilirsiniz.
SetRange()i ararak da bir ArrayList iindeki bir blmn zerine bir baka
koleksiyonun elemanlarn yazabilirsiniz. Ayrca, btn bir koleksiyonu sralamak ya da
aramak yerine koleksiyon iindeki bir blm sralayp, arayabilirsiniz.
ArrayList varsaylan ekliyle senkronize edilmemitir. Bir koleksiyon etrafnda
senkronize edilmi bir klf elde etmek iin Synchronized() arn.
TABLO 22.4: ArrayList Tarafndan Tanmlanan Metotlardan Ska Kullanlan Birka


Metot Aklama
public virtual void
AddRange(ICollection c)
cnin iindeki elemanlar arda bulunan
ArrayListin sonuna ekler.


HERKES N C#
KISIM II C# KTPHANESN KEFETMEK

658
public virtual int BinarySearch(object
v)
arda bulunan koleksiyon iinde v
zerinden aktarlan deeri arar. Elenen
elemann indeksi dndrlr. Eer deer
bulunamazsa negatif bir deer dndrlr.
arda bulunan liste sral olmaldr.
public virtual int BinarySearch(object
v, IComparer comp)
comp ile belirtilen karlatrma nesnesini
kullanarak arda bulunan koleksiyon iinde
v zerinden aktarlan deeri arar. Elenen
elemann indeksi dndrlr. Eer deer
bulunamazsa negatif bir deer dndrlr.
arda bulunan liste sral olmaldr.
public virtual int BinarySearch(int
startIdx, int count, object v,
IComparer comp)
comp ile belirtilen karlatrma nesnesini
kullanarak arda bulunan koleksiyon iinde
v zerinden aktarlan deeri arar. Arama
startIdxten balar ve count sayda
eleman kapsar. Elenen elemann indeksi
dndrlr. Eer deer bulunamazsa negatif
bir deer dndrlr. arda bulunan liste
sral olmaldr.
public virtual void CopyTo(Array ar,
int startIdx)
startIdxten balayarak arda bulunan
koleksiyonun ieriini ar ile belirtilen diziye
kopyalar. ar, koleksiyondaki elemanlarn
tipiyle uyumlu tek boyutlu bir dizidir.
public virtual void CopyTo(int srcIdx,
Array ar, int destIdx, int count)
startIdxten balayarak count sayda
eleman iin geerli olmak zere arda
bulunan koleksiyonun bir blmn ar ile
belirtilen diziye kopyalar. ar, koleksiyondaki
elemanlarn tipiyle uyumlu tek boyutlu bir
dizidir.
public virtual ArrayList GetRange(int
idx, int count)
arda bulunan ArrayListin bir
blmn dndrr. Dndrlen aralk idx
ile balar ve count sayda eleman kapsar.
Dndrlen nesne, arda bulunan nesne ile
ayn elemanlara referansta bulunur.
public static ArrayList
FixedSize(ArrayList ar)
ar sabit byklkte bir ArrayList iine
sarar ve sonucu dndrr.
public virtual void InsertRange(int
startIdx, ICollection c)
cnin elemanlarn startIdx ile belirtilen
indeksten balayarak arda bulunan
koleksiyona ekler.
public virtual int LastIndexOf(object
v)
arda bulunan koleksiyon iinde vye son
rastlanlan konumun indeksini dndrr. v
mevcut deilse -1 dndrr.
public static ArrayList
ReadOnly(ArrayList ar)
ar salt okunur bir ArrayList iine sarar
ve sonucu dndrr.
BLM 22: KOLEKSYONLARLA ALIMAK

HERKES N C#
659
public virtual void RemoveRange(int
idx, int count)
idxten balayarak arda bulunan
koleksiyondan count sayda eleman kartr.
public virtual void Reverse() arda bulunan koleksiyonun ieriini ters
evirir.
public virtual void Reverse(int
startIdx, int count)
startIdxten balayarak arda bulunan
koleksiyonda count sayda eleman ters
evirir.
public virtual void SetRange(int
startIdx, ICollection c)
startIdxten balayarak arda bulunan
koleksiyon iindeki elemanlar c ile belirtilen
elemanlarla deitirir.
public virtual void Sort() Koleksiyonu artan srada sralar.

public virtual void Sort(IComparer
comp)
Belirtilen karlatrma nesnesini kullanarak
koleksiyonu sralar. Eer comp null ise her
nesne iin varsaylan karlatrma kullanlr.
public virtual void Sort(int startIdx,
int endIdx, IComparer comp)
Belirtilen karlatrma nesnesini kullanarak
koleksiyonu sralar. Sralama startIdxten
balar ve endIdxte sona erer. Eer comp
null ise her nesne iin varsaylan
karlatrma kullanlr.
public static ArrayList
Synchronized(ArrayList list)
arda bulunan ArrayListin senkronize
edilmi versiyonunu dndrr.
public virtual object[] ToArray() arda bulunan nesnenin elemanlarnn
kopyalarn ieren bir dizi dndrr.
public virtual Array ToArray(Type type) arda bulunan nesnenin elemanlarnn
kopyalarn ieren bir dizi dndrr. Dizinin
elemanlarnn tipi type ile belirtilir.
public virtual void TrimToSize() Capacityye Count deerini verir.
Uygulad arayzler tarafndan tanmlanan zelliklere ek olarak ArrayList, aada
gsterilen Capacity zelliini ekler:
public virtual int Capacity { get; set; }
Capacity, arda bulunan ArrayListin kapasitesini alr ya da ayarlar. Kapasite, sz
konusu ArrayListin geniletilmesi gerekmeden nce tutabilecei eleman saysdr. nceden
de bahsedildii gibi, bir ArrayList otomatik olarak byr; bu nedenle, kapasiteyi elle
ayarlamaya gerek yoktur. Yine de, verimlilii salamak adna listenin ka adet eleman
iereceini nceden bildiiniz durumlarda, kapasiteyi ayarlamak isteyebilirsiniz. Bu, daha fazla
bellek alan ayrmakla ilintili ek yk nler.
te yandan, bir ArrayListin altnda yatan dizinin bykln azaltmak istediinizde
Capacityye daha kk bir deer verebilirsiniz. Ancak, bu deer Counttan daha kk
olmamaldr. Hatrlarsanz; Count, bir koleksiyon iinde halihazrda sakl olan nesnelerin say-

HERKES N C#
KISIM II C# KTPHANESN KEFETMEK

660
sn tutan, ICollection tarafndan tanml bir zelliktir. Capacityye Counttan daha
kk bir deer vermeye almak bir ArgumentOutOfRangeExceptionn retilmesine
neden olur. Tam olarak, bir ArrayListin halen tutmakta olduu e says kadar bir
bykl sahip bir ArrayList elde etmek iin Capacityyi Counta eitleyin. Ayrca
TrimToSize() da arabilirsiniz.
Aadaki program ArrayListi gstermektedir. Program, bir ArrayList oluturur ve
buna karakterler ekler. Liste sonra ekranda grntlenir. Elemanlarn bazlar kartlr ve liste
tekrar ekranda grntlenir. Daha sonra, daha fazla eleman eklenir: bu sayede, listenin
kapasitesinin artrlmas zorlanr. Son olarak, elemanlarn ierikleri deitirilir.
// ArrayList kullanimini gosterir.

using System;
using System.Collections;

class ArrayListDemo {
public static void Main() {
// Bir dizi listesi olustur
ArrayList al = new ArrayList();

Console.WriteLine(Initial capacity: +
al.Capacity);
Console.WriteLine(Initial number of elements: +
al.Count);

Console.WriteLine();

Console.WriteLine(Adding 6 elements);
// Dizi listesine eleman ekle
al.Add(C);
al.Add(A);
al.Add(E);
al.Add(B);
al.Add(D);
al.Add(F);

Console.WriteLine(Current capacity: +
al.Capacity);
Console.WriteLine(Number of elements: +
al.Count);

// Dizi indeksleme kullanarak dizi listesini goruntule.
Console.Write(Current contents: );
for(int i = 0; i < al.Count; i++)
Console.Write(al[i] + );
Console.WriteLine(\n);

Console.WriteLine(Removing 2 elements);
// Dizi listesinden eleman cikart.
al.Remove(F);
al.Remove(A);

BLM 22: KOLEKSYONLARLA ALIMAK

HERKES N C#
661
Console.WriteLine(Current capacity: + al.capacity);
Console.WriteLine(Number of elements: + al.Count);

// Listeyi goruntulemek icin foreach dongusu kullan.
Console.Write(Contents: );
foreach(char c in al)
Console.Write(c + );
Console.WriteLine(\n);

Console.WriteLine(Adding 20 more elements);
// alin buyumesini zorlamak icin yeterli eleman ekle.
for(int i = 0; i < 20; i++)
al.Add((char)(a + i));
Console.WriteLine(Current capacity: +
al.Capacity);
Console.WriteLine(Number of elements after adding 20: +
al.Count);
Console.Write(Contents: );
foreach(char c in al)
Console.Write(c + );
Console.WriteLine(\n);

// Dizi indeksleme kullanarak icerigi degistir.
Console.WriteLine(Change first three elements);
al[0] = X;
al[1] = Y;
al[2] = Z;
Console.Write(Contents: );
foreach(char c in al)
Console.Write(c + );
Console.WriteLine();
}
}
Bu programn kts aada gsterilmitir:
Initial capacity: 16
Initial number of elements: 0

Adding 6 elements
Current capacity: 16
Number of elements: 6
Current contents: C A E B D F

Removing 2 elements
Current capacity: 16
Number of elements: 4
Contents: C E B D

Adding 20 more elements
Current capacity: 32
Number of elements after adding 20: 24
Contents: C E B D a b c d e f g h i j k l m n o p q r s t

Change first three elements

HERKES N C#
KISIM II C# KTPHANESN KEFETMEK

662
Contents: X Y Z D a b c d e f g h i j k l m n o p q r s t
Dikkat ederseniz; koleksiyon, 16 balang kapasitesi ile bo olarak balamaktadr. htiya
olduka kapasite artrlmaktadr. Her artrlnda kapasite ikiye katlanr.
ArrayListi Sralamak ve Aramak
ArrayList, Sort() ile sralanabilir. Bir kez sralandktan sonra BinarySearch() ile
verimli biimde aranabilir. Aadaki program bu metotlar gstermektedir:
// ArrayList'i siralamak ve aramak.

using System;
using System.Collections;

class SortSearchDemo {
public static void Main() {
// bir dizi listesi olustur
ArrayList al = new ArrayList();

// Dizi listesine eleman ekle
al.Add(55);
al.Add(43);
al.Add(-4);
al.Add(88);
al.Add(3);
al.Aad(19);

Console.Write(Original contents: );
foreach(int i in al)
Console.Write(i + );
Console.WriteLine(\n);

// Sirala
al.Sort();

// Listeyi goruntulemek icin foreach dongusu kullan.
Console.Write(Contents after sorting: );
foreach(int i in al)
Console.Write(i + );
Console.WriteLine(\n);

Console.WriteLine(Index of 43 is + al.BinarySearch(43));
}
}
kt aada gsterilmitir:
Original contents: 55 43 -4 88 3 19

Contents after.sorting: -4 3 19 43 55 88

Index of 43 is 3
BLM 22: KOLEKSYONLARLA ALIMAK

HERKES N C#
663
Bir ArrayList ayn liste iinde herhangi tipte nesneler saklayabilmesine ramen, bir
listeyi sralarken ya da ararken bu nesnelerin karlatrlabilir olmalar gereklidir. Sz gelii,
nceki programda eer liste bir karakter katar iermi olsayd, program kural d bir durum
retmi olurdu. (Her eye ragmen, karakter katarlarn ve tamsaylar karlatrmaya imkan
veren zel karlatrma metotlar oluturmak mmkndr. zel karlatrclar bu blmn
ileriki sayfalarnda anlatlmtr.)
Bir ArrayListten Bir Dizi Elde Etmek
ArrayList ile alrken kimi zaman sz konusu listenin ieriini ieren gerek anlamda
bir dizi elde etmek isteyeceksiniz. Bunu ToArray()i ararak gerekletirebilirsiniz. Bir
koleksiyonu bir diziye dntrme isteinizin ardnda birka neden olabilir. Bunlardan ikisi
yledir: Belirli ilemler iin daha hzl ilem sreleri elde etmek isteyebilirsiniz ya da bir
diziyi, bir koleksiyonu kabul edecek ekilde ar yklenmemi bir metoda aktarmanz
gerekebilir. Gerekeniz ne olursa olsun, bir ArrayListi bir diziye dntrmek, aadaki
rnekte de grld gibi, nemsiz bir meseledir:
// Bir ArrayListi bir diziye donusturmek.

using System;
using System.Collections;

class ArrayListToArray {
public static void Main() {
ArrayList al = new ArrayList();

// Dizi listesine eleman ekle.
al.Add(1);
al.Add(2);
al.Add(3);
al.Add(4);

Console.Write(Contents: );
foreach(int i in al)
Console.Write(i + );
Console.WriteLine();

// Diziyi al.
int[] ia = (int[]) al.ToArray(typeof(int));
int sum = 0;

// dizi elemanlarini topla
for(int i = 0; i < ia.Length; i++)
sum += ia[i];

Console.WriteLine(Sum is: + sum);
}
}
Programn kts aada gsterilmitir:

HERKES N C#
KISIM II C# KTPHANESN KEFETMEK

664
Contents: 1 2 3 4
Sum is: 10
Program, tamsaylardan oluan bir koleksiyon oluturarak balar. Sonra, int olarak
belirtilen tip ile birlikte ToArray() arlr. Bu, bir tamsay dizisinin oluturulmasna neden
olur. ToArray()in dn tipi Array olduu iin dizinin ierii yine de int[]e
dntrlmelidir. Son olarak, deerler toplanr.
Hashtable
Hashtable, depolama iin bir hash tablosu kullanan bir koleksiyon oluturur.
Okuyucularn birou bilecektir, bir hash tablosu, hashing denilen bir mekanizmay kullanarak
bilgileri saklar. Hashingde bir anahtarn bilgi tayan ierii, hash kod denilen benzersiz bir
deeri belirlemek iin kullanlr. Hash kod daha sonra sz konusu anahtar ile ilikili verilerin
tablo iinde saklanaca konumun indeksi olarak kullanlr. Anahtarn karlk gelen hash
koduna dnm otomatik olarak gerekletirilir - asla hash kodun kendisini grmezsiniz.
Hashingin avantaj; arama, alma ve ayarlama ilemlerinin alma srelerinin byk kmeler
iin bile sabit olarak kalmasna olanak tanmasdr.
Hashtable; IDictionary, ICollection, IEnumerable, ISerializable,
IDeserializationCallback ve ICloneable arayzlerini uygular.
Hashtableda ska kullanlan u fonksiyonlar da dahil olmak zere birok yaplandrc
tanmlanmtr:
public Hashtable()
public Hashtable(IDictionary c)
public Hashtable(int kapasite)
public Hashtable(int kapasite, float dolulukOran)
lk ifade varsaylan Hashtable yaplandrr. kinci ifade, cnin elemanlarn kullanarak
Hashtablea balang deeri atar. nc ifade, Hashtablen kapasitesini kapasite
olarak ayarlar. Drdnc ifade ise hem kapasiteye hem de doluluk oranna ilk deer atar.
Doluluk oran (buna yk faktr de denir) 0.1 ile 1.0 arasnda olmaldr. Doluluk oran, hash
tablosunun yukar ynde yeniden boyutlandrlmasndan nce ne kadar dolu olacan belirler.
Spesifik olarak, eleman says, tablonun kapasitesinin doluluk oran ile arpmndan bykse,
tablo geniletilir. Doluluk oran almayan yaplandrclar iin 1.0 kullanlr.
Hashtablen uygulad arayzler tarafndan tanmlanan metotlara ek olarak
Hashtablen kendisi de birka metot tanmlamaktadr. Yaygn olarak kullanlanlardan
bazlar Tablo 22.5te gsterilmitir. Bir Hashtablen bir anahtar ierip iermediini
belirlemek iin ContainsKey()i arn. Belirli bir deerin saklanp saklanmadn anlamak
iin ContainsValue()yu arn. Bir Hashtablen ieriini numaralandrmak iin
GetEnumerator() ararak bir IDictionaryEnumerator elde edin. Hatrlarsanz,
anahtar/deer iftlerini saklayan bir koleksiyonun ieriini numaralandrmak iin
IDictionaryEnumerator kullanlmaktadr.
BLM 22: KOLEKSYONLARLA ALIMAK

HERKES N C#
665
TABLO 22.5: Hashtable Tarafndan Tanmlanan Metotlardan Ska Kullanlan Birka


Metot Aklama
public virtual bool
ContainsKey(object k)
k, arda bulunan Hashtable iinde bir anahtar
ise true dndrr. Aksi halde, false dndrr.

public virtual bool
ContainsValue(object v)
v, arda bulunan Hashtable iinde bir deer
ise true dndrr. Aksi halde, false dndrr.

public virtual IDictionaryEnumerator
GetEnumerator()
arda bulunan Hashtable iin bir
IDictionaryEnumerator dndrr.

public static Hashtable
Synchronized(Hashtable ht)
ht zerinden aktarlan Hashtablen senkronize
edilmi versiyonunu dndrr.

Hashtablen uygulad arayzler tarafndan tanmlanan bu zelliklere ek olarak,
Hashtablen kendisi de iki ak zellik daha ekler. Aada gsterilen zellikleri kullanarak
Hashtablen anahtarlarndan ya da deerlerinden oluan bir koleksiyon elde edebilirsiniz:
public virtual ICollecticn Keys { get; }
public virtual ICollection Values { get; }
Hashtable ile sral bir koleksiyon desteklenmedii iin elde edilen anahtar ya da deer
koleksiyonunun belirli bir sras yoktur. Hashtable ayrca Hcp ve Comparer adlarnda iki
korumal zellik de tanmlar. Her iki zellik, kendilerinden tretilen snflarn kullanmlarna
aktr.
Hashtable, anahtar/deger iftlerini bir DictionaryEntry yaps eklinde saklar; fakat,
ou zaman bu durumdan direkt olarak haberiniz olmayacaktr, nk sz konusu zellikler ve
metotlar, anahtar ve deerlerle ayr ayr almaktadrlar. Sz gelii, bir Hashtablea bir
eleman eklerseniz, iki argman alan Add()i arrsnz. Add()in argmanlar anahtar ve
deerdir.
Hashtablen elemanlarnn srasn garanti etmediine dikkat ekmek nemlidir. Bunun
nedeni, hashing srecinin genellikle sral tablo oluumuna kendisini katmamasdr.
te, Hashtable kullanmn gsteren bir rnek;
// Hashtable kullanimini gosterir.

using System;
using System.Collections;

class HashtableDemo {
public static void Main() {
// Bir hash tablo olustur.
Hashtable ht = new Hashtable();

// Tabloya eleman ekle.
ht.Add(house, Dwelling);

HERKES N C#
KISIM II C# KTPHANESN KEFETMEK

666
ht.Add(car, Means of transport);
ht.Add(book, Collection of printed words);
ht.Add(apple, Edible fruit);

// Indeksleyiciyi kullanarak da ekleme yapilabilir.
ht[tractor] = Farm implement;

// Anahtarlardan olusan bir koleksiyon al.
ICollection c = ht.Keys;

// Degerleri elde etmek icin anahtarlari kullan.
foreach(string str in c)
Console.WriteLine(str + : + ht[str]);
}
}
Bu programn kts aada gsterilmitir:
tractor: Farm implement
book: Collection of printed words
apple: Edible fruit
car: Means of transport
house: Dwelling
ktdan da grld gibi, anahtar/deer iftleri sral olarak saklanmamaktadr. ht isimli
hash tablosunun ieriinin nasl elde edildiine ve grntlendiine dikkat edin. nce, Keys
zellii kullanlarak anahtarlardan oluan bir koleksiyon alnmtr. Her anahtar daha sonra
htyi indekslemek iin kullanlm, her anahtara karlk gelen deer, sonu olarak elde
edilmitir. Hatrlarsanz, IDictionary tarafndan tanmlanan ve Hashtable tarafndan
uygulanan indeksleyici, indeks olarak bir anahtar kullanmaktadr.
SortedList
SortedList, anahtarlarn deerlerine bal olarak anahtar/deer iftlerini sral olarak
saklayan bir koleksiyon oluturur. SortedList; IDictionary, ICollection,
IEnumerable ve ICloneable arayzlerini uygular.
SortedList, aada gsterilenler de dahil olmak zere, birka yaplandrcya sahiptir:
public SortedList()
public SortedList(IDictionary c)
public SortedList(int kapasite)
public SortedList(IComparer karlatr)
lk yaplandrc, balang kapasitesi olarak 16 deerine sahip bo bir koleksiyon
yaplandrr. kinci yaplandrc, kendisine ilk deer olarak cnin elemanlar ve kapasitesi
atanan bir SortedList yaplandrr. nc yaplandrc, kapasite ile belirtilen balang
kapasitesine sahip bo bir SortedList kurar. Kapasite, elemanlar saklamak iin kullanlan
altta yatan dizinin bykldr. Drdnc ifade, listenin iinde yer alan nesneleri
BLM 22: KOLEKSYONLARLA ALIMAK

HERKES N C#
667
karlatrmak iin kullanlacak bir karlatrma metodu belirtmenize olanak tanr. Bu ifade,
balang kapasitesi 16 olan bo bir koleksiyon oluturur.
Bir dizi listesine elemanlar eklendike SortedListin kapasitesi gerektiinde otomatik
olarak byr. Mevcut kapasitenin almas durumunda kapasite iki katna kartlr. Bir
SortedList olutururken kapasite belirtmenin avantaj, koleksiyonun bykln yeniden
ayarlama ilemiyle ilintili ek yk nleyebilmeniz ya da asgariye indirmenizdir. Elbette,
balang kapasitesi belirtmek, ancak ka adet eleman saklanaca hakknda bir fikriniz varsa
mantkldr.
SortedList'in uygulad arayzler tarafndan tanmlanan metotlara ek olarak
SortedListin kendisi de ayrca birka metot tanmlar. Yaygn olarak kullanlanlardan
bazlar Tablo 22.6da gsterilmitir. Bir SortedListin bir anahtar ierip iermediini
belirlemek iin ContainsKey()i arn. Belirli bir deerin saklanp saklanmadn anlamak
iin ContainsValue()yu arn. Bir SortedListin ieriini numaralandrmak iin
GetEnumerator() ararak bir IDictionaryEnumerator elde edin. Hatrlarsanz,
anahtar/deer iftlerini saklayan bir koleksiyonun ieriini numaralandrmak iin
IDictionaryEnumerator kullanlr. Synchronized() ararak bir SortedList
etrafnda senkronize edilmi bir klf elde edebilirsiniz.
TABLO 22.6: SortedList Tarafndan Tanmlanan Metotlardan Ska Kullanlan Birka


Metot Aklama
public virtual bool ContainsKey(object k) k, arda bulunan SortedList iinde
bir anahtar ise true dndrr. Aksi halde,
false dndrr.
public virtual bool ContainsValue(object
v)
v, arda bulunan SortedList iinde
bir deer ise true dndrr. Aksi halde,
false dndrr.
public virtual object GetByIndex(int idx) idx ile belirtilen indeksteki deeri
dndrr.
public virtual IDictionaryEnumerator
GetEnumerator()
arda bulunan SortedList iin bir
IDictionaryEnumerator dndrr.
public virtual object GetKey(int idx) idx ile belirtilen indeksteki anahtar
dndrr.
public virtual IList GetKeyList() arda bulunan SortedList iindeki
anahtarlarn bir IList koleksiyonunu
dndrr.
public virtual IList GetValueList() arda bulunan SortedList iindeki
deerlerin bir IList koleksiyonunu
dndrr.

HERKES N C#
KISIM II C# KTPHANESN KEFETMEK

668
public virtual int IndexOfKey(object k) k ile belirtilen anahtarn indeksini
dndrr. Anahtar listede deilse -1
dndrr.
public virtual int IndexOfValue(object v) v ile belirtilen deere ilk rastlanlan
konumun indeksini dndrr. Deer listede
deilse -1 dndrr.
public virtual void SetByIndex(int idx,
object v)
idx ile belirtilen indeksteki deere v
zerinden aktarlan deeri atar.
public static SortedList
Synchronized(SortedList sl)
sl zerinden aktarlan SortedListin
senkronize edilmi versiyonunu dndrr.
public virtual void TrimToSize() Capacityye Count deerini atar.
Bir deer ya da anahtar ayarlamak veya elde etmek iin eitli yntemler mevcuttur.
Belirli bir indeks ile ilikili deeri elde etmek iin GetByIndex()i arn. ndeksi verilen bir
deeri ayarlamak iin SetByIndex()i arn. Tm anahtarlarn bir listesini elde etmek iin
GetKeyList()i kullann. Tm deerlerin bir listesini almak iin GetValueList()i
kullann. IndexOfKey()i ararak bir anahtarn indeksini ve IndexOfValue()yu
ararak da deerin indeksini elde edebilirsiniz. SortedList, elbette, IDictionary
tarafndan tanmlanan indeksleyiciyi de ayrca destekler. Bu sayede, anahtar verilen bir deeri
ayarlamanza ya da elde etmenize olanak tannr.
SortedListin uygulad arayzler tarafndan tanmlanan bu zelliklere ek olarak
SortedListin kendisi de iki zellik ekler. Aada gsterilen zellikleri kullanarak bir
SortedListin anahtarlarndan ya da deerlerinden oluan salt okunur bir koleksiyon elde
edebilirsiniz:
public virtual ICollection Keys { get; }
public virtual ICollection Values { get; }
Anahtar ve deerlerin sras SortedListin srasn yanstr.
Tpk Hashtable gibi, SortedList de anahtar/deer iftlerini bir DictionaryEntry
yaps eklinde saklar, fakat genellikle anahtarlara ve deerlere SortedList tarafndan
tanmlanan metotlar ve zellikleri kullanarak ayr ayr erieceksiniz.
Aadaki program SortedList kullanmn gstermektedir. Bu program, nceki
blmdeki Hashtable kullanmn gsteren programn zerinden gidip, Hashtable yerine
SortedListi yerletirerek o program geniletmitir. kty incelediinizde SortedList
versiyonunun anahtara gre sralanm olduunu greceksiniz.
// SortedList kullanimini gosterir.

using System;
using System.Collections;

class SLDemo {
BLM 22: KOLEKSYONLARLA ALIMAK

HERKES N C#
669
public static void Main() {
// Sirali bir SortedList olustur.
SortedList sl = new SortedList();

// Tabloya eleman ekle.
sl.Add(house, Dwelling);
sl.Add(car, Means of transport);
sl.Add(book, Collection of printed words);
sl.Add(apple, Edible fruit);

// Indeksleyiciyi kullanarak da ekleme yapabilirsiniz.
sl[tractor] = Farm implement;

// Anahtarlarin koleksiyonunu al.
ICollection c = sl.Keys;

// Degerleri elde etmek icin anahtarlari kullan.
Console.WriteLine(Contents of list via indexer.);
foreach(string str in c)
Console.WriteLine(str + : + sl[str]);

Console.WriteLine();

// Tamsayi indeksleri kullanarak listeyi goruntule.
Console.WriteLine(Contents by integer indexes.);
for(int i =0; i < sl.Count; i++)
Console.WriteLine(sl.GetByIndex(i));

Console.WriteLine();

// Ogelerin tamsayi indekslerini goster.
Console.WriteLine(Integer indexes of entries.);
foreach(string str in c)
Console.WriteLine(str + : + sl.IndexOfKey(str));
}
}
kt aadadr:
Contents of list via indexer.
apple: Edible fruit
book: Collection of printed words
car: Means of transport
house: Dwelling
tractor: Farm implement

Contents by integer indexes.
Edible fruit
Collection of printed words
Means of transport
Dwelling
Farm implement

Integer indexes of entries.
apple: 0

HERKES N C#
KISIM II C# KTPHANESN KEFETMEK

670
book: 1
car: 2
house: 3
tractor: 4
Stack
Okuyucularn birounun bildii gibi yn, ilk giren son kar ileyiine sahip bir listedir.
Yn gz nnde canlandrmak iin bir masa zerinde bir tabak yn hayal edin. Masaya ilk
konan tabak, en son alnacak tabaktr. Yn, hesaplama amal kullanlan en nemli veri
yaplarndan biridir. Sistem yazlmlar, derleyiciler ve yapay zeka tabanl geri izleme
(backtracking) rutinleri ynn ska kullanld alanlardan yalnzca birkadr.
Bir yn destekleyen koleksiyon snf Stack olarak adlandrlr. Stack snf
ICollection, IEnumerable ve ICloneable arayzlerini uygular. Stack, saklamas
gereken elemanlar barndrabilmesi iin gerektiinde byyen dinamik bir koleksiyondur.
Kapasitenin artrlmas gerektiinde kapasite ikiye katlanr.
Stackte aadaki yaplandrclar tanmldr:
public Stack()
public Stack(int kapasite)
public stack(ICollection c)
lk ifade, 10 deerinde balang kapasitesine sahip bo bir yn oluturur. kinci ifade,
kapasite ile belirtilen balang kapasitesine sahip bo bir yn oluturur. nc ifade ise c
ile belirtilen koleksiyonun eleman saysn ve kapasitesini ieren bir yn kurar.
Stackin uygulad arayzler tarafndan tanmlanan metotlara ek olarak Stackin kendisi
de Tablo 22.7de gsterilen metotlar tanmlar. Genel olarak, Stacki ite u ekilde
kullanrsnz. Ynn en stne bir nesne eklemek iin Push()u arn. Ynn en stndeki
eleman karmak ve dndrmek iin Pop()u arn. Pop()u ardnz yn eer bo ise,
bir InvalidOperationException frlatlr. Ynn en stndeki nesneyi yndan
kartmadan dndrmek iin Peek()i kullanabilirsiniz.

TABLO 22.7: Stack Tarafndan Tanmlanan Metotlar


Metot Aklama
public virtual bool Contains(object
v)
v, arda bulunan ynda ise true dndrr.
Eer v mevcut deilse, false dndrr.
public virtual void Clear() Counta sfr deerini atar. Bu, etkin biimde
yn temizler.
public virtual object Peek() arda bulunan ynn en stndeki nesneyi
dndrr, fakat nesne yndan kartlmaz.
BLM 22: KOLEKSYONLARLA ALIMAK

HERKES N C#
671
public virtual object Pop() arda bulunan ynn en stndeki nesneyi
dndrr. Nesne bu ilem srasnda yndan
kartlr.
public virtual object Push(object v) vyi yna yerletirir.
public static Stack
Synchronized(Stack stk)
stk zerinden aktarlan Stackn senkronize
edilmi versiyonunu dndrr.
public virtual object[] ToArray() arda bulunan ynn elemanlarnn
kopyalarn ieren bir dizi dndrr.
te, bir yn oluturan, bu yna birka Integer nesnesi yerletiren ve sonra bunlar
tekrar yndan kartan bir rnek:
// Stack sinifini gosterir.

using System;
using System.Collections;

class StackDemo {
static void showPush(Stack st, int a) {
st.Push(a);
Console.WriteLine(Push( + a + ));

Console.Write(stack: );
foreach(int i in st)
Console.Write(i + );

Console.WriteLine();
}

static void showPop(Stack st) {
Console.Write(Pop -> );
int a = (int) st.Pop();

Console.WriteLine(a);

Console.Write(stack: );
foreach(int i in st)
Console.Write(i + );

Console.WriteLine();
}

public static void Main() {
Stack st = new Stack();

foreach(int i in st)
Console.Write(i + );

Console.WriteLine();

showPush(st, 22);
showPush(st, 65);

HERKES N C#
KISIM II C# KTPHANESN KEFETMEK

672
showPush(st, 91);
showPop(st);
showPop(st);
showPop(st);

try {
showPop(st);
} catch (InvalidOperationException) {
Console.WriteLine(Stack empty.);
}
)
}
Program tarafndan retilen kt aadaki gibidir. Yn boken yndan eleman
alnmaya allnca ortaya kan InvalidOperationExcception, kural d durum
yneticisinin nasl kontrol altna aldna dikkat edin.
Push(22)
stack: 22
Push(65)
stack: 65 22
Push(91)
stack: 91 65 22
Pop -> 91
stack: 65 22
Pop -> 65
stack: 22
Pop -> 22
stack:
Pop -> Stack empty.
Queue
Bir baka tandk veri yaps ise kuyruktur. Kuyruk, ilk giren ilk kar ileyiine sahip bir
listedir. Yani, bir kuyrua yerletirilen ilk e kuyruktan kartlacak ilk edir. Kuyruklar
gerek hayatta ska karmza kar. Sz gelii, bir bankadaki ya da fast-food restoranndaki
sralar kuyruktur. Programlamada kuyruklar; sistemde halen almakta olan prosesler, askda
olan veri taban ilemleri ya da Internet zerinden alnan veri paketleri gibi eyleri tutmak iin
kullanlrlar. Ayrca simlasyonlarda da ska kullanlmaktadrlar.
Bir kuyruu destekleyen koleksiyon snf Queue olarak adlandrlr Queue snf
ICollection, IEnumerable ve ICloneable arayzlerini uygular. Queue, saklamas
gereken elemanlar barndrabilmesi iin gerektiinde byyen dinamik bir koleksiyondur.
Daha fazla yere ihtiya olduunda kuyruun bykl byme faktr orannda artrlr.
Byme faktrnn varsaylan deeri 2.0dir.
Queueda aadaki yaplandrclar tanmldr:
public Queue()
public Queue (int kapasite)
public Queue (int kapasite, float bymeFaktr)
BLM 22: KOLEKSYONLARLA ALIMAK

HERKES N C#
673
public Queue (ICollection c)
lk ifade, balang kapasitesi 32 olan bo bir kuyruk oluturur ve 2.0 deerindeki
varsaylan byme faktrn kullanr. kinci ifade, balang kapasitesi kapasite ile
belirtilen ve 2.0 byme faktrne sahip bo bir kuyruk oluturur. nc ifade,
bymeFaktr iinde bir byme faktr belirtmenize olanak tanr. Drdnc ifade ise, c
ile belirtilen koleksiyonun eleman saysna ve kapasitesine sahip bir kuyruk yaplandrr. Bu
ifadede 2.0 deerindeki varsaylan byme faktr kullanlr.
Queuenun uygulad arayzler tarafndan tanmlanan metotlara ek olarak Queuenun
kendisi de Tablo 22.8de gsterilen metotlar tanmlar. Genel olarak, Queueyu u ekilde
kullanrsnz. Kuyrua bir nesne yerletirmek iin Enqueue()yu arn. Kuyruun bandaki
nesneyi karp dndrmek iin Dequeue()yu kullann. Dequeue() ile arlan kuyruk bo
ise bir InvalidOperationException frlatlr. Bir sonraki nesneyi kuyruktan kartmadan
dndrmek iin Peek() kullanabilirsiniz.
TABLO 22.8: Queue Tarafndan Tanmlanan Metotlar


Metot Aklama
public virtual bool Contains(object
v)
v, arda bulunan kuyruk iinde ise true
dndrr. Eer v mevcut deilse, false
dndrr.
public virtual void Clear() Counta sfr deerini atar. Bu, etkin biimde
kuyruu temizler.
public virtual object Dequeue() arda bulunan kuyruun nndeki nesneyi
dndrr. Nesne bu ilem srasnda kuyruktan
kartlr.
public virtual void Enqueue(object v) vyi kuyruun sonuna ekler.
public virtual object Peek() arda bulunan kuyruun nndeki nesneyi
dndrr, fakat nesne kuyruktan kartlmaz.
public static Queue
Synchronized(Queue q)
qnun senkronize edilmi versiyonunu dndrr.
public virtual object[] ToArray() arda bulunan kuyruun elemanlarnn
kopyalarn ieren bir dizi dndrr.
public virtual void TrimToSize() Capacityye Countun deerini atar.
te, Queue snfn gsteren bir rnek:
// Queue sinifini gosterir.

using System;
using System.Collections;


HERKES N C#
KISIM II C# KTPHANESN KEFETMEK

674
class QueueDemo {
static void showEnq(Queue q, int a) {
q.Enqueue(a);
Console.WriteLine(Enqueue( + a + ));

Console.Write(queue: );
foreach(int i in q)
Console.Write(i + );

Console.WriteLine();
}

static void showDeq(Queue q) {
Console.Write(Dequeue -> );
int a = (int) q.Dequeue();
Console.WriteLine(a);

Console.Write(queue: );
foreach(int i in q)
Console.Write(i + );

Console.WriteLine();
}

public static void Main() {
Queue q = new Queue();

foreach(int i in q)
Console.Write(i + );

Console.WriteLine();

showEnq(q, 22);
showEnq(q, 65);
showEnq(q, 91);
showDeq(q);
showDeq(q);
showDeq(q);

try {
showDeq(q);
} catch (InvalidOperationException) {
Console.WriteLine(Queue empty.);
}
}
}
kt aada gsterilmitir:
Enqueue(22)
queue: 22
Enqueue(65)
queue: 22 65
Enqueue(91)
queue: 22 65 91
BLM 22: KOLEKSYONLARLA ALIMAK

HERKES N C#
675
Dequeue -> 22
queue: 65 91
Dequeue -> 65
queue: 91
Dequeue -> 91
queue:
Dequeue -> Queue empty.
BitArray le Bitleri Saklamak
BitArray snf, bitlerden oluan bir koleksiyonu destekler. BitArray, nesneler yerine
bitleri saklad iin dier koleksiyonlardan daha farkl becerilere sahiptir. Yine de, BitArray;
ICollection ve IEnumerable uygulayarak temel koleksiyon esaslarn da destekler.
Ayrca ICloneable da uygulamaktadr.
BitArrayde birka yaplandrc tanmldr. Aadaki yaplandrcy kullanarak Boolean
deerlerinden oluan bir diziden bir BitArray yaplandrabilirsiniz:
public BitArray(bool[] bitler)
Bu durumda bitlerin her eleman sz konusu koleksiyonun biti olur. Bylece,
koleksiyondaki her bit, bitlerin bir elemanna karlk gelir. stelik, bitler iindeki
elemanlarn sras ile koleksiyondaki bitlerin sras ayndr.
Aadaki yaplandrcy kullanarak bir byte dizisinden bir BitArray oluturabilirsiniz:
public BitArray(byte[] bitler)
Burada bitler iindeki bit modeli, koleksiyon iindeki bitlerin modeli olur. bitler[0],
ilk 8 biti belirtir; bitler[1] ikinci 8 biti belirtir vs. Benzer ekilde, aadaki yaplandrcy
kullanarak bir tamsay dizisinden bir BitArray yaplandrabilirsiniz:
public BitArray(int[] bitler)
Bu durumda bitler[0] ilk 32 biti; bitler[1] ikinci 32 biti vs belirtir.
u yaplandrcy kullanarak belirli bir byklkte bir BitArray oluturabilirsiniz:
public BitArray(int byklk)
Burada byklk, bit saysn belirtir. Koleksiyon iindeki bitlere ilk deer olarak false
atanr. Bykl ve bitler iin ilk deerleri belirtmek iin aadaki yaplandrcy kullann:
public BitArray(int byklk, bool v)
Bu durumda koleksiyondaki tm bitler v zerinden aktarlan deere gre ayarlanacaktr.
Son olarak, aadaki yaplandrcy kullanarak mevcut olan bir BitArrayden yeni bir
BitArray oluturabilirsiniz:
public BitArray(BitArray bitler)

HERKES N C#
KISIM II C# KTPHANESN KEFETMEK

676
Yeni nesne, bitler ile ayn bit koleksiyonunu ierecektir, fakat iki koleksiyon dier
bakmlardan ayr olacaktr.
BitArrayler indekslenebilir. Her indeks ayr bir biti belirtir. Sfr deerine sahip alt bite
iaret eder.
BitArrayin uygulad arayzler tarafndan belirlilen metotlara ek olarak BitArrayin
kendisi de Tablo 22.9da gsterilen metotlar tanmlar. BitArrayin Synchronized()
metodunu salamadna dikkat edin. Bu nedenle, senkronize edilmi bir klf mevcut deildir
ve IsSynchronized zellii daima falsetur. Ancak, SyncRoot tarafndan salanan nesne
zerinde senkronizasyon yaparak BitArraye eriimi kontrol edebilirsiniz.
BitArrayin uygulad arayzler tarafndan belirtilen zelliklere BitArray aada
gsterilen Length zelliini de ekler:
public int Length { get; set; }
Length, koleksiyon iindeki bitlerin saysn ayarlar ya da elde eder. Bylece, Length;
tm koleksiyonlar iin tanml olan standart Count zellii ile ayn deeri verir. Ancak, Count
salt okunur bir zelliktir; fakat Length deildir Bylece, bir BitArrayin bykln
deitirmek iin Length kullanlabilir. Eer bir BitArrayi ksaltrsanz, st utaki bitler
kesilir. Bir BitArrayi uzatrsanz, st uca sfr deerinde bitler eklenir.
TABLO 22.9: BitArray Tarafndan Tanmlanan Metotlar


Metot Aklama
public BitArray And(BitArray ba) arda bulunan nesnenin bitleri ile ba ile
belirtilen bitlere VE uygular. Sonucu ieren bir
BitArray dndrr.
public bool Get(int idx) idx ile belirtilen indeksteki bitin deerini
dndrr.
public BitArray Not() arda bulunan koleksiyon zerinde bit tabanl
mantksal DEL ilemi gerekletirir ve sonucu
ieren bir BitArray dndrr.
public BitArray Or(BitArray ba) arda bulunan nesnenin bitleri ile ba ile
belirtilen bitlere VEYA uygular. Sonucu ieren
bir BitArray dndrr.
public void Set(int idx, bool v) idx ile belirtilen indeksteki bite v deerini verir.
public void SetAll(bool v) Tm bitlere v deerini verir.
public BitArray Xor(BitArray ba) arda bulunan nesnenin bitleri ile ba ile
belirtilen bitlere XOR uygular. Sonucu ieren bir
BitArray dndrr.
BitArrayde aadaki indeksleyici tanmldr:
BLM 22: KOLEKSYONLARLA ALIMAK

HERKES N C#
677
object this[int idks] { get; set; }
Bir elemann deerini almak ya da ayarlamak iin bu indeksleyiciyi kullanabilirsiniz.
te, BitArrayi gsteren bir rnek:
// BitArrayi gosterir.

using System;
using System.Collections;

class BADemo {
public static void showbits(string rem, BitArray bits) {
Console.WriteLine(rem);

for(int i = 0; i < bits.Count; i++)
Console.Write({0, -6} , bits[i]);

Console.WriteLine(\n);
}

public static void Main() {
BitArray ba = new BitArray(8);
byte[] b = { 67 };
BitArray ba2 = new BitArray(b);

showbits(Original contents of ba:, ba);

ba = ba.Not();

showbits(Contents of ba after Not:, ba);

showbits(Contents of ba2:, ba2);

BitArray ba3 = ba.Xor(ba2);

showbits(Result of ba XOR ba2:, ba3);
}
}
kt aada gsterilmitir:
Original contents of ba:
False False False False False False False False

Contents of ba after Not:
True True True True True True True True

Contents of ba2:
True True False False False False True False

Result of ba XOR ba2:
False False True True True True False True

HERKES N C#
KISIM II C# KTPHANESN KEFETMEK

678
zelletirilmi Koleksiyonlar
.NET Framework belirli bir veri tipi zerinde ya da belirli bir ekilde almak zere
optimize edilmi baz zelletirilmi koleksiyonlar salar. Bu koleksiyon snflar
System.Collections.Specialized isim uzaynda tanmlanmlardr. Aadaki tabloda
bunlarn bir zeti yer almaktadr:
zelletirilmi Koleksiyon Aklama
CollectionsUtil Karakter katarlarnda byk-kk harf ayrmn dikkate
almayan bir koleksiyon.
HybridDictionary Koleksiyon iinde birka eleman olduu zaman anahtar/deer
iftlerini saklamak iin bir ListDictionary kullanan bir
koleksiyon. Koleksiyon belirli bir bykln tesine geerse
elemanlar saklamak iin otomatik olarak bir Hashtable
kullanlr.
ListDictionary Anahtar/deer iftlerini bir bal liste iinde saklayan bir
koleksiyon. Yalnzca kk koleksiyonlar iin nerilir.
NameValueCollection Anahtar ve deerin her ikisinin de string tipinde olduu
anahtar/deer iftlerinden oluan bir koleksiyon.
StringCollection Karakter katarlarn saklamak iin optimize edilmi bir
koleksiyon.
StringDictionary Anahtar ve deerin her ikisinin de string tipinde olduu
anahtar/deer iftlerinden oluan bir hash tablo.
Systems.Collectionsda ayrca zet temel snf daha tanmldr:
CollectionBase, ReadOnlyCollectionBase ve DictionaryBase. Bu snflar kaltm
yoluyla aktarlabilir ve kullanma uygun zelletirilmi koleksiyonlarn gelitirilmesi iin
balang noktas olarak kullanlabilirler.
Bir Numaralandrc zerinden Bir Koleksiyona
Erimek
Genellikle bir koleksiyonun elemanlar zerinde ilerlemek isteyeceksiniz. Sz gelii,
elemanlarn her birini grntlemek isteyebilirsiniz. Bunu gerekletirmenin bir yolu, nceki
rneklerde yapld gibi bir foreach dngs kullanmaktr. Bir dier yntem ise bir
numaralandrc kullanmaktr. Numaralandrc, IEnumerator arayzn uygulayan bir
nesnedir.
IEnumeratorda Current adndan bir tek zellik tanmldr. Current aada
gsterilmitir:
object Current { get; }
BLM 22: KOLEKSYONLARLA ALIMAK

HERKES N C#
679
Current, halihazrda numaralandnlmakta olan eleman elde eder. Current salt okunur
bir zellik olduu iin, bir numaralandrc yalnzca koleksiyon iindeki nesneleri almak iin
kullanlabilir, deitirmek iin kullanlamaz.
IEnumerator iki metot tanmlar, lki MoveNext()tir:
bool MoveNext()
MoveNext()e yaplan her ar, numaralandrcnn mevcut konumunu koleksiyon
iindeki bir sonraki elemana kaydrr. Bir sonraki eleman mevcut ise metot true dndrr,
eer koleksiyonun sonuna gelinmise false dndrr. MoveNext()e yaplan ilk ardan
nce Currentn deeri tanmszdr.
Reset()i armak suretiyle numaralandrcy koleksiyonun bana kaydrarak
sfrlayabilirsiniz:
void Reset()
Reset()i ardktan sonra numaralandrma koleksiyonun bandan balar; ilk eleman
elde etmek iin MoveNext()i armalsnz.
Numaralandrc Kullanmak
Bir koleksiyona bir numaralandrc araclyla eriebilmeniz iin ncelikle bir
numaralandrc elde etmi olmalsnz. Koleksiyon snflarnn her biri, koleksiyonun bana bir
numaralandrc dndren GetEnumerator() metodunu salarlar. Bu numaralandrcy
kullanarak, bir kerede bir elemana erimek suretiyle koleksiyonun elemanlarnn her birine
eriebilirsiniz. Genel olarak, bir koleksiyonun ierii zerinde dnerek ilerlemek amacyla bir
numaralandrc kullanmak iin aadaki admlar takip edin:
1. Koleksiyonun GetEnumerator() metodunu ararak koleksiyonun ba iin bir
numaralandrc elde edin.

2. MoveNext()e arda bulunan bir dng kurun. MoveNext(), true dndrd
srece dngnn tekrarlamasn salayn.

3. Dng iinde Current araclyla elemanlarn her birini elde edin.
te, bu admlar uygulayan bir rnek. Bu program bir ArrayList kullanmaktadr, fakat
genel prensipler her trl koleksiyon tipi iin geerlidir.
// Bir numaralandirici gosterir.

using System;
using System.Collections;

class EnumeratorDemo {
public static void Main() {
ArrayList list = new ArrayList(1);

HERKES N C#
KISIM II C# KTPHANESN KEFETMEK

680

for(int i = 0; i < 10; i++)
list.Add(i);

// Listeye erismek icin numaralandirici kullan.
IEnumerator etr = list.GetEnumerator();
while(etr.MoveNext())
Console.Write(etr.Current + );

Console.WriteLine();

// Listeyi yeniden numaralandir.
etr.Reset();
while(etr.MoveNext())
Console.Write(etr.Current + );

Console.WriteLine();
}
}
kt aada gsterilmitir:
0 1 2 3 4 5 6 7 8 9
0 1 2 3 4 5 6 7 8 9
Genel olarak, bir koleksiyonun zerinde ilerlemeniz gerekince foreach dngs
numaralandrmadan daha kullanldr. Bununla birlikte; numaralandrc kullanm, istee bal
olarak numaralandrcy sfrlamanza olanak tanyarak kk bir ek kontrol sunmaktadr.
IDictionaryEnumerator Kullanm
IDictionaryyi uygulayan bir koleksiyon snf anahtar/deer iftlerini saklar. Bu tr bir
koleksiyonun elemanlar zerinde tekrarlama yaparken IEnumerator yerine
IDictionaryEnumerator kullanacaksnz. IDictionaryEnumerator, IEnumeratordan
kaltmla tretilmitir; ayrca zellik daha ierir. Bu zelliklerin ilki udur:
DictionaryEntry Entry { get; }
Entry, bir DictionaryEntry yaps eklinde olan numaralandrcdan bir sonraki
anahtar/deer iftini alr. DictionaryEntrynin Key ve Value adnda iki zellik
tanmladn ve bu zelliklerin koleksiyon girdisinin ierdii anahtar ya da deere erimek iin
kullanlabildiini hatrlayn. IDictionaryEnumerator tarafndan tanmlanan dier iki
zellik aada gsterilmitir:
object Key { get; }
object Value { get; }
Bunlar anahtar ve deere dorudan erimenize imkan verirler.
IDictionaryEnumerator tpk sradan numaralandrc gibi kullanlr. Tek fark, bu kez
mevcut deeri Current yerine Entry, Key ve Value zellikleri araclyla elde
BLM 22: KOLEKSYONLARLA ALIMAK

HERKES N C#
681
edebileceksiniz. Bylece, bir IDictionaryEnumerator elde ettikten sonra ilk elemana
erimek iin MoveNext()i armalsnz. Koleksiyondaki kalan elemanlar da elde etmek
iin MoveNext()i armaya devam edin. Artk hi eleman kalmadnda MoveNext()
false dndrr.
te, bir Hashtable iindeki elemanlar bir IDictionaryEnumerator araclyla
numaralandran bir rnek:
// IdictionaryEnumeratori gosterir.

using System;
using System.Collections;

class IDicEnumDemo {
public static void Main() {
// Bir hash tablosu olustur.
Hashtable ht = new Hashtable();

// Tabloya eleman ekle.
ht.Add(Tom, 555-3456);
ht.Add(Mary, 555-9876);
ht.Add(Todd, 555-3452);
ht.Add(Ken, 555-7756);

// Numaralandiriciyi goster.
IDictionaryEnumerator etr = ht.GetEnumerator();
Console.WriteLine(Display info using through Entry.);
while(etr.MoveNext())
Console.WriteLine(etr.Entry.Key + : +
etr.Entry.Value);

Console.WriteLine();

Console.WriteLine(Display info using Key and Value
directly.);
etr.Raset();
while(etr.MoveNext())
Console.WriteLine(etr.Key + : + etr.value);
}
}
kt aada gsterilmitir:
Display info using through Entry.
Tom: 555-3456
Todd: 555-3452
Ken: 555-7756
Mary: 555-9876

Display info using Key and Value directly.
Tom: 555-3456
Todd: 555-3452
Ken: 555-7756
Mary: 555-9876

HERKES N C#
KISIM II C# KTPHANESN KEFETMEK

682
Koleksiyonlar inde Kullanc Tarafndan Tanmlanan
Snflar Saklamak
Basit olsun diye nceki rnekler bir koleksiyon iinde int, string ya da char gibi
standart tipleri saklamlard. Koleksiyonlar elbette standart nesnelerin depolanmas ile snrl
deildir. Aslnda ama bununla olduka zttr. Koleksiyonlarn gc, kendi oluturduunuz
snflara ait nesneler de dahil olmak zere herhangi tipteki nesneyi saklayabilmesindedir.
rnein, aadaki program ele aln. Bu program, Inventory snf iine paketlenen envanter
bilgilerini saklamak iin bir ArrayList kullanmaktadr.
// Basit bir envanter program.

using System;
using System.Collections;

class Inventory {
string name;
double cost;
int onhand;

public Inventory(string n, double c, int h) {
name = n;
cost = c;
onhand = h;
}

public override string ToString() {
return
String.Format({0,-10}Cost: {1,6:C} Onhand: {2},
name, cost, onhand);
}
}

class InventoryList {
public static void Main() {
ArrayList inv = new ArrayList();

// Listeye eleman ekle.
inv.Add(new Inventory(Pliers, 5.95, 3));
inv.Add(new Inventory(Wrenches, 8.29, 2));
inv.Add(new Inventory(Hammers, 3.50, 4));
inv.Add(new Inventory(Drills, 19.88, 8));

Console.WriteLine(Inventory list:);
foreach(Inventory i in inv) {
Console.WriteLine( + i);
}
}
}
Programn kts aada gsterilmitir:
BLM 22: KOLEKSYONLARLA ALIMAK

HERKES N C#
683
Inventory list:
Pliers Cost: $5.95 On hand: 3
Wrenches Cost: $8.29 On hand: 2
Hammers Cost: $3.50 On hand: 4
Drills Cost: $19.88 On hand: 8
Programda, Inventory tipinde nesneleri bir koleksiyon iinde saklamak iin zel bir
ileme gerek olmadna dikkat edin. Tm tipler objectten tretildikleri iin herhangi tipten
bir nesne genel amal herhangi bir koleksiyon iinde saklanabilir.
Yukardaki programla ilgili dikkat ekici bir baka husus daha sz konusudur: Program ol-
duka ksadr. Bu programn 40 satrdan daha az bir kod ile envanter bilgilerini saklayabilen,
geri alabilen ve ileyebilen dinamik bir dizi kurduunu ele alrsak, koleksiyonlarn gc netlik
kazanmaya balar. Okuyucularn birou bilecektir, bu ilevselliin tm elle kodlanm ol-
sayd, program birka kat daha uzun olurdu. Koleksiyonlar ok eitli programlama problemle-
rine kesin zmler sunarlar. Gerektiinde bunlar kullanmalsnz.
nceki programn annda fark edilemeyen kstlayc bir yn de vardr: Sz konusu
koleksiyon sralanamaz. Bunun gerekesi, ArrayListin iki Inventory nesnesini nasl
karlatraca hakknda bilgi sahibi olmamasdr. Bu durumu dzeltmek iin iki yntem
mevcuttur. ncelikle Inventory, IComparable arayzn uygulayabilir. Bu arayz, bir
snfa ait iki nesnenin nasl karlatrlacan tanmlar. kincisi, karlatrma gerekli
olduunda bir IComparer nesnesi belirtilebilir. Aadaki blmlerde her iki yaklam
rneklenmektedir.
IComparablei Uygulamak
Kullanc tarafndan tanmlanan nesnelerden oluan bir ArrayListi sralamak isterseniz
(ya da bu nesneleri bir SortedList iinde saklamak isterseniz), sz konusu koleksiyon bu
nesneleri nasl karlatracan bilmelidir. Bunu gerekletirmenin bir yolu, saklanmakta olan
nesnenin IComparable arayzn uygulamasdr. IComparable yalnzca tek bir metot
tanmlar: CompareTo(). CompareTo(), karlatrmalarn nasl gerekletirileceini belirler.
CompareTo()nun genel kullanm ekli aada gsterilmitir:
int CompareTo(object nesne)
CompareTo(), metodu aran nesneyi nesne ile karlatrr. Artan srada sralamak iin
uygulamanz, nesneler eitse sfr dndrmelidir; arda bulunan nesne nesneden bykse
sfrdan byk bir deer dndrmeli; arda bulunan nesne nesneden kkse sfrdan kk
bir deer dndrmelidir. Karlatrmann sonucunu tersinden ele alarak azalan srada sralama
yapabilirsiniz. Eer nesnenin tipi, arda bulunan nesnenin tipi ile karlatrlmak iin
uyumlu deilse metot, bir ArgumentException frlatabilir.
te, IComparablen nasl uygulandn gsteren bir rnek. Program, nceki blmde
gelitirilen Inventory snfna IComparable ekler. IComparable uygulayarak program
Inventory nesnelerinden oluan bir koleksiyonunun sralanmasna olanak tanr.

HERKES N C#
KISIM II C# KTPHANESN KEFETMEK

684
// IComparablei uygular.

using System;
using System.Collections;

class Inventory : IComparable {
string name;
double cost;
int onhand;

public Inventory(string n, double c, int h) {
name = n;
cost = c;
onnhand = h;
}

public override string ToString() {
return
String.Format({0,-10}Cost: {1,6:C} On hand: {2},
name, cost, onhand);
}

// IComparable arayuzunu uygula.
public int CompareTo(object obj) {
Inventory b;
b = (Inventory) obj;
return name.CompareTo(b.name);
}
}

class IComparableDemo {
public static void Main() {
ArrayList inv = new ArrayList();

// listeye eleman ekle
inv.Add(new Inventory(Pliers, 5.95, 3));
inv.Add(new Inventory(Wrenches, 8.29, 2));
inv.Add(new Inventory(Hammers, 3.50, 4));
inv.Add(new Inventory(Drills, 19.88, 8));

Console.WriteLine(Inventory list before sorting:);
foreach(Inventory i in inv) {
Console.WriteLine( + i);
}
Console.WriteLine();

// Listeyi sirala.
inv.Sort();

Console.WriteLine(Inventory list after sorting:);
foreach(Inventory i in inv) {
Console.WriteLine( + i);
}
}
}
BLM 22: KOLEKSYONLARLA ALIMAK

HERKES N C#
685
kt u ekildedir. Dikkat ederseniz, Sort()a yaplan ardan sonra envanter isme gre
sralanmtr.
Inventory list before sorting:
Pliers Cost: $5.95 On hand: 3
Wrenches Cost: $8.29 On hand: 2
Hammers Cost: $3.50 On hand: 4
Drills Cost: $19.88 On hand: 8

Inventory list after sorting:
Drills Cost: $19.88 On hand: 8
Hammers Cost: $3.50 On hand: 4
Pliers Cost: $5.95 On hand: 3
Wrenches Cost: $8.29 On hand: 2
ICompareri Belirtmek
Kendi oluturduunuz snflara ait nesnelerin bir koleksiyon tarafndan sralanmasna
imkan vermek amacyla bu snflar iin IComparable uygulamak en kolay yntem olmasna
ramen bu probleme IComparer kullanarak farkl bir adan yaklaabilirsiniz. IComparer
kullanmak iin ncelikle ICompareri uygulayan bir snf oluturun, sonra karlatrmalar
gerekli olduunda bu snfa ait bir nesne belirtin. IComparerde yalnzca bir tek metot
tanmldr: Compare(). Compare() aada gsterilmitir:
int Compare(object nesne1, object nesne2)
Compare(), nesne1i nesne2 ile karlatrr. Uygulamanz, artan srada sralamak iin,
nesneler eit ise sfr dndrmelidir; nesne1, nesne2den bykse pozitif bir deer
dndrmeli; nesne1, nesne2den kkse negatif bir deer dndrmelidir. Karlatrmann
sonucunu tersinden ele alarak azalan srada sralama yapabilirsiniz. arda bulunan nesne ile
nesne tipi karlatrma iin uyumlu deilse metot, bir ArgumentException frlatabilir.
IComparer; bir SortedList yaplandrrken, ArrayList.Sort(IComparer)
arlrken ve koleksiyon snflar iinde eitli dier konumlarda belirtilebilir. IComparer
kullanmann balca avantaj, IComparable uygulamayan snflarn nesnelerini de
sralayabiliyor olmanzdr.
Aadaki program, envanter programnn, envanter listesini sralamak iin IComparer
kullanacak ekilde yeniden allm bir versiyonudur. Program ncelikle ICompareri
uygulayan CompInv adnda bir snf oluturur ve iki Inventory nesnesini karlatrr. Bu
snfa ait bir nesne daha sonra envanter listesini sralamak iin Sort() arsnda kullanlr.
// IComparer kullanir.

using System;
using System.Collections;

// Inventory nesneleri icin bir IComparer olustur.
class CompInv : IComparer {

HERKES N C#
KISIM II C# KTPHANESN KEFETMEK

686
// IComparable arayuzunu uygula.
public int Compare(object obj1, object obj2) {
Inventory a, b;
a = (Inventory) obj1;
b = (Inventory) obj2;
return a.name.CompareTo(b.name);
}
}

class Inventory {
public string name;
double cost;
int onhand;

public Inventory(string n, double c, int h) {
name = n;
cost = c;
onhand = h;
}

public override string ToString() {
return
String.Format({0,-10}Cost: {1,6:C} On hand: {2},
name, cost, onhand);
}
}

class MailList {
public static void Main() {
CompInv comp = new CompInv();
ArrayList inv = new ArrayList();

// Elemanlari listeye ekle.
inv.Add(new Inventory(Pliers, 5.95, 3));
inv.Add(new Inventory(Wrenches, 8.29, 2));
inv.Add(new Inventory(Hammers, 3.50, 4));
inv.Add(new Inventory(Drills, 19.88, 8));

Console.WriteLine(Inventory list before sorting:);
foreach(Inventory i in inv) {
Console.WriteLine( + i);
}
Console.WriteLine();

// IComparer kullanarak listeyi sirala.
inv.Sort(comp);

Console.WriteLine(Inventory list after sorting:);
foreach(Inventory i in inv) {
Console.WriteLine( + i);
}
}
}
kt programn bir nceki versiyonunun kts ile ayndr.
BLM 22: KOLEKSYONLARLA ALIMAK

HERKES N C#
687
Koleksiyonlarn zeti
Koleksiyonlar, siz programclara, programlamann en yaygn grevlerinden bazlar iin iyi
tasarlanm, gl birtakm zmler sunar. Bilgileri saklamanz ve geri almanz gereken bir
sonraki ilemde bir koleksiyon kullanmay dnn. Koleksiyonlarn yalnzca byk iler
iin ayrlmalar gerekmez. Sz gelii, kurumsal veri tabanlar, posta listeleri ya da envanter
sistemleri gibi. Koleksiyonlar daha kk ilere uygulandklarnda da etkilidirler. rnein, bir
SortedList, gnlk randevularn listesini tutmak iin mkemmel bir koleksiyon oluturur.
Koleksiyon temelli zmlerden yararlanacanz problem trleri, yalnzca hayal gcnzle
snrldr.



Y R M N C B L M


INTERNET LE A
UYGULAMALARI





















23
BLM 22: KOLEKSYONLARLA ALIMAK

HERKES N C#
689
C-#, modern hesaplama ortamlar iin tasarlanm bir dildir. yle ki, bu ortamlarn
nemli bir parasn internet oluturmaktadr. Bu yzden, C#n tasarmndaki ana kriter,
Internet kullanm iin gerekli zellikleri dahil etmekti. Internete erimek, dosyalar indirmek
ve kaynaklar elde etmek iin C ve C++ gibi nceki diller de kullanlabilir olmasna ramen
bu sre, birok programcnn beenisini kazanacak kadar standardize edilmemiti. C# bu
durumu zme kavuturmutur. C#n ve .NET Librarynin standart zelikleri kullanlarak
uygulamalarnz Internet-olanakl klmak kesinlikle kolaydr.
A oluturma (networking) destei iki isim uzaynda yer almaktadr. Birincisi
System.Nettir. System.Net, Internet ortamnda yaygn, eitli tipte ilemleri destekleyen
yksek dzeyli, kullanm kolay ok sayda snf tanmlar. kincisi,
System.Net.Socketsdir. Bu isim uzay, a oluturma zerinde dk dzeyli kontrol
sunan soketleri destekler. System.Net tarafndan salanan snflar, sunduklar rahatlktan
dolay bir ok uygulama iin daha iyi bir seenektir; bu blmde biz de bu isim uzayn
kullanacaz.
NOT

Sunucu taraf iin destek, ASP.NET tabanl a uygulamalar System.Web isim
uzaynda bulunur.
System.Net yeleri
System.Net birok ye ieren byk bir isim uzaydr. Bunlarn tmn burada
incelemeyecek olmamza ramen, nelerin sizin kullanmnza hazr olduu hakknda bir fikriniz
olmas asndan, bu yeleri listeleme zahmetine deer. System.Net tarafndan tanmlanan
snflar aada gsterilmitir:
AuthenticationManager Authorization
Cookie CookieCollection
CookieContainer CookieException
CredentialCache Dns
DnsPermission DnsPermissionAttribute
EndPoint EndpointPermission
FileWebRequest FileWebResponse
GlobalProxySelection HttpVersion
HttpWebRequest HttpWebResponse
IPAddress IPEndPoint
IPHostEntry NetworkCredential
ProtocolViolationException ServicePoint
ServicePointManager SocketAddress
SocketPermission SocketPermissionAttribute
WebClient WebException
WebHeaderCollection WebPermission
WebPermissionAttribute WebProxy
WebRequest WebResponse
System.Nette aadaki arayzler tanmldr:

HERKES N C#
KISIM II C# KTPHANESN KEFETMEK

690
IAuthenticationModule ICertificatePolicy
ICredentials IWebProxy
IWebRequestCreate
System.Net drt adet numaralandrma tanmlar:
HttpStatusCode NetworkAccess
TransportType WebExceptionStatus
Son olarak, System.Nette bir tek delege tanmlanmtr: HttpContinueDelegate.
System.Nette birok ye tanmlanm olmasna ramen, Internet programlama
grevlerinin birounu gerekletirmek iin bunlardan yalnzca birka gereklidir. A
oluturmann ekirdeinde WebRequest ve WebResponse isimli zet snflar yer almaktadr.
Bu snflar, belirli bir a protokoln destekleyen snflardan kaltmla tretilmilerdir.
(Protokol, bir a zerinden bilgi gndermek iin kullanlan kurallar tanmlar.) rnein,
standart HTTP protokoln destekleyen tretilmi snflar HttpWebRequest ve
HttpWebResponstur.
WebRequest ve WebResponse baz grevler iin kolaylkla kullanlabilir olsalar bile siz
WebClienta dayanan ok daha basit bir yntem de kullanabilirsiniz. Sz gelii, yalnzca bir
dosyay gndermeniz ya da indirmeniz gerekiyorsa, bunu gerekletirmenin en iyi yolu
genellikle WebClient kullanmaktr.
Uniform Resource Identifierlar
Internet programlamann temelinde Uniform Resource Identifier (URI - Dzgn Kaynak
Tanmlaycs) yer alr. URI, a zerindeki bir kaynan konumunu tarif eder. URI genellikle
URL olarak da adlandrlr. URL, Uniform Resource Locator (Dzgn Kaynak
Konumlandrcs) ifadesinin ksaltlm eklidir. Microsoft, System.Netin yelerini tarif
ederken URI terimini kulland iin, bu kitapta da ayn ekilde ele alnacaktr, URIlar
kukusuz biliyorsunuzdur, nk ne zaman Internet taraycnza bir adres girerseniz aslnda bir
URI kullanrsnz.
Bir URI genel olarak u ekildedir:
Protocol://ServerID/FilePath?Query
Protocol, kullanlmakta olan protokol belirtir; rnein, bu HTTP olabilir. ServerID,
belirli bir sunucuyu - sz gelii Osborne.com ya da Weather.com - belirler. FilePath, belirli
bir dosya iin dosya yolunu belirtir. FilePath belirtilmezse, belirtilen ServerID zerindeki
varsaylan sayfa elde edilir. Son olarak; Query, sunucuya gnderilecek bilgiyi belirtir. Query
istee baldr.
C#ta URIlar Uri snf iine paketlenmitir. Bu snf, blm iinde daha sonra
incelenecektir.
BLM 23: INTERNET LE A UYGULAMALARI

HERKES N C#
691
Internet Eriim Esaslar
System.Net iinde yer alan snflar, Internet etkileiminin istek/yant modelini
desteklerler. Bu yaklamda; programnz, yani istemci, sunucudan bilgi talep eder, sonra
sunucunun yantn bekler. Sz gelii, programnz bir Web sitesinin URIn sunucuya
gnderebilir. Sizin alacanz yant sz konusu URI ile ilikili hypertexttir. Bu istek/yant
yaklamnn kullanm hem rahat hem de basittir, nk ayrntlarn ou sizin iin ele
alnmtr.
En stnde WebRequest ve WebResponseun yer ald snf hiyerarisi, Microsoftun
taklabilir (pluggable) protokoller olarak adlandrd protokolleri uygular. Okuyucularn
birounun bildii gibi, birka farkl tipte a iletiim protokol mevcuttur. Internet
kullanmnda en yaygn olan HTTPdir (HyperText Transfer Protocol). Bir dieri ise FTPdir
(File Transfer Protocol). Bir URI kurulduu zaman URIn neki ilgili protokol belirtir.
rnein, HTTP://MyWebSite.com, HTTP nekini kullanr. Bu, HyperText Transfer
Protocoln belirtir.
nceden de bahsedildii gibi, WebRequest ve WebResponse, tm protokollerde ortak
olan genel istek/yant ilemlerini tanmlayan zel snflardr. Bu snflardan, spesifik
protokolleri uygulayan somut snflar tretilir. Tretilmi snflar, static metot
RegisterPrefix()i kullanarak kendilerini kaydederler. RegisterPrefix(),
WebRequest tarafndan tanmlanmtr. Bir WebRequest nesnesi oluturduunuz zaman
URIn nekinde belirtilen protokol, eer mevcutsa, otomatik olarak kullanlacaktr, Bu
taklabilir yaklamn salad avantaj udur: Ne tr bir protokol kullanyor olursanz olun,
kodunuzun byk blm deimeden ayn kalr.
.NET alma srasnda HTTP protokoln otomatik olarak tanmlar. Bylece, HTTP
nekini kullanan bir URL belirtirseniz otomatik olarak bunu destekleyen HTTP uyumlu bir
snf elde edersiniz. HTTP'yi destekleyen snflar HttpWebRequest ve
HttpWebResponsedur. Bu snflar WebRequest ve WebResponsedan kaltmla
tretilmitir; ayrca HTTP protokolne uygulanan birka metot daha eklerler.
System.Net, hem senkronize hem de asenkron iletiimi destekler. Internet
uygulamalarnn birounda senkronize ilemler en iyi seenektir, nk bunlarn kullanmlar
kolaydr. Senkronize iletiimde programnz bir istekte bulunur, sonra bir yant alnana kadar
bekler. Yksek performansl baz uygulama tipleri iin asenkron iletiim daha iyidir.
Programnz asenkron yaklam kullanarak bir yandan bilgilerin iletilmesini beklerken dier
yandan ilemlerine devam edebilir. Ancak, asenkron iletiimin uygulanmas daha zordur.
stelik, asenkron yaklamdan tm programlar yararlanamaz. rnein, Internetten bilgi
almaya gerek olduunda, genellikle bilgi alnana kadar yaplacak bir ey yoktur. Bu tr
durumlarda asenkron yaklamdan elde edilecek potansiyel kazanlar ayrmsanmaz. Senkronize
Internet eriimi hem kullanm kolay olduu iin, hem de evrensel olarak daha ok kabul
grdnden dolay bu blmde incelenen tek eriim tipidir.

HERKES N C#
KISIM II C# KTPHANESN KEFETMEK

692
WebRequest ve WebResponse, System.Netin kalbinde yer ald iin bir sonraki
admda bunlar ele alnacaktr.
WebRequest
WebRequest snf, a isteklerini ynetir. Bu zel bir snftr, nk belirli bir protokol
uygulamaz. Ancak, tm isteklerde ortak olan metotlar ve zellikleri uygular. Senkronize
iletiimi destekleyen ve WebRequest tarafndan tanmlanan metotlar Tablo 23.1de
gsterilmitir, WebRequest tarafndan tanmlanan zellikler ise Tablo 23.2de gsterilmitir.
zelliklerin varsaylan deerleri tretilmi snflarla belirlenir. WebRequest ak yaplandrc
tanmlamaz.
TABLO 23.1: WebRequest Tarafndan Tanmlanan ve Senkronize letiimi Destekleyen Metotlar


Metot Aklama
public static WebRequest
Create(string uri);
uri tarafndan aktarlan karakter katar ile belirtilen
URI iin bir WebRequest nesnesi oluturur.
Dndrlen nesne, URIin neki ile belirtilen
protokol uygulayacaktr. Bylece nesne,
WebRequestten kaltmla tretilen bir snfa ait
olacaktr. stenilen protokol mevcut deilse bir
NotSupportedException frlatlr. URI biimi
geerli deilse, bir UriFormatException frlatlr.
public static WebRequest
Create(Uri uri);
uri tarafndan aktarlan karakter katar ile belirtilen
URI iin bir WebRequest nesnesi oluturur.
Dndrlen nesne, URIin neki ile belirtilen
protokol uygulayacaktr. Bylece nesne,
WebRequestten kaltmla tretilen bir snfa ait
olacaktr. stenilen protokol mevcut deilse bir
NotSupportedException frlatlr.
public virtual stream
GetRequestStream()
nceden istenilen URI ile ilikili bir kt ak
dndrr.
public virtual WebResponse
GetResponse()
nceden oluturulan istei gnderir ve yant bekler. Bir
yant alndnda, bu yant bir WebResponse nesnesi
olarak dndrlr. Programnz belirtilen URIdan
bilgi edinmek iin bu nesneyi kullanacaktr. Yant elde
ederken bir hata meydana gelirse bir WebException
frlatlr.
TABLO 23.2: WebRequest Tarafndan Tanmlanan zellikler


zellik Aklama
public virtual string
ConnectionGroupName { get; set; }
Balant grup adn elde eder ya da ayarlar. Balant
gruplar, bir dizi istek oluturmann yoludur. Basit
Internet iletiimleri iin gerekli deildirler.
BLM 23: INTERNET LE A UYGULAMALARI

HERKES N C#
693
public virtual long ContentLength {
get; set; }
eriin uzunluunu elde eder ya da ayarlar.
public virtual string ContentType {
get; set; }
eriin uzunluunu elde eder ya da ayarlar.
public virtual ICredentials
Credentials { get; set; }
Gven belgesini elde eder ya da ayarlar. Gven
belgeleri, kullanc kimlik denetimi gerektiren
siteler iin gereklidir.
public virtual WebHeaderCollection
Headers { get; set; }
Balklar elde eder ya da ayarlar.
public virtual string Method { get;
set; }
Protokol elde eder ya da ayarlar.
public virtual bool PreAuthenticate
{ get; set; }
true ise, istek gnderildiinde kimlik denetimi
bilgisi de gnderilir. false ise, kimlik denetimi
bilgisi sadece URI tarafndan istendiinde salanr.
public virtual IWebProxy Proxy {
get; set; }
Proxy sunucu elde eder ya da ayarlar. Bu sadece,
bir proxy sunucu kullanlan ortamlarda geerlidir.
public virtual Uri RequestUri
{ get; }
stein URIn elde eder.
public virtual int Timeout { get;
set; }
stein yant vermek iin bekleyecei sreyi
milisaniye olarak elde eder ya da ayarlar. Sonsuza
kadar beklemek iin Timeout.Infinite
kullann.
Bir URIa bir istek gndermek iin ncelikle istenilen protokol uygulayan ve
WebRequestten tretilen bir snfa ait bir nesne oluturmalsnz. Bu, Create() arlarak
gerekletirilir. Create(), WebRequest tarafndan tanmlanan static bir metottur.
Create(), WebRequestten kaltm yoluyla tretilen ve belirli bir protokol uygulayan bir
snfa ait bir nesne dndrr.
TABLO 23.3: WebResponse Tarafndan Tanmlanan Metotlar


Metot Aklama
public virtual void Close() Yant kapatr. Ayrca, GetResponseStream()
tarafndan dndrlen yant akn da kapatr.
public virtual stream GetResponse
Stream()
stenilen URIa bal bir girdi ak dndrr. Bu
ak kullanlarak URIdan veri okunabilir.
WebResponse
WebResponse, bir istein sonucu olarak elde edilen yant snf iine paketler.
WebResponse zet bir snftr. WebResponsetan kaltmla tretilen snflar,
WebResponseun bir protokol destekleyen spesifik, somut versiyonlarn olutururlar. Bir

HERKES N C#
KISIM II C# KTPHANESN KEFETMEK

694
WebResponse nesnesi normal olarak WebRequest tarafndan tanmlanan GetResponse()
metodu arlarak elde edilir. Bu nesne, spesifik bir protokol uygulayan WebResponsetan
tretilen somut bir snfn bir rnei olacaktr: WebResponse tarafndan tanmlanan metotlar
yukarda Tablo 23.3te gsterilmitir. WebResponse tarafndan tanmlanan zellikler ise Tablo
23.4te gsterilmitir. Bu zelliklerin deerleri, her yanta ayr ayr bal olarak ayarlanr.
WebResponse ak yaplandrc tanmlamaz.
TABLO 23.4: WebResponse Tarafndan Tanmlanan zellikler


zellik Aklama
public virtual long ContentLength
{ get; set; }
Alnmakta olan ieriin uzunluunu elde eder ya da
ayarlar. erik uzunluu mevcut deilse bunun
deeri -1 olacaktr.
public virtual string ContentType
{ get; set; }
eriin tamamn elde eder.
public virtual WebHeaderCollection
Headers { get; }
Sz konusu URI ile ilintili bir balk koleksiyonu
elde eder.
public virtual Uri ResponseUri
{ get; }
Yant reten URI ilde eder. Eer yant bir baka
URIa ynlendirilmise elde edilen, istenilenden
farkl olabilir.
HttpWebRequest ve HttpWebResponse
HttpWebRequest ve HttpWebResponse snflar WebRequest ve WebResponse
snflarndan kaltm yoluyla tretilirler ve HTTP protokoln uygularlar. Bu sre iinde her
iki snf, bir HTTP ilemi hakknda ayrntl bilgi veren birka zellik de ekler. Bu zelliklerin
bir ksm bu bolmn ileriki sayfalarnda kullanlmtr. Ancak, basit Internet ilemleri iin bu
ek becerileri genellikle kullanmanz gerekmeyecektir.
lk Basit rnek
Internet eriimi WebRequest ve WebResponse etrafnda odaklanr. Bu sreci ayrntl
olarak incelemeden nce istek/yant yaklam ile Internet eriimini gsteren bir rnek grmek
yararl olacaktr. Bu snflar alrken grdkten sonra, bunlarn neden bu ekilde organize
edildiklerini anlamak daha da kolaylar.
Aadaki program, basil ama ayn zamanda ok da yaygn bir Internet ilemini
gerekletirmektedir. Program, belirli bir URIda mevcut olan hypertexti alr. Bu rnekte
McGraw-Hilln (elinizdeki kitabn orijinalinin yayncs) Osborne blmnn web sitesi olan
Osborne.comun ierii alnmaktadr; fakat siz, bunun yerine - herkes tarafndan eriilebilir
olmas kaydyla - bir baka web sitesini yerletirebilirsiniz. Program, hypertexti ekranda 400
karakterlik paralar halinde grntler; bylece, Internet zerinden nelerin indirildiini ekran
kaymadan nce grebilirsiniz.
BLM 23: INTERNET LE A UYGULAMALARI

HERKES N C#
695
// Internete erisir.

using System;
using System.Net;
using System.IO;

class NetDemo {
public static void Main() {
int ch;

// Once, bir URIa bir WebRequest olusturun.
HttpWebRequest req = (HttpWebRequest)
WebRequest.Create(http://www.osborne.com);

// Sonra bu istegi gonderin ve yaniti bekleyin.
HttpWebResponse resp = (HttpWebResponse)
req.GetResponse();

// Gelen yanittan bir girdi akisi elde edin.
Stream istrm = resp.GetResponseStream();

/* Simdi, belirtilen URIda mevcut olan htmli okuyun ve
goruntuleyin. Boylece, ekranda neyin gosterilmekte
oldugunu anlayabilirsiniz; veri, bir kerede 400 karakter
seklinde gosterilir. Her 400 karakter gosterildikten
sonra bir sonraki 400 karakteri almak icin ENTERa
basmalisiniz. */

for(int i = 1; ; i++) {
ch = istrm.ReadByte();
if(ch == -1) break;
Console.Write((char) ch);
if((i % 400) == 0) {
Console.Write(\nPress a key.);
Console.Read();
}
}

// Yaniti kapatin. Bu ayni zamanda istrmi de kapatir.
resp.Close();
}
}
ktnn ilk ksm aada gsterilmitir. (Tam ierik kukusuz zaman iinde deiebilir.)
<!DOCTYPE HTML PUBLIC -//W3C//DTD HTML 4.0 Transitional//EN>
<HTML>
<HEAD>
<TITLE>Find all the right computer books and learning tools at
Osborne McGraw-
Hill</TITLE>
<META NAME=Title CONTENT=Find all the right computer books and
learning tools at Osborne McGraw-Hill>
<META NAME=Keywords CONTENT=osborne, mcgraw-hill, mcgraw hill,
it books, computer books, database books, programming

HERKES N C#
KISIM II C# KTPHANESN KEFETMEK

696
Press a key.
books, networking books, certification books, computing books,
computer application books, hardware books, information
technology books, operating systems, web development, oracle
press, communications, complete refarence, how to do everything,
yellow pages, book publisher, certification study guide,
reference book, security, network security, ebusiness,
e-business, a+, network+, i-net+, cisco ce
Press a key.
.
.
.
Bu, hypertextin Osborne.com web sitesi ile ilintili parasdr. Program, ierii karakter
karakter grntledigi iin, tarayc ktsndaki gibi biimlendirilmemitir. Ham haliyle
grntlenmitir.
Gelin imdi bu program satr satr inceleyelim. ncelikle, System.Net isim uzaynn
kullanldna dikkat edin. nceden akland gibi, a oluturma snrlarn ieren isim uzay
budur. Ayrca, System.IOnun da dahil edildiine dikkat edin. Web sitesinden alnan bilgiler
bir Stream nesnesi kullanlarak okunduu iin bu isim uzayn kullanmak gereklidir.
Program, istenilen URI ieren bir WebRequest nesnesi oluturarak balar. Bu amala bir
yaplandrc yerine Create() metodunun kullanldna dikkat edin. Create(),
WebRequestin static yesidir. WebRequest aslnda zel snf olsa bile bu snfn static
bir metodunu armak her eye ramen mmkndr. Sz konusu URIn protokol nekine
bal olarak Create(), kendisine taklm doru protokole sahip bir WebRequest nesnesi
dndrr. Bu rnekte sz konusu protokol HTTPdir. Bylece, Create() bir
HttpWebRequest() nesnesi dndrr. Kukusuz, Create()in dndrd deer, req
adnda HttpWebRequest referansna atanrken her eye ramen tip atamas yoluyla
HttpWebRequeste dntrlmelidir. Bu aamada, sz konusu istek oluturulmutur, fakat
belirtilen URIa henz gnderilmemitir.
stei gndermek iin program, WebRequest nesnesi zerinde GetResponse()u arr.
stek gnderildikten sonra GetResponse() bir yant bekler. Bir kez yant alndktan sonra
GetResponse(), yant iine saran bir WebResponse nesnesi dndrr. Bu nesne respe
atanr. Bu rnekte yant, HTTP protokoln kulland iin sonu HttpWebResponsea
dntrlr. Dier zelliklerinin yan sra yant, URIdan veri okumak iin kullanlabilecek
bir ak ierir.
Sonra, resp zerinde GetResponseStream() arlarak bir girdi ak elde edilir. Bu,
dier herhangi bir girdi aknn tm nitelik ve zelliklerine sahip standart bir Stream
nesnesidir. Ak gsteren bir referans istrme atanr. istrm kullanlarak, belirtilen URIdaki
veriler, tpk bir dosyadan okunur gibi okunabilir.
Daha sonra program, Osborne.comdan verileri okur ve bunlar ekranda gsterir. ok fazla
miktarda bilgi mevcut olduu iin, ekran her 400 karakterde bir durur ve sizin ENTER tuuna
BLM 23: INTERNET LE A UYGULAMALARI

HERKES N C#
697
basmanz bekler. Bu ekilde, bilgilerin ilk bolm ekrandan kayp gitmeyecektir. Karakterlerin
ReadByte() kullanlarak okunduuna dikkat edin. Hatrlarsanz, bu metot, girdi akndaki bir
sonraki karakteri bir int olarak dndrr; bu int deer tip atamas yoluyla chara
dntrlmelidir. Akn sonuna ulaldnda metot, -1 dndrr.
Son olarak; yant, resp zerinde Close() arlarak kapatlr. Yant akn kapatmak
otomatik olarak girdi akn da kapatr. Her istekten sonra yant kapatmak nemlidir. Eer
kapatmazsanz, a kaynaklarn tketmek ve bir sonraki balanty nlemek mmkndr.
Bu rnei terk etmeden nce vurgulanmas gereken bir nemli husus daha vardr:
Osborne.com web sitesinden okunan hypertexti grntlemek iin bir HttpWebRequest ya
da HttpWebResponse nesnesi kullanmak aslnda gerekli deildi. nceki program HTTPye
zg zellikleri kullanmad iin WebRequest ve WebResponse tarafndan tanmlanan
standart metotlar bu ilemi ele almak iin yeterliydi. Bylece, Create()e ve
GetResponse()a yaplan arlar u ekilde de yazlabilirdi:
// Once, bir URIa bir WebRequest oluturun.
WebRequest req = WebRequest.Create(http://www.osborne.com);

// Sonra bu istegi gonderin ve yaniti bekleyin.
WebResponse resp = req.GetResponse();
Microsoft, belirli tipte bir protokol uygulamas iin tip atamas kullanmanza gerek
olmayan durumlarda WebRequest ve WebResponse kullanmann daha iyi olacan neriyor.
nk bu sayede kodunuzu etkilemeden protokolleri deitirmeniz mmkndr. Ancak, bu
blmdeki rneklerin tm HTTP ve ok az HTTPye zg zellikleri kullanyor olaca iin,
programlar HttpWebRequest ve HttpWebResponse kullanacaklardr.
A Hatalarn Kontrol Altna Almak
nceki blmdeki program doru olmasna ramen esnek deildir. En basit a hatas bile
programn aniden sona ermesine neden olacaktr. Bu blmde gsterilen rneklerde byle bir
problem sz konusu olmamasna ramen bu, gerek dnyaya ait uygulamalarda nlemeniz
gereken bir durumdur. Programn retebilecei ala ilgili tm kural d durumlar tam olarak
kontrol altna almak iin Create()e, GetResponse()a ve GetResponseStream()e
yaplan arlar izlemelisiniz. Her tipten olas hata bir sonraki blmde anlatlmaktadr.
Create() Tarafndan retilen Kural D Durumlar
WebRequest tarafndan tanmlanan Create() metodu kural d durum retebilir. URI
neki ile belirtilen protokol eer desteklenmiyorsa NotSupportedException frlatlr. Eer
URI biimi geerli deilse, UriFormatException frlatlr. Create() ayrca, eer null
referans ile arlmsa, bir ArgumentNullException da frlatabilir, ancak bu, aa balanma
ile ilintili olarak retilen bir hata deildir.

HERKES N C#
KISIM II C# KTPHANESN KEFETMEK

698
GetReponse() Tarafndan retilen Kural D
Durumlar
GetResponse() arlarak bir yant elde edilirken eer bir hata ortaya karsa bir
WebException frlatlr. Tm kural d durumlar iin tanmlanan yelere ek olarak
WebException, a hatalaryla balantl iki zellik daha ekler: Response ve Status.
Response zellii aracl ile bir kural d durum yneticisi iinde WebResponse
nesnesine atfta bulunan bir referans elde edebilirsiniz. Bir kural d durum ortaya km
olsayd, GetResponse() tarafndan dndrlen nesne bu olurdu. Response u ekilde
tanmlanr:
public WebResponse Response { get; }
Bir hata ortaya ktnda problemin nereden kaynaklandn bulmak iin
WebExceptionn Status zelliini kullanabilirsiniz. Status u ekilde tanmlanr:
public WebExceptionStatus { get; }
WebExceptionStatus, aadaki deerleri ieren bir numaralandrmadr:
ConnectFailure ConnectionClosed
KeepAliveFailure NameResolutionFailure
Pending PipelineFailure
ProtocolError ProxyNameResolutionFailure
ReceiveFailure RequestCanceled
SecureChannelFailure SendFailure
ServerProtocolViolation Success
Timeout TrustFailure
Hatann nedeni belirlenir belirlenmez, artk programnz uygun bir eylemde bulunabilir.
GetResponseStream() Tarafndan retilen Kural D
Durumlar
GetResponseun GetResponseStream() metodu bir ProtocolViolationException
frlatabilir. ProtocolViolationException, genel olarak, belirtilen protokole bal olarak
bir hatann meydana geldii anlamna gelir. ProtocolViolationException,
GetResponseStream() ile balantl olduu iin mevcut yant aklarndan hi birinin
geerli olmad anlamn tar. Ayrca, akn okunmas srasnda bir IOException da
meydana gelebilir.
Kural D Durum Ynetimini Kullanmak
Aadaki program, daha nce gsterilen rnee, a ile ilgili olas tm kural d durumlar
iin kural d durum yneticileri ekler:
BLM 23: INTERNET LE A UYGULAMALARI

HERKES N C#
699
// Ag ile ilgili kural disi durumlar kontrol altina almak.

using System;
using System.Net;
using System.IO;

class NetExcDemo {
public static void Main() {
int ch;

try {
// Once, bir URIa bir WebRequest olusturun.
HttpWebRequest req = (HttpWebRequest)
WebRequest.Create(http://www.osborne.com);

// Sonra bu istegi gonderin ve yaniti bekleyin.
HttpWebResponse resp = (HttpWebResponse)
req.GetResponse();

// Yanittan bir girdi akisi elde edin.
Stream istrm = resp.GetResponseStream();

/* Simdi, belirtilen URIda mevcut olan htmli okuyun ve
gorntleyin. Boylece, ekranda neyin gosterilmekte
oldugunu anlayabilirsiniz; veri, bir kerede 400
karakter seklinde gosterilir. Her 400 karakter
gosterildikten sonra bir sonraki 400 karakteri almak
icin ENTERa basmalisiniz. */

for(int i = 1; ; i++) {
ch = istrm.ReadByte();
if(ch == -1) break;
Console.Write((char) ch);
if((i % 400) == 0) {
Console.Wrte(\nPress a key.);
Console.Read();
}
}

// Yaniti kapatin. Bu ayni zamanda istrmi de kapatir.
resp.Close();

} catch(WebException exc) {
Console.WriteLine(Network Error: + exc.Message +
\nStatus code: + exc.Status);
} catch(ProtocolViolationException exc) {
Console.WriteLine(Protocol Error: + exc.Message);
} catch(UriFormatException exc) {
Console.WriteLine(URI Format Error: + exc.Message);
} catch(NotSupportedException exc) {
Console.WriteLine(Unknown Protocol: + exc.Message);
} catch(IOException exc) {
Console.WriteLine(I/O Error: + exc.Message);
}
}

HERKES N C#
KISIM II C# KTPHANESN KEFETMEK

700
}
A ile ilgili metotlarn retebilecei kural d durumlar artk yakalanmtr. rnein,
Create()e yaplan ary aadaki gibi deitirirseniz,
WebRequest.Create(http://www.osborne.com/moonrocket);
sonra program yeniden derleyip, altrrsanz u kty greceksiniz:
Network Error: The remote server returned an error: (404) Not Found.
Status code: ProtocolError
Osborne.com web sitesinde moonrocket isimli bir dizin mevcut olmad iin byle bir
URI bulunamaz. kt da bunu dorulamaktadr.
rnekleri ksa ve sade tutmak amacyla bu blmdeki programlarn birou eksiksiz bir
kural d ynetim mekanizmas iermeyecektir. Ancak, sizin gerek dnyaya ynelik
uygulamalarnz mutlaka iermelidir.
URI Snf
Tablo 23.1de WebRequest.Create()in iki farkl versiyonu olduu dikkatinizi
ekecektir. Bunlardan biri, sz konusu URI bir karakter katar eklinde kabul eder. nceki
programlarda bu versiyon kullanlmtr. Dieri ise, URI Uri snfnn bir rnei olarak alr.
Uri snf bir URI paketler. Uri kullanarak, Create()e aktarlabilen bir URI kurabilirsiniz.
Ayrca, bir Uri dikkatle inceleyip, paralarn elde edebilirsiniz. Birok basit Internet
ilemleri iin Uri kullanmanz gerekmese de, daha sofistike durumlarda Uri kullanmnn ok
deerli olduunu fark edebilirsiniz.
Urida birka yaplandrc tanmldr. Bunlardan yaygn olarak kullanlan ikisi aada
gsterilmitir:
public Uri(string uri)
public Uri(string baz, string rel)
lk ifade, bir karakter katar eklinde verilen URIdan bir Uri kurar. kinci ifade, rel ile
belirtilen bir bal URI, baz ile belirtilen mutlak baz konumundaki URIa ekleyerek bir Uri
yaplandrr. Mutlak URI, komple bir URI tanmlar. Bal URI ise yalnzca eriim yolunu
tanmlar.
Uri, URIlar ynetmenize yardmc olan ya da bir URIn eitli paralarna erimenize
imkan veren birok alan, zellik ve metot tanmlar. Kayda deer lde ilgi ekici zellikler
aada gsterilmitir:


zellik Aklama
public string Host { get; } Sunucunun adn elde eder.
public string LocalPath { get; } Dosya yolunu elde eder.
BLM 23: INTERNET LE A UYGULAMALARI

HERKES N C#
701
public string PathAndQuery { get; } Dosya yolunu ve sorgu karakter katarn
elde eder.
public int Port { get; } Belirtilen protokol iin port (kap)
numarasn elde eder. http iin port 80dir.
public string Query { get; } Sorgu karakter katarn elde eder.
public string Scheme { get; } Protokol elde eder.
Bu zellikler bir URI kendisini oluturan paralara ayrmak iin kullanldr. Aadaki
program bunlarn kullanmn gstermektedir:
// Uri kullanimini gosterir.

using System;
using System.Net;

class UriDemo {
public static void Main() {
Uri sample =
new Uri(http://MySite.com/somefile.txt?SomeOuery);
Console.WriteLine(Host: + sample.Host);

Console.WriteLine(Port: + sample.Port);
Console.WriteLine(Scheme: + sample.Scheme);
Console.WriteLine(Local Path: + sample.LocalPath);
Console.WriteLine(Query: + sample.Query);
Console.WriteLine(Path and query: + sample.PathAndQuery);
}
}
kt aada gsterilmitir:
Host: mysite.com
Port: 80
Scheme: http
Local Path: /somefile.txt
Query: ?SomeQuery
Path and query: /somefile.txt?SomeQuery

Ek HTTP Yant Bilgilerine Eriim
HttpResponseu kullanrken belirtilen kaynan ierii haricindeki dier bilgilere de
eriim iznine sahip olursunuz. URIn en son gncellenme zaman, sunucunun ad bu tr
bilgiler kapsamnda yer alr. Bu bilgiler yant ile ilintili eitli zellikler araclyla
kullanlabilirler. Bu zellikler, ki WebResponse tarafndan tanmlanan drd de buna dahildir,
Tablo 23.5te gsterilmilerdir. Aadaki blmlerde tipik rneklerin nasl kullanlaca
aklanmaktadr.

HERKES N C#
KISIM II C# KTPHANESN KEFETMEK

702
TABLO 23.5: HttpWebResponse Tarafndan Tanmlanan zellikler


zellik Aklama
public string CharacterSet { get; } Kullanlmakta olan karakter setinin adn elde
eder.
public string ContentEncoding { get; } Kodlama ynteminin adn elde eder.
public long ContentLength { get; } Alnmakta olan ieriin uzunluunu elde
eder. erik uzunluu mevcut deilse bu
deer -1dir.
public string ContentType { get; } eriin tamamn elde eder.
public CookieCollection Cookies
{ get; set; }
Yanta ilitirilmi erezlerin listesini elde
eder.
public WebHeaderCollection Headers
{ get; }
Yanta ilitirilmi balklarn koleksiyonunu
elde eder.
public DateTime LastModified { get; } URIn en son deitirildii saati elde eder.
public string Method { get; } Yant metodunu belirten bir karakter katar
elde eder.
public version ProtocolVersion { get; } lemde kullanlan HTTPnin versiyonunu
tarif eden bir Version nesnesi elde eder.
public Uri ResponseUri { get; } Yant reten URI elde eder. Eer yant bir
baka URIa ynlendirilmise elde edilen,
istenilenden farkl olabilir.
public string Server { get; } Sunucunun ismini simgeleyen bir karakter
katar elde eder.
public HttpStatusCode StatusCode
{ get; }
lemin durumunu tarif eden bir
HttpStatusCode nesnesi elde eder.
public string StatusDescription { get; } lemin durumunu okunabilir ekilde
simgeleyen bir karakter katar elde eder.
Bala Eriim
HttpWebResponse tarafndan tanmlanan Headers zellii araclyla bir HTTP yant
ile ilintili balk bilgilerine eriebilirsiniz. Headers aada gsterilmitir:
public WebHeaderCollection Headers{ get; }
Bir HTTP bal, karakter katar olarak simgelenen isim ve deer iftlerinden oluur. Her
isim/deer ifti bir WebHeaderCollection iinde saklanr. Bu zelletirilmi koleksiyon
anahtar/deer iftlerini saklar ve dier herhangi bir koleksiyon gibi kullanlabilir. (Blm 22ye
bakn.) simlerden oluan bir string dizisi AllKeys zellii ile elde edilebilir. Bir isim ile
ilikili deeri indeksleyiciyi kullanarak elde edebilirsiniz. ndeksleyici, ya bir nmerik indeks
ya da sz konusu ismi kabul edecek ekilde ar yklenmitir.
BLM 23: INTERNET LE A UYGULAMALARI

HERKES N C#
703
Aadaki program, Osborne.com ile ilintili tm balklar grntler:
// Basliklari inceler.

using System;
using System.Net;

class HeaderDemo {
public static void Main() {

// Bir URIa bir WebRequest olustur.
HttpWebRequest req = (HttpWebRequest)
WebRequest.Create(http://www.osborne.com);

// Bu istegi gonder ve yaniti dondur.
HttpWebResponse resp = (HttpWebResponse)
req.GetResponse();

// Isimlerin listesini al.
string[] names = resp.Headers.AllKeys;

// Baslikta yer alan isim/deger ciftlerini goster.
Console.WriteLine({0,-20}{1}\n, Name, Value);
foreach(string n in names)
Console.WriteLine({0,-20}{1}, n, resp.Headers[n]);

// Yaniti kapat.
resp.Close();
}
}
retilen kt aadadr. (Osborne.comdaki balk bilgilerinin deitirilebileceini
hatrnzdan karmayn. Bu nedenle, ktda biraz farkl bir ey grebilirsiniz.)
Name Value
Date Mon, 14 Jan 2002 17:45:50 GMT
Server Apache/1.3.9 (Unix) PHP/3.0.14
Keep-Alive timeout=30, max=500
Connection Keep-Alive
Transfer-Encoding chunked
Content-Type text/html
erezlere Eriim
HttpWebResponse tarafndan tanmlanan Cookies zellii araclyla bir HTTP yant
ile ilintili erezlere eriim elde edebilirsiniz. erezler, bir tarayc tarafndan saklanan bilgileri
ierir. erezler, isim/deer iftlerinden oluur ve belirli tipte Web eriimini kolaylatrrlar.
Cookies u ekilde tanmlanr:
public CookieCollection Cookies { get; set; }

HERKES N C#
KISIM II C# KTPHANESN KEFETMEK

704
CookieCollection, ICollection ve IEnumerable arayzlerini uygular ve dier
herhangi bir koleksiyon gibi kullanlabilir. (Blm 22ye bakn.) Ayrca, erezin indeksini ya
da ismini belirterek erezi elde etmeye olanak tanyan bir indeksleyici de ierir.
CookieCollection, Cookie tipinde nesneler saklar. Cookie, bir erez ile ilikili
bilginin eitli paralarna erimenize imkan veren birka zellik tanmlar. Bunlardan burada
kullanacamz ikisi Name ve Valuedur; u ekilde tanmlanrlar:
public string Name { get; set; }
public string Value { get; set; }
erezin ismi Name iinde yer alr ve deeri de Value iindedir.
Bir yant ile ilintili erezlerin listesini elde etmek iin sz konusu istek iinde bir erez
konteyneri salamalsnz. Bu amala, HttpWebRequest aada gsterilen
CookieContainer zelliini tanmlar:
public CookieContainer CookieContainer { get; set; }
CookieContainer, erezleri saklamanza imkan veren eitli alan, zellik ve metotlar
sunar. Ancak, birok uygulamada CookieContainer ile dorudan almanza gerek
olmayacaktr. Bunun yerine, yanttan elde ettiiniz CookieCollection kullanacaksnz.
CookieContainer yalnzca erezler iin altta yatan bir depolama mekanizmas salar.
Aadaki program, komut satrnda belirtilen URI ile ilikili erezlerin isimlerini ve
deerlerini grntler. Btn web sitelerinin erez kullanmadn hatrnzdan karmayn; bu
nedenle, erez kullanan bir site bulana kadar birkan denemek zorunda kalabilirsiniz.
/* Cerezleri inceler.

Bir Web sitesinin kullandgi cerezleri gormek icin
Web sitesinin ismini komut satirinda belirtin.
Ornegin, eger bu programa Cookie adini verirseniz,
Cookie http://MSN.COM
MSN.COM ile ilintili cerezi goruntuler.
*/

using System;
using System.Net;

class CookieDemo {
public static void Main(string[] args) {

if(args.Length != 1) {
Console.WriteLine(Usage: CookieDemo <uri>);
return;
}

// Belirtilen URIa bir WebRequest olustur.
HttpWebRequest req = (HttpWebRequest)
BLM 23: INTERNET LE A UYGULAMALARI

HERKES N C#
705
WebRequest.Create(args[0]);

// Bos bir cerez konteyneri al.
req.CookieContainer = new CookieContainer();

// Istegi gonder ve yaniti dondur.
HttpWebResponse resp = (HttpWebResponse)
req.GetResponse();

// Cerezleri goruntule.
Console.WriteLine(Number of cookies: +
resp.Cookies.Count);
Console.WriteLine({0,-20}{1}, Name, Value);

for(int i = 0; i < resp.Cookies.Count; i++)
Console.WriteLine({0, -20}{1},
resp.Cookies[i].Name,
resp.Cookies|i].Value);

// Yaniti kapat.
resp.Close();
}
}
LastModified zelliinin Kullanm
Kimi zaman bir URIn en son ne zaman gncellendigini bilmek isteyeceksiniz.
HttpWebResponse kullanlrken bunu kefetmek kolaydr, nk HttpWebResponse,
LastModified zelliini tanmlar. Bu zellik aada gsterilmitir:
public DateTime LastModified { get; }
LastModified, sz konusu URIn ieriinin deitirildii en son zaman elde eder.
Aadaki program, Microsoft.com web sitesinin en son gncellendigi saati ve tarihi
grntler:
// LastModifiedi kullanir.

using System;
using System.Net;

class HeaderDemo {
public static void Main() {










HERKES N C#
KISIM II C# KTPHANESN KEFETMEK

706

















































return uri;
}

public static void Main(string[] args) {
string link = null;
string str;
BLM 23: INTERNET LE A UYGULAMALARI

HERKES N C#
707
string answer;

int curloc; // yanit icinde mevcut konumu tutar

if(args.Length != 1) {
Console.WriteLine(Usage: MiniCrawler <uri>);
return;
}

string uristr = args[0]; // mevcut URIi tutar

try {

do {
Console.WriteLine(Linking to + uristr);

// Belirtilen URIa bir WebRequest olusturur.
HttpWebRequest req = (HttpWebRequest)
WebRequest.Create(uristr);

uristr = null; // bu URIin daha fazla kullanimina
// izin verme
// Bu istegi gonder ve yaniti dondur.
HttpWebResponse resp = (HttpWebResponse)
req.GetResponse();

// Yanittan bir girdi akisi elde et.
Stream istrm = resp.GetResponseStream();

// Girdi akisini bir StreamReader icine sar.
StreamReader rdr = new StreamReader(istrm);

// Butun sayfayi oku.
str = rdr.ReadToEnd();

curloc = 0;

do {
// Baglanilacak bir sonraki URIi bul.
link = FindLink(str, ref curloc);

if(link != null) {
Console.WriteLine(Link found: + link);

Console.Write(Link, More, Quit?);
answer = Console.ReadLine();

if(string.Compare(answer, L, true) == 0) {
uristr = string.Copy(link);
break;
}
else
if(string.Compare(answer, Q, true) == 0) {
break;
}

HERKES N C#
KISIM II C# KTPHANESN KEFETMEK

708
else
if(string.Compare(answer, M, true) == 0) {
Console.WriteLine(Searching for another
link.);
}
} else {
Console.WriteLine(No link found.);
break;
}

} while(link.Length 0);

// Yaniti kapat.
resp.Close();
} while(uristr != null);

} catch(WebException exc) {
Console.WriteLine(Network Error: + exc.Message +
\nStatus code: + exc.Status);
} catch(ProtocolViolationException exc) {
Console.WriteLine(Protocol Error: + exc.Message);
} catch(UriFormatException exc) {
Console.WriteLine(URI Format Error: + exc .Message);
} catch(NotSupportedException exc) {
Console.WriteLine(Unknown Protocol: + exc.Message);
} catch(IOException exc) {
Console.WfriteLine(I/O Error: + exc.Message);
}

Console.WriteLine(Terminating MiniCrawler.);
}
}
te oturumun bir paras:
C:MiniCrawler http://osborne.com
Linking to http://osborne.com
Link found: http://www.osborne.com/aboutus/aboutus.shtml
Link, More, Quit? M
Searching for another link.
Link found: http://www.osborne.com/downloads/downloads.shtml
Link, More, Quit? L
Linking to http://www.osborne.com/downloads/downloads.shtml
.
.
.
Gelin imdi, Mini Crawlerin nasl altna yakndan gz atalm. MiniCrawlerin
almaya balayaca URI, komut satrnda belirtilir. Bu URI Main()de uristr denilen bir
karakter katar iinde saklanr. Bu URIa bir istek oluturulur, sonra uristr, null olacak
ekilde ayarlanr. Bu. bu URIn daha nce kullanlm olduuna iaret eder. Daha sonra, istek
gnderilir ve buna karlk gelen yant elde edilir. GetResponseStream() tarafndan
dndrlen ak, bir StreamReader iine sarlarak ve sonra ReadToEnd() arlarak sz
BLM 23: INTERNET LE A UYGULAMALARI

HERKES N C#
709
konusu ierik okunur. ReadToEnd(), sz konusu akn btn ieriini bir karakter katar
olarak dndrr.
Program daha sonra bu ierii kullanarak bir balant arar. Bunu, ayrca MiniCrawler
tarafndan da tanmlanan static bir metot olan FindLink()i ararak gerekletirir.
FindLink(), ierii tutan karakter katar ve aramaya balanlacak olan balang konumu ile
birlikte arlr.
Bu deerleri alan parametreler srasyla htmlstr ve startloctur. startlocun bir
ref parametresi olduuna dikkat edin. FindLink() nce ierii tutan karakter katarnn
kk harflerden oluan bir kopyasn karr, sonra href=http - bu bir balantya iaret
eder - ile elenen bir alt karakter katar arar. Elenen bir deer bulunursa sz konusu URI,
uria kopyalanr ve startlocun deeri balantnn sonuna iaret edecek ekilde gncellenir.
startloc bir ref parametresi olduu iin bu ilem, startlocun Main()de karlk gelen
argmannn gncellenmeslne neden olur. Bylece, bir sonraki aramann bir ncekinin kald
yerden balamas mmkn klnr. Son olarak, uri dndrlr. uria balangta null deeri
atand iin, bir eleme olmamas durumunda, baarszlk anlamna gelen bir null referans
dndrlm olur.
Main()e geri dnersek, FindLink() tarafndan dndrlen balant null deilse bu
balant grntlenir ve kullancya ne yapaca sorulur. Kullanc L tuuna basarak bu
balantya gidebilir, M tuuna basarak mevcut ierik iinde bir baka balant arayabilir ya da Q
tuuna basarak programdan kabilir. Kullanc eer L tuuna basarsa, sz konusu balant takip
edilir ve balantnn ierii elde edilir. Sonra, yeni balant iinde bir balant aranr Bu ilem,
olas tm balantlar tkenene kadar srer.
MiniCrawlerin gcn artrmay ilgin bulabilirsiniz. Sz gelii, crawlern kullanc ile
etkileime girmeden, bulduu her balantya kendisinin gitmesini salayacak ekilde, program
tamamen otomatize etmeyi deneyin. Yani, bir balang sayfasndan balayarak bulduu ilk
balantya gitmesini salayn. Sonra, yeni sayfa iinde ilk balantya gitmesini salayn vs. Bir
kez bir kr noktaya ulaldnda artk bir seviye geri gelmesini (backtrack), bir sonraki balan-
ty bulmasn ve balamaya devam etmesini salayn. Bu plan baaryla gerekletirmek iin
URIlar ve bir URI iindeki aramann mevcut konumunu tutmak iin yn kullanmanz
gerekecektir. Bunu gerekletirmenin bir yolu bir Stack koleksiyonu kullanmaktr. Ekstra
zorluk katmak iin, balantlar bir aa eklinde gsteren bir kt oluturmay deneyin.
Web Client Kullanm
Bu blm noktalamadan nce WebClientn ksa bir zetini yapmaya deer. Bu
blmn balarnda bahsedildii gibi, uygulamanzn Internet zerinden yalnzca gnderme ya
da indirme yapmasna gerek varsa WebRequest ve WebResponse yerine WebClienti
kullanabilirsiniz. WebClientn avantaj, birok ayrnty sizin yerinize ele alyor olmasdr.
WebClientta, aada gsterilen, tek yaplandrc tanmldr:

HERKES N C#
KISIM II C# KTPHANESN KEFETMEK

710
public WebClient()
WebClient, Tablo 23.6da gsterilen zellikleri ve Tablo 23.7de gsterilen metotlar
tanmlar. Belirtilen URI geerli deilse metotlarn tm bir UriFormatException frlatrlar.
Transmisyon srasnda bir hata meydan gelir ise, bir WebException frlatlr.

TABLO 23.6: WebClient Tarafndan Tanmlanan zellikler


zellik Aklama
public string BaseAddress { get; set; } stenilen URIn baz adresini elde eder ya da
ayarlar. Bu zelliin varsaylan deeri
nulldr. Bu zellik eer ayarlanmsa
WebClient metotlar tarafndan belirtilen
metotlar, baz adresine bal olacaktr.
public ICredentials Credentials { get;
set; }
Kimlik denetimi (authentication) bilgilerini
elde eder ya da ayarlar. Bu zelliin
varsaylan deeri nulldr.
public WebHeaderCollection Headers
{ get; set; }
stek balklarnn koleksiyonunu elde eder
ya da ayarlar.
public NameValueCollection QueryString
{ get; set; }
Bir istee ilitirilebilir isim/deer
iftlerinden oluan bir sorgu karakter katar
elde eder ya da ayarlar. Sorgu karakter
katar, URIdan ? ile ayrlr. Eer birden
fazla isim/deer ifti mevcutsa her ift @ ile
birbirinden ayrlr.
public WebHeaderCollection
ResponseHeaders { get; }
Yant balklarnn koleksiyonunu elde eder.
TABLO 23.7: WebClient Tarafndan Tanmlanan Metotlar


Metot Aklama
public byte[] DownloadData(string uri) uri ile belirtilen URIdaki bilgileri indirir ve
sonucu bir byte dizisinde dndrr.
public void DownloadFile(string uri,
string fname)
uri ile belirtilen URIdaki bilgileri indirir ve
fname ile belirtilen dosyada saklar.
public Stream OpenRead(string uri) uri ile belirtilen URIdaki bilgilerin
okunabilecei bir girdi ak dndrr.
Okuma sona erdikten sonra bu ak
kapatlmaldr.
BLM 23: INTERNET LE A UYGULAMALARI

HERKES N C#
711
public Stream OpenWrite(string uri)
uri ile belirtilen URIdaki bilgilerin
yazlabilecei bir kt ak dndrr.
Yazma sona erdikten sonra bu ak
kapatlmaldr.
public Stream OpenWrite(string uri,
string how)
uri ile belirtilen URIdaki bilgilerin
yazlabilecei bir kt ak dndrr.
Yazma sona erdikten sonra bu ak
kapatlmaldr. how zerinden aktarlan
karakter katar, bilgilerin nasl yazlacan
belirtir.
public byte[] UploadData(string uri,
byte[] info)
info ile belirtilen bilgileri uri ile
belirtilen URIa yazar. Yant dndrlr.
public byte[] UploadData(string uri,
string how, byte[] info)
info ile belirtilen bilgileri uri ile
belirtilen URIa yazar. Yant dndrlr.
how zerinden aktarlan karakter katar,
bilgilerin nasl yazlacan belirtir.
public byte[] UploadFile(string uri,
string fname,)
fname ile belirtilen dosya iindeki bilgileri
uri ile belirtilen URIa yazar. Yant
dndrlr.
public byte[] UploadFile(string uri,
string how, string fname,)
fname ile belirtilen dosya iindeki bilgileri
uri ile belirtilen URIa yazar. Yant
dndrlr. how zerinden aktarlan
karakter katar, bilgilerin nasl yazlacan
belirtir.
public byte[] UploadValues(string uri,
NameValueCollection vals)
vals ile belirtilen koleksiyon iindeki
bilgileri uri ile belirtilen URIa yazar.
Yant dndrlr.
public byte[] UploadValues(string uri,
string how, NameValueCollection vals)
vals ile belirtilen koleksiyon iindeki
bilgileri uri ile belirtilen URIa yazar.
Yant dndrlr. how zerinden aktarlan
karakter katar, bilgilerin nasl yazlacan
belirtir.
Aadaki program, verileri Internetten bir dosyaya indirmek iin WebClientin nasl
kullanldn gstermektedir:
// Bilgileri bir dosyaya indirmek icin WebClient kullanir.

using System;
using System.Net;
using System.IO;

class WebClientDemo {
public static void Main() {
WebClient user = new WebClient();
string uri = http://www.osborne.com;
string fname = data.txt;

try {

HERKES N C#
KISIM II C# KTPHANESN KEFETMEK

712
Console.WriteLine(Downloading data from +
uri + to + fname);
user.DownloadFile(uri, fname);
} catch (WebException exc} {
Console.WriteLine(exc);
} catch (UriFormatException exc) {
Console.WriteLine(exc);
}

Console.WriteLine(Download complete.);
}
}
Bu program, Osborne.comdaki bilgileri indirir ve data.txt adnda bir dosyaya
yerletirir. Programda, zellikle, olas kural d durumlarn her ikisinin de kontrol altna
alnd dnlrse, ne kadar az kod satrnn kullanldna dikkat edin. Ayrca, uri tarafndan
belirtilen karakter katarn deitirerek herhangi bir URIdan bilgi indirebilirsiniz.
WebRequest ve WebResponse size daha fazla kontrol verir ve daha fazla bilgiye eriim
olana tanr. Ancak, buna ramen bir ok uygulamann gerektirdii WebClient olacaktr. Bir
uygulamann tm gereksinim duyduu Webden bilgi indirmek olduunda WebClient
zellikle kullanldr. Sz gelii, bir uygulamann belgelerle ilgili gncellemeleri elde etmesine
olanak tanmak iin WebClient kullanabilirsiniz.



N C K I S I M


C#I UYGULAMAYA
GERMEK


Ksm IIIte C#n uygulamasna yer verilmektedir.
Bunlardan ilki, bileenlerin oluturulmas ve ynetilmesidir. C#n
pek ok zellii dorudan bileenlerin oluturulmasna olanak
vermek amacyla tasarland iin bileenler, C# ile programlamann
nemli bir parasdr. kinci uygulamada, System.Windows.Forms
tarafndan tanmlanan snflar kullanlarak bir Windows program
oluturulmaktadr. Nihayet kitabn son uygulamas olarak, C#, bir
saf kod rneine uygulanmaktadr: Cebirsel deyimlerin
hesaplanmas iin yinelenerek inen bir ayrtrc hazrlanmaktadr.











III



Y R M D R D N C B L M


BLEENLERN
OLUTURULMASI





















24
BLM 24: BLEENLERN OLUTURULMASI

HERKES N C#
715
C#n hemen hemen her trl uygulama yazmnda kullanlabilmesine ragmen, C#n
kullanld en nemli uygulamalardan biri bileenlerdir. Bileen tabanl programlama C# ile
ylesine btnlemitir ki, C#a bazen bileen ynetimli bir dil denir. C# ve .NET Framework,
bileenler zerine tasarlanmtr ve bu yaplrken bileenlerle programlama modeli, eski
yaklamlara gre nemli lde basitletirilmi ve standardize edilmitir. rnein, bileen
terimi size COM bileenlerini ve bunlarn neden olduu skntlar anmsatyorsa, endie
etmeyin, C# tabanl bileenleri yazmas ok daha kolaydr.
Bileen Nedir?
ncelikle bileen terimini tanmlamakla ie balayalm. te genel bir tanm: Bir bileen;
bamsz ve yeniden kullanlabilen ikili ilevsellik birimidir. Bu tanm, bir bileenin drt temel
zelliini tarif etmektedir. Her birini tek tek ele alacaz.
Bir bileen, bamszdr. Her bileen kendi bana vardr (yani kendi paketini) oluturur.
Bir baka ifade ile, bir bileen, ihtiyac olan tm ilevsellii kendi zerinde tar. Ayrca, bir
bileenin kendi iinde nasl alt d dnyaya ak deildir. Bileenin tam olarak nasl
uyguland, o bileeni kullanan kodu etkilemeden deitirilebilir.
Bir bileen yeniden kullanlabilir. Yani bir bileen, onun ilevselliine ihtiya duyan
herhangi bir program tarafndan kullanlabilir. Bir bileeni kullanan programa istemci (client)
denir. Bir bileen, istenen sayda istemci tarafndan kullanlabilir.
Bir bileen tek bir ilevsellik birimidir. Bu, temel bir kavramdr, istemcinin asndan
bakldnda, bir bileen, spesifik bir ilevi ya da ilevleri yerine getirir.
Bir bileenin salad ilevsellik, herhangi bir program tarafndan kullanlabilir ama bir
bileen kendi bana bir program deildir.
Son olarak, bir bileenin yeniden kullanlabilir olmas ikili biimde salanr. Bu, temel bir
kavramdr. Bir bileeni stenen sayda istemci kullanabilir ama istemciler bileenin kaynak ko-
duna eriemez. Bir bileenin ilevsellii istemcilere o bileenin public yeleri aracl ile
salanr. Yani bir bileen, istemcilerine hangi ilevsellii saladn ve hangi ilevsellii
private olarak sakladn kontrol edebilir.
Bileen Modeli
Yukarda sunulan tanm bir yazlm bileenini gerekten de doru bir ekilde tanmlyor
olsa da, bileeni temelden etkileyen bir konu daha vardr: Bileenin uygulad model. Bir
istemcinin bir bileeni kullanmas iin; hem istemcinin hem de bileenin ayn kural dizisini
kullanmas gereklidir. Bir bileenin eklini ve doasn belirleyen kurallar dizisine bileen
modeli denir. Bir bileenle bir istemci arasnda nasl bir etkileim olacan ite bu bileen
modeli tanmlar.
Bileen modeli nemlidir; nk yeniden kullanlabilir ikili ilevsellik herhangi bir ekilde
oluturulabilir. rnein, parametreleri aktarmann ve deer dndrmenin farkl yollar vardr.

HERKES N C#
KISIM III C#'I UYGULAMAYA GERMEK

716
Ayrca, bellek ya da sistem kaynaklarn ayrmann ve serbest brakmann farkl yollar
mevcuttur. stemcilerin bileenleri serbeste kullanabilmesi iin, her ikisi de bileen modeli
tarafndan tanmlanan kurallara uymaldr. Aslnda, bileen modeli, istemci ile bileen arasnda
her iki tarafn da uymay kabul ettii szlemeyi tanmlar.
lgin bir husus udur: C# ve .NET Framework ncesinde ou bileen COM bileeniydi.
Component Object Model anlamna gelen COM, geleneksel Windows ortam ve C++ iin
tasarlanmt. Bu yzden COM, C# ve .NET Framework tarafndan salanan modern bellek
ynetiminden yararlanamad. Sonuta, COM szlemesi, uygulamas zor ve hatalara akt.
Neyse ki, C# ve .NET Framework tm bu skntlar ortadan kaldrd. Dolaysyla, eer
gemite
COMla ilgili kt deneyimler yasadysanz, bileenlerin C#ta ne kadar kolay
oluturulabildiini grmek sizin iin ho bir srpriz olacaktr.
C# Bileeni Nedir?
C#n alma eklinden dolay, herhangi bir snf, genel bileen tanmna uyar. rnein,
bir snf derlendikten sonra ikili ekliyle herhangi bir sayda uygulama tarafndan kullanlabilir.
Bu, her snfn bir bileen olduu anlamna gelir mi? Hayr. Bir snfn bir bileen olabilmesi
iin, o snf .NET Framework tarafndan tanmlanan bileen modeline uymaldr. Neyse ki, bu
son derece kolay yerine getirilebilecek bir kouldur:
System.ComponentModel.IComponent arayzn uygulamak bunun iin yeterlidir.
IComponentin uygulanmas zor olmasa da, pek ok durumda daha iyi bir alternatif
vardr: Bir snf, System.ComponentModel.Componenti kaltm yoluyla alabilir.
Component snf IComponentin varsaylan bir uygulamasn salar. Bu snf ayn zamanda
bileenle ilgili baka yararl zellikler de salar. ou bileen IComponenti kendileri
uygulamak yerine Componenti kaltm yoluyla alr, nk iin skc ksmnn bir blm
sizin adnza yaplmtr. Bylece, C#ta bir bileen olutururken sizin zerinize ar bir i
dmez.
Konteynerler ve Siteler
C# bileenleri ile yakndan ilgili iki yap daha vardr: Konteynerler ve siteler. Konteyner,
bir bileen grubudur. Konteynerler, birden fazla bileen kullanan programlar sadeletirir. Bir
site ise konteynerlerle bileenleri birbirine balamaya yarar. Bunlarn her ikisi de, ileride
ayrntl olarak ele alnmaktadr.
C# ile COM Bileenlerinin Karlatrmas
C# bileenlerinin uygulanmas ve kullanlmas, COM tabanl bileenlerden daha kolaydr.
COMu tanyanlar bir COM bileeni kullanrken bileenin bellekte kalmasn salamak iin
referans saym yapmak gerektiini bilirler. Byle bir erevede, bir bileene yeni bir referans
geldike, kodunuz AddRef()i armaldr. Bir referans ortadan kalktnda da kodunuz
BLM 24: BLEENLERN OLUTURULMASI

HERKES N C#
717
Release()i armaldr. Bu yaklamn problemi, hataya ak olmasdr. Neyse ki referans
saym C# bileenlerinde gerekli deildir. C#, anlamsz verilerin toplanmasn (garbage collec-
tion) kulland iin bir bileen, kendisine herhangi bir referans kald srece bellekte durur ve
referans kalmad anda bellekten silinir.
IComponent ve Component, bileenlerle programlamann temelini oluturduu iin
imdi de bunlar ele alacaz.
IComponent
IComponent, bileenlerin uymak zorunda olduu szlemeyi tanmlar. IComponent, tek
bir zellik ve bir olay belirler. Burada sz edilen zellik Sitedir ve aada gsterilmitir:
ISite Site { get; set; }
Site, bileenin sitesini elde eder ya da atar. Bir site, bileenin kimliini belirler. Eer
bileen bir konteynerde saklanmyorsa bu zellik null deerine sahiptir.
IComponent tarafndan tanmlanan olay aada gsterildii gibi Disposeddur.
event EventHandler Disposed
Bir bileen yok edildiinde bunun kendisine bildirilmesini isteyen ilemci Disposed olay
ile bir olay yneticisi kaydeder.
IComponent, Dispose() metodunu aada gsterildii ekilde tanmlayan
System.IDisposable da kaltm yoluyla alr:
void Dispose()
Bu metot, nesnenin kullanyor olabilecei tm kaynaklar serbest brakr.
Bileen
Bir bileen oluturmak iin IComponenti uygulayabilirsiniz ama kaltm yoluyla
Componenti almak ok daha kolaydr. nk Componentte IComponentin varsaylan bir
uygulamas mevcuttur. Bu blmdeki rneklerde bu yaklam kullanacaz. Componenti
kaltm yoluyla ald iin, snfnz .NET uyumlu bir bileen oluturmak iin gerekli kurallar
otomatik olarak yerine getirmi olacaktr.
Component snf sadece varsaylan yaplandrcy tanmlar. Normal olarak bir
Component nesnesini direkt olarak yaplandramazsnz. nk Componentin asl kullanm
yeri, oluturduunuz bileenler iin bir temel snf olmaktr.
Component, iki ak zellik tanmlar. Bunlardan ilki aada gsterilen Containerdir.
public IContainer Container { get; }

HERKES N C#
KISIM III C#'I UYGULAMAYA GERMEK

718
Container, aran bileeni tutan konteyneri elde eder. Eer bileen orada deilse null
deeri dndrlr. Containerin atamas bileen deil konteyner tarafndan yaplr.
kinci zellik, IComponent tarafndan tanmlanan Sitetr. Site, aada gsterildii
gibi Component tarafndan sanal bir zellik olarak uygulanr.
public virtual ISite Site { get; set; }
Bu ekilde bileenle balantl ISite nesnesi elde edilir ya da ona deer atanr. Eer
bileen bir konteynerde tutulmuyorsa Site, nulldr. Siten deeri bileen deil konteyner
tarafndan atanr.
Component, iki ak metot tanmlar. Bunlardan ilki ToString()i devre d brakan bir
metottur. kincisi de Dispose() metodudur. Bunun iki biimi vardr. lki yledir:
public void Dispose()
Bu kod, aran bileen tarafndan kullanlan tm kaynaklar serbest brakr. Metot,
IDisposable arayz tarafndan belirlenen Dispose() metodunu uygulamaktadr. Bir
bileenle onun kaynaklarn serbest brakmak iin, istemci Dispose()un bu versiyonunu
aracaktr.
Dispose() metodunun ikinci ekli de yledir:
protected virtual public void Dispose(bool nasl)
Eger nasl true ise, metodun bu versiyonu, aran bileen tarafndan kullanlan
ynetilen ve ynetilmeyen tm kaynaklar serbest brakr. Eer nasl false ise, sadece
ynetilmeyen kaynaklar serbest braklr. Dispose()un bu versiyonu korunmu olduundan,
istemci kodu tarafndan arlamaz. Onun yerine, nce Dispose()un ilk versiyonu tarafndan
arlr. Bir baka ifade ile, Dispose()a yaplan ilk ar, Dispose(bool)a bir ar
oluturmaktadr.
Genelde, sizin yazdnz bileen, artk kendisine ihtiya kalmadnda, serbest braklmas
gereken kaynaklar hala elinde tutuyorsa, Dispose(bool)u devre d brakacaktr. Eer
bileeninizin elinde herhangi bir kaynak yoksa, Dispose(bool)un Component tarafndan
salanan varsaylan uygulamas yeterlidir.
Component, bir bileenin kendi yerel uygulama ortamnn dnda rneklenmesi
durumunda kullanlan MarshalByRefObject nesnesini kaltm yoluyla alr. Byle bir
uygulama, bir bileenin bir baka prosesle ya da ala bal baka bir bilgisayarda oluturulmas
durumunda ortaya kabilir. Metot argmanlar ve geri dn deerleri gibi verinin alnp
verilebilmesi iin, verinin nasl gnderildiini tanmlayan bir mekanizma olmaldr. Varsaylan
durumda, bilgi, deer olarak alnp verilir. Ancak MarshalByRefObjectin kaltm yoluyla
alnmasyla veri, referans olarak aktarlr. Bylece, bir C# bileeni veriyi referans olarak alp
verir.
BLM 24: BLEENLERN OLUTURULMASI

HERKES N C#
719
Basit Bir Bileen
Bu noktada daha fazla teori sunmadan nce, basit bir rnek zerinde almak yararl
olacaktr. Aadaki programda ok basit bir ifreleme stratejisini uygulayan CipherComp adl
bir bileen oluturulmaktadr. Bir karakter, kendisine 1 eklenerek kodlanmaktadr. Kodun
zlmesi de 1 karlarak yaplmaktadr, Bir karakter katarm ifrelemek iin Encode(),
plaintext argman ile arlr. ifrelenmi bir karakter katarnn kodunu zmek iin
Decode(), ciphertext argman ile arlmaktadr. Her iki durumda da evrilmi karakter
katar dndrlmektedir.
// Basit bir Cipher bileseni. Bu dosyaya CipherLib.cs adini verin.

using System.ComponentModel;

namespace CipherLib { // bileseni kendi isim uzayna koyun

/* CipherCompun Componenti kalitim yoluyla aldigina
dikkat edin. */
public class CipherComp : Component {

// Bir karakter katarini kodla.
public string Encode(string msg} {
string temp = ;

for(int i = 0; i < msg.Length; i++)
temp += (char) (msg[i] + 1);

return temp;
}

// Bir karakter katarinin kodunu coz.
public string Decode(string msg) {
string temp = ;

for(int i = 0; i < msg.Length; i++)
temp += (char) (msg[i] - 1);

return temp;
}
}
}
imdi bu kodu yakndan inceleyelim. nce, dosyann en stndeki aklamann da iaret
ettii gibi, rnei takip edebilmek iin bu dosyaya CipherLib.cs adn verin. Bu sayede, eer
Visual Studio IDE kullanyorsanz, bileeni daha rahat kullanabilirsiniz.
System.ComponentModelin dahil edilmi olmasna da dikkat edin. Daha nce akland
gibi, bileenlerle programlamay destekleyen isim uzay budur.

HERKES N C#
KISIM III C#'I UYGULAMAYA GERMEK

720
CipherComp snf, CipherLib adl bir isim uzay iinde tutulmaktadr. Bir bileeni
kendi isim uzay iine koyarak global isim uzaynn dank bir hal almas nlenir. Bu, takip
edilmesi iyi olacak bir uygulamadr, ama teknik olarak gerekli deildir.
CipherComp snf Componenti kaltm yoluyla alr. Yani, CipherComp, .NET uyumlu
bir bileen olmak iin gerekli kontratn gereklerini yerine getirmektedir. CipherComp ok basit
olduundan, kendi bana bileenle ilgili ilevler yerine getirmesine gerek yoktur. Formaliteye
dair tm bu ayrntlar Component halletmektedir.
Sonra, CipherCompun herhangi bir kaynak ayrmadna dikkat edin. Spesifik olarak,
dier nesnelere herhangi bir referans da tutmamaktadr. CipherComp sadece Encode() ve
Decode() adl iki metot tanmlamaktadr. CipherComp herhangi bir kaynak tutmad iin
Dispose(bool)u uygulamak zorunda deildir. Kukusuz hem Encode() hem de
Decode() karakter katar referanslar dndrmektedir ama bu referanslar CipherComp
nesnesinin deil aran kodundur.
CipherLibi Derlemek
Bir bileenin exe dosyas olarak deil dll olarak derlenmesi gereklidir. Visual Studio IDE
kullanyorsanz, CipherLib iin bir Class Library projesi oluturmanz gerekecektir. Komut
satr derleyicisini kullanyorsanz, /t:library seeneini belirtmelisiniz. rnein,
CipherLibi derlemek iin u komut satrn kullanabilirsiniz:
csc /t:library CipherLib.cs
Bu komut, CipherComp bileenini tutan CipherLib.dll adl bir dosya oluturur.
CipherComp Kullanan Bir stemci
Oluturulan bileen artk kullanma hazrdr. rnein, aadaki program CipherCompun
bir istemcisidir ve bir karakter katarn ifrelemek ve onun ifresini zmek iin
CipherCompu kullanmaktadr.
// CipherComp kullanan bir istemci.

using System;
using CipherLib; // CipherCompun isim uzayini al

class CipherCompClient {
public static void Main() {
CipherComp cc = new CipherComp();

string text = This is a test;
string ciphertext = cc.Encode(text);
Console.WriteLine(ciphertext);

string plaintext = cc.Decode(ciphertext);
Console.WriteLine(plaintext);

BLM 24: BLEENLERN OLUTURULMASI

HERKES N C#
721
cc Dispose(); // kaynaklari serbest birak
}
}
stemcinin CipherLib isim uzayn dahil ediine dikkat edin. Bylece CipherComp
bileeni grnr hale gelmektedir. Kukusuz CipherCompa yaplan her referans uzun uzun
ve tam olarak yazmak da mmkndr ama onun isim uzayn dahil etmek daha kolaydr, Daha
sonra, CipherComp herhangi bir snf gibi kullanlmaktadr.
Dikkat ederseniz, programn sonunda Dispose() arlmaktadr Daha nce akland
gibi. Dispose()u ararak istemci, bileenin elinde bulunmas mmkn tm kaynaklarn
serbest braklmasn salamaktadr. Bileenler, dier C# nesne tipleri ile ayn anlamsz
verilerin toplanmas mekanizmalarn kullansalar da anlamsz verilerin toplanmas ii son
derece seyrek olarak yaplr. Dispose()u ararak bileenin kaynaklarn derhal serbest
brakmasn salarsnz.
Bu, bir bileenin bir a balants gibi kstl bir kayna elinde tutmas gibi baz
durumlarda nemli olabilir. CipherComp kendisine ait bir kayna elinde tutmad iin,
Dispose()a yaplan ar aslnda bu rnekte gerekli deildir. Ancak, Dispose(), bileen
szlemesinin bir parasn oluturduu iin bir bileenle iiniz bittiinde bu metodu armay
adet edinmeniz iyi bir fikirdir.
stemci program derlemek iin derleyiciye CipherLib.dlle referansta bulunmasn
sylemeniz gereklidir. Bunu salamak iin /r seeneini kullann. rnein, aadaki komut
satr, istemci programn derlenmesini salamaktadr.
csc /r:CipherLib.dll client.cs
Eer Visual Studio IDE kullanyorsanz, istemciye referans olarak CipherLib.dlli
eklemeniz gereklidir.
Program altrdnzda aadaki kty greceksiniz:
Uijt!jt!b!uftu
This is a test
Dispose()u Devre D Brakmak
Yukarda grdmz CipherComp bileeni herhangi bir sistem kayna tutmad gibi
herhangi bir nesne de oluturmaz ve tutmaz. Bu nedenle. Dispose(bool)u devre d
brakmaya gerek kalmamtr. Ancak, bileeniniz kaynak tutarsa, kaynaklarn deterministik
(ayn koullarda her seferinde tam olarak ayn sonucu veren) bir ekilde serbest braklmasn
salamak iin genellikle Dispose(bool)u devre d brakmanz gerekecektir. Neyse ki, bu
kolay bir itir.
Balamadan once, C#n anlamsz verileri toplama mekanizmasna gvenmek yerine,
neden bir bileenin kendi kaynaklarn genellikle kendisinin serbest brakmas gerektiini

HERKES N C#
KISIM III C#'I UYGULAMAYA GERMEK

722
anlamak nemlidir. Bu kitapta daha nce de akland gibi, sizin programnzn gzyle
bakldnda, anlamsz verilerin toplanmas deterministik bir olay deildir. Anlamsz veriler,
nesnelerin geri dnm gerektiinde deil ihtiya olduka (ya da anlamsz veri toplaycsnn
ihtiya grd zamanlarda) toplanmaktadr. Bu nedenle, eer bir bileen rnein ak bir
dosya gibi bir kayna elinde tutuyorsa ve bu kaynan bir baka program tarafndan
kullanlabilmesi iin serbest braklmas gerekiyorsa, o zaman kayna kullanan bileenin ii
bittii zaman kayna deterministik olarak serbest brakabilmesinin bir yolu olmaldr. Bileene
ynelik tm referanslar kaldrmak problemi zmez. nk bileen, ihtiya duyulan kaynaa
yapt referans bir sonraki anlamsz veri toplama turuna kadar elinde tutmaya devam eder.
Problemin zm, bileenin Dispose(bool)u uygulamasdr.
Dispose(bool)u devre d brakrken baz kurallara uymanz gereklidir:
1. Dispose(bool) deeri true olan bir argmanla arldnda, sizin versiyonunuz,
bileenle ilgili ynetilen ve ynetilmeyen tm kaynaklar serbest brakmaldr. Eer
metot false bir argmanla arlrsa, sizin versiyonunuz -eer varsa- sadece
ynetilmeyen kaynaklar serbest brakmaldr.

2. Dispose(bool), herhangi bir saknca domadan tekrar tekrar arlabilmelidir.

3. Dispose(bool), Dispose(bool)un temel snf uygulamasn armaldr.

4. Bileeninizin yok edicisi sadece Dispose(false)u armaldr.
kinci kurala uymak iin, bileeniniz, ne zaman dispose edildiini takip etmelidir. Bu,
genellikle dispose konumunu tutan zel bir alan tutarak yaplr.
Aada Dispose(bool)u uygulayan iskelet bir bileene yer verilmektedir.
/* Dispose(bool) kullanan bir bilesenin iskeletsel (basit) bir
uygulamasi. */
class MyComp : Component {
bool isDisposed; // bilesen dispose edildiyse truedur

public MyComp {
isDisposed = false;
// ...
}

-MyComp() {
Dispose(false);
}

protected override void Dispose(bool dispAll) {
if(!isDisposed) {
if(dispAll) {
// yonetilen kaynaklari burada serbest birak
isDisposed = true; // bileseni dispose edilmis olarak
// isaretle
}
// yonetilmeyen kaynaklari burada serbest birak
BLM 24: BLEENLERN OLUTURULMASI

HERKES N C#
723
base.Dispose(dispAll);
}
}
}
Dispose()u bir bileenin bir rnei zerinde ardnzda, Dispose(bool) bileenin
elinde bulunuyor olabilecek tm kaynaklar temizlemek iin otomatik olarak arlr.
Dispose(bool)un Kullanm
Dispose(bool)un kullanmn grmek iin, CipherCompu, tm ifreleme ilemlerinin
kaydn tutacak ekilde gelitireceiz. Program bunu yapmak iin bir dosyann Encode() ve
Decode() edilmesi iin gelen tm arlarn sonucunu kaydedecektir. Bu ek ilevsellik,
CipherCompun kullancsna saydamdr, yani kullancnn konudan haberdar olmas
gerekmez. Amaca ulamak iin, Dispose(bool)un bileene olan ihtiya ortadan kalktnda
dosyay kapatmas salanmtr. Dispose(bool)un ne zaman ve nasl arldn gstermek
iin koda WriteLine() arlar eklenmitir.
// Kutuk dosyas tutacak sekilde gelistirilmis bir sifreleme
// bileseni.

using System;
using System.ComponentModel;
using System.IO;

namespace CipherLib {

// Kutuk dosyasi tutan bir Cipher bileseni.
public class CipherComp : Component {
static int useID = 0;
int id; // ornek (instance) kodu
bool isDisposed; // bilesen dispose edilmis ise true
// degerine sahiptir.
FileStream log;

// Yapilandirici
public CipherComp() {
isDisposed = false; // bilesen dispose edilmemis
try {
log = new FileStream(CipherLog +
useID, FileMode.Create);
id = useID;
useID++;
} catch (FileNotFoundException exc) {
Console,WriteLine(exc);
log = null;
}
}

// Yok edici
-CipherComp() {
Console.WriteLine(Destructor for component + id);

HERKES N C#
KISIM III C#'I UYGULAMAYA GERMEK

724
Dispose(false);
}

// Dosyayi kodla. Sonucu dondur ve sakla.
public string Encode(string msg) {

string temp = ;

for(int i = 0; i < msg.Length; i++)
temp += (char) (msg[i] + 1);

// Kutuk dosyasina kaydet.
for(int i = 0; i < temp.Length; i++)
log.WriteByte((byte) temp[i]);

return temp;
}

// Mesajin kodunu coz. Sonucu dondur ve sakla.
public string Decode(string msg) {

string temp = ;

for(int i = 0; i < msg.Length; i++)
temp += (char) (msg[i] - 1);

// Kutuk dosyasina kaydet.
for(int i = 0; i < temp.Length; i++)
log.WriteByte((byte) temp[i]);

return temp;
}

protected override void Dispose(bool dispAll) {
Console.WriteLine(Dispose( + dispAll +
) for component + id);

if(!isDisposed) {
if(dispAll) {
Console.WriteLine(Closing file for +
component + id);
log.Close(); // sifrelenmis dosyayi kapat
isDisposed = true;
}
// serbest birakilacak yonetilmeyen bir kaynak yok.
base.Dispose(dispAll);
}
}
}
}
CipherCompun bu versiyonunu yakndan inceleyelim. Kod, u alanlarla balyor:
static int useID = 0;
int id; // ornek (instance) kodu
BLM 24: BLEENLERN OLUTURULMASI

HERKES N C#
725
bool isDOisposed; // bilesen dispose edilmisse true.
FileStream log;
lk alan, statik bir inttir ve CipherCompun her bir rneinin kimliini belirlemek iin
kullanlacaktr. UseIDdeki deer ktk dosyas ismine eklenecektir ve bylece
CipherCompun her rnei kendi ktk dosyasn kullanacaktr. Bileenin kimlii id alannda
tutulmaktadr. Bu, bileenin oluturulduu andaki useID deeridir. Bileenin dispose edilip
edilmedii bilgisi isDisposed alannda tutulmutur. Drdnc alan daha sonra ktk
dosyasna atfta bulunacak olan bir FileStream referans olan logdur.
Ardndan CipherCompun yaplandrcs gelmektedir:
public CipherComp() {
isDisposed = false; // bilesen dispose edilmemis
try {
log = new FileStream(CipherLog + useID, FileMode.Create);
id = useID;
useID++;
} catch (FileNotFoundException exc) {
Console.WriteLine(exc);
log = null;
}
}
Yaplandrcda isDisposeda balang deeri olarak false verilmitir. Bu,
CipherComp nesnesinin kullanlabilir olduunu gstermektedir. Ardndan ktk dosyas
almtr. Dikkat ederseniz, dosya ismi CipherLog ile useIDnin karakter katar cinsinden
ifadesinin birletirilmesiyle oluturulmaktadr. Daha sonra, useIDnin deeri idye atanmakta
ve peinden useID artrlmaktadr. Bylece, CipherCompun her rnei ayr bir ktk dosyas
kullanr ve her rnein benzersiz bir kimlik numaras vardr. Burada sz konusu olan nemli
noktalardan biri, bir CipherComp nesnesi oluturulmas ile bir dosya alm olmasdr. Bu
dosya, bileenin artk ona ihtiya duymad an serbest braklmas gereken bir sistem
kaynadr. Ancak istemcinin dosyay serbest brakma konusunda dorudan bir yetenei
yoktur. Hatta, istemci bir dosya aldndan bile habersizdir. Bu nedenle, dosya kapatma ii
Dispose(bool) tarafndan halledilmelidir.
Encode(), karakter katar argmann ifrelemekte ve sonucu dndrmektedir. Bu metot
ayn zamanda sonucu bir ktk dosyasna da kaydetmektedir. Ktk dosyas ak kald iin
Encode()a gelen yeni arlar, dosyaya yeni bilgiler eklenmesiyle sonulanr. rnein,
Encode(), farkl karakter katarn ifrelemek iin kullanlrsa, ifrelenmi karakter
katarn da tutan bir ktk dosyas ortaya kacaktr. Decode() da ayn ekilde almaktadr.
Tek fark, argmann deifre etmesidir.
imdi, CipherComp tarafndan devre d braklan Dispose(bool)a yakndan bakalm.
Kolaylk olsun diye kod aada gsterilmitir:
protected override void Dispose(bool dispAll) {
Console.WriteLine(Dispose( + dispAll +

HERKES N C#
KISIM III C#'I UYGULAMAYA GERMEK

726
) for component + id);

if(!isDisposed) {
if(dispAll) {
Console.WriteLine(Closing file for +
component + id);
log.Close(); // sifrelenmis dosyayi kapat
isDisposed = true;
}
// serbest birakilacak yonetilmeyen bir kaynak yok
base.Dispose(dispAll);
}
}
Dispose(bool)un protected olduuna dikkat edin. Bu metot, istemci kodundan
arlmayacaktr. Bunun yerine, Component tarafndan uygulanan ve ak olarak eriilebilen
Dispose() metodu tarafndan arlacaktr. Dispose(bool)un iinde isDisposed deeri
kontrol edilir. Nesne nceden dispose edilmise, hi bir eylemde bulunulmaz. Eer
isDisposed, false ise dispAll parametresi kontrol edilir. Eer bu parametre true ise
ktk dosyas kapatlr ve isDisposed, true deerini alacak ekilde ayarlanr. dispAll,
true olduunda, kural gerei tm kaynaklarn serbest braklmas gerektiini hatrlayn.
dispAll, false iken yalnzca ynetilmeyen kaynaklar (bu rnekte bu tr kaynaklar mevcut
deildir) serbest braklmaldr. Son olarak, temel snf (bu rnekte, Component) tarafndan
uygulanan Dispose(bool) arlr. Bu. temel snf tarafndan kullanlan her trl kaynan
serbest braklmasn garanti eder. WriteLine() arlar yalnzca rnek gstermek amacyla
dahil edilmitir. Gerek dnyaya ait bir uygulamada kullanlan Dispose(bool) metodu bu
arlar iemeyecektir.
imdi CipherCom iin yok ediciye gz atalm; bu fonksiyon aada gsterilmitir:
-CipherComp() {
Console.WriteLine(Destructor for component + id);
Dispose(false);
}
Sz konusu yok edici, false argman ile birlikte Dispose(bool)u armaktadr.
Bunun gerekesi basittir. Eer sz konusu bileen iin ilgili yok edici almakta ise, bileen
anlamsz veri toplaycs tarafndan geri dntrlyor dernektir. Bu durumda, ynetilen
kaynaklarn tm otomatik olarak serbest braklacaktr. Yok edicinin yapmas gereken tek ey,
ynetilmeyen kaynaklar serbest brakmaktr. WriteLine() ars yalnzca rnek gstermek
amacyla kullanlmtr; gerek bir programda bu ar yer almayacaktr.
CipherCompa yaplan deiiklikler CipherCompun ak arayzn etkilemedii iin
CipherComp daha nce kullanld ekilde kullanlabilir. rnein, iki karakter katarn ifrele-
yen ve ifrelerini zen bir istemci program aada yer almaktadr:
// CipherComp kullanan baska bir istemci.

using System;
BLM 24: BLEENLERN OLUTURULMASI

HERKES N C#
727
using CipherLib; // CipherCompun isim uzayini al

class CipherCompClient {
public static void Main() {
CipherComp cc = new CipherComp();

string test = Testing;

string ciphertext = cc.Encode(text);
Console.WriteLine(ciphertext);

string plaintext = cc.Decode(ciphertext);
Console.WriteLine(plaintext);

text = Components are powerful.;

ciphertext = cc.Encode(text);
Console.WriteLine(ciphertext);

plaintext = cc.Decode(ciphertext);
Console.WriteLine(plaintext);

cc.Dispose(); // kaynaklari serbest birak
}
}
Programn kts aada gsterilmitir:
Uftujoh
Testing
Dpnqpofout!bsf!qpxfsgvm/
Components are powerful.
Dispose(True) for component 0
Closing file for component 0
Program altktan sonra CipherLogO adnda bir ktk dosyas aadakileri ierecektir:
UftujohTestingDpnqpofout!bsf!qpxfsgvm/Components are powerful.
Bu, ifrelenen ve ifreleri zlen iki karakter katarnn pe pee eklenmi halidir.
Dispose(bool)un true argman ile arldna ktda dikkat edin. Bunun nedeni,
programn Dispose()u CipherComp nesnesi zerinde armasdr. nceden de akland
gibi, Dispose() daha sonra Dispose(bool)u true argman ile arr; bu, tm
kaynaklarn serbest braklmasn iaret eder. Altrma olarak istemci programndaki
Dispose() arsn aklama yoluyla programdan karn, sonra program derleyin ve
altrn. Artk u kty greceksiniz:
Uftujoh
Testing
Dpnqpofout!bsf!qpxfsgvm/
Components are powerful.
Destructor for component 0
Dispose(False) for component 0

HERKES N C#
KISIM III C#'I UYGULAMAYA GERMEK

728
Dispose(False) for component 0
Dispose()a ar yaplmad iin CipherComp bileeni aka dispose edilmez.
Ancak, program sona erdiinde kukusuz yok edilir. Bylece, ktdan da grld gibi,
bileenin kendi yok edicisi arlr; bu da sras geldiinde Dispose(bool)u bir false
argmanla arr. Dispose(bool)a yaplan ikinci ar, CipherCompun Dispose(bool)
metodu iindeki Dispose()un temel snf versiyonuna yaplan ardan dolay meydana
gelir. Bu durum Dispose(bool)un ikinci kez arlmasna neden olur. Bu rnekte bu
gereksizdir, fakat Dispose(), nasl arldnn farknda olamayaca iin bu nlenemez
ancak zararszdr.
Dispose(bool)un uygulan ile ilgili ayn temel yaklam kendi oluturduunuz
herhangi bir bileen tarafndan da kullanlabilir.
Dispose Edilmi Bir Bileenin Kullanmn nlemek
Yukarda gsterildii zere CipherComp kendi kendisini tam anlamyla dispose ediyor
olsa bile, yine de, herhangi bir gerek dnya bileeni tarafndan ynlendirilmesi gereken bir
problem iermektedir: CipherComp, bir istemcinin dispose edilmi bir bileeni kullanma
giriimini nlememektedir. Sz gelii, bir istemcinin bir CipherComp bileenini dispose
etlikten sonra bu bileen zerinde Encode()u arma giriiminden bu istemciyi hi bir ey
alkoyamaz. Neyse ki, bunun zm kolaydr: Sz konusu bileenin her kullanmnda
isDisposed alann kontrol etmesi yeterlidir. rnein, Encode() ve Decode()u daha iyi
yazmann yollar aada gsterilmitir:
// Dosyay sifrele. Sonucu dondur ve sakla.
public string Encode(string msg) {

// Dispose edilmis bir bilesenin kullanilmasn engelle.
if(isDisposed) {
Console.WriteLine(Error: Component disposed.);
return null;
}

string temp = ;

for(int i = 0; i < msg.Length; i++)
temp += (char) (msg[i] + 1);

// Bir kutuk dosyasinda sakla
for(int i = 0; i < temp.Length; i++)
log.WriteByte((byte) temp[i]);

return temp;
}

// Mesajin sifresini coz. Sonucu dondur ve sakla.
publc string Decode(string msg) {

// Dispose edilmis bir bilesenin kullanimini engelle.
BLM 24: BLEENLERN OLUTURULMASI

HERKES N C#
729
if(isDisposed) {
Console.WriteLine(Error: Component disposed.);
return null;
}

string temp = ;

for(int i = 0; i < msg.Length; i++)
temp += (char) (msg[i] - 1);

// Bir kutuk dosyasinda sakla
for(int i = 0; i < temp.Length; i++)
log.WriteByte((byte) temp[i]);

return temp;
}
Her iki metotta da, eer isDisposed, true ise bir hata mesaj grntlenir ve baka bir
eylemde bulunulmaz. Kukusuz gerek dnya ile ilgili bir bileende, eer dispose edilmi bir
nesne kullanlmaya allrsa normal olarak programnz bir kural d durum frlatacaktr.
using fadesini Kullanmak
Blm 18de akland gibi, bir nesneyi serbest brakmak iin aka Dispose()
metodunu armak yerine, bu ilemin otomatik olarak gereklenmesi iin using ifadesi
kullanlabilir. using ifadesinin aadaki gibi genel kullanmlar olduunu hatrlayn:
using (nesne) {
// nesneyi kullanir
}

using (tip nesne = ilkDeer) {
// nesneyi kullanir
}
Burada nesne, using blou iinde kullanlmakta olan bir nesnedir. lk ifadede, sz
konusu nesne using ifadesinin dnda deklare edilir, ikinci ifadede, nesne using ifadesinin
iinde deklare edilir. Blok sona ererken Dispose() metodu otomatik olarak arlr. using
ifadesi yalnzca System.IDisposable arayzn uygulayan nesnelere uygulanr. (Elbette
tm bileenler bu arayz uygular.)
te, CipherComp iin, dorudan Dispose()u armak yerine usingi kullanan bir
istemci:
// Using ifadesini kullanir.

using System;
using CipherLib; // CipherCompun isim uzayini import et

class CipherCompClient {
public static void Main() {

HERKES N C#
KISIM III C#'I UYGULAMAYA GERMEK

730

// cc bu blogun sonunda dispose edilecektir.
using(CipherComp cc = new CipherComp()) {

string text = The using statement.;

string ciphertext = cc.Encode(text);
Console.WriteLine(ciphertext);

string plaintext = cc.Decode(ciphertext);
Console.WriteLine(plaintext);
}
}
}
Programn kts aada gsterilmitir:
Uif!vtjoh!tubufnfou/
The using statement.
Dispose(True) for component 0
Closing file for component 0
ktdan da grld gibi, using blou sona erince Dispose() otomatik olarak
arlmtr. usingi kullanmak ya da aka Dispose()u armak size kalmtr. Ancak,
using kesinlikle kodunuzu kolaylatrr.
Konteynerler
Bileenlerle alrken bunlar bir konteyner iinde saklamann yararl olabileceini fark
edebilirsiniz. nceden de akland gibi, bir konteyner bir grup bileen tanmlar. Konleynerin
balca avantaj, bir grup bileenin ortaklaa ynetilmesine olanak tanmasdr. Sz gelii, bir
konteyner zerinde Dispose()u ararak konteyner iindeki tm bileenleri dispose
edebilirsiniz. Genel olarak konteynerler, birden fazla bileenle almay ok daha
kolaylatrrlar.
Bir konteyner oluturmak iin System.ComponentModel isim uzaynda tanmlanan
Container snfna ait bir nesne oluturacaksnz. Konteyner iin yaplandrc u ekildedir:
public Container()
Bu ifade bo bir konteyner oluturur.
Bir kez bir Container nesnesi oluturduktan sonra artk Add()i ararak buna
bileenler eklersiniz. Add()in aada gsterilen iki kullanm vardr:
public virtual void Add(IComponent bileen)
public virtual void Add(IComponent bileen, string bileenAd)
lk ifade bileeni konteynere ekler. kinci ifade bileeni konteynere ekler ve buna
bileenAd ile belirtilen ismi verir. sim benzersiz olmaldr ve byk kk harf ayrm dik-
BLM 24: BLEENLERN OLUTURULMASI

HERKES N C#
731
kate almamaldr. Zaten konteynerde olan bir ismi kullanmaya alrsanz, bir
ArgumentException frlatlr. Bu isim, bileenin Site zellii araclyla elde edilebilir.
Bir konteynerden bir bileen karlmak iin aada gsterilen Remove()u kullann:
public virtual void Remove(IComponent bileen]
Bu metodun baarl olmas beklenir, nk ya metot bileeni konteynerden kartr ya
da bileen ilk etapta konteynerde deildir. Her iki durumda da, Remove()a yaplan
ardan sonra bileen artk konteynerde mevcut deildir.
Container, Dispose()u uygular. Dispose() bir konteyner zerinde arld zaman
konteyner iindeki tm bileenler kendi Dispose() metotlarnn arlmasn
salayacaklardr. Bylece, tek bir Dispose() ars ile bir konteyner iindeki tm bileenleri
dispose edebilirsiniz.
Container, Components adnda bir zellik tanmlar. Components u ekilde
tanmlanr:
public virtual ComponentCollection Components { get; }
Bu zellik, arda bulunan konteyner iinde saklanan bileenlerin bir koleksiyonunu elde
eder.
Componentn Container ve Site adnda iki zellik tanmladn hatrlayn. Bu
zellikler tm tretilmi bileenlerde yer alacaktr. Bir bileen bir konteyner iinde sakland
zaman sz konusu nesnenin Container ve Site zellikleri otomatik olarak ayarlanr.
Container zellii, sz konusu bileenin sakland konteynere referansta bulunur. Site,
bileenle ilgili bilgilere referansta bulunur. Bileenin ad, bileenin iinde sakland
konteynerin ad ve bileenin tasarm kipinde olup olmad bu bilgiler kapsamnda yer alr.
Site zellii bir ISite referans dndrr. Bu arayzde aadaki zellikler tanmldr:

zellik Aklama
IComponent Component { get; } Sz konusu bileen iin bir referans elde eder.
IContainer Container { get; } Sz konusu konteyner iin bir referans elde eder.
bool DesignMode { get; } Eer bileen bir tasarm arac tarafndan
kullanlyorsa bu, doru deerine sahiptir.
string Name { get; set; } Sz konusu bileenin adn alr ya da ayarlar.
alma srasnda kullanlan konteyner hakknda ya da bileenin alma srasndaki
durumu hakknda bilgi edinmek iin bu zellikleri kullanabilirsiniz.


HERKES N C#
KISIM III C#'I UYGULAMAYA GERMEK

732
Konteynerin Gsterilmesi
Aadaki program, iki CipherComp bileenini saklamak iin bir konteyner
kullanmaktadr. lk bileen bir isim belirtilmeden konteynere eklenir. kinci bileene Second
Component ad verilir. Bir sonraki admda, her iki bileen zerinde ilemler gerekletirilir.
Sonra, ikinci bileenin ad kendi Site zellii aracl ile grntlenir. Son olarak, konteyner
zerinde Dispose() arlarak her iki bileen serbest braklr. (Burada bir using ifadesi
kullanlm olabilirdi. Ancak, rnek vermek amacyla Dispose() ak olarak arlmtr.)
// Bir bilesen konteynerini gosterir.

using System;
using System.ComponentModel;
using CipherLib; // CipherCompun isim uzayini al

class UseContainer {
public static void Main(string[] args) {
string str = Using containers.;
Container cont = new Container();

CipherComp cc = new CipberComp();
CipherComp cc2 = new CipherComp();

cont.Add(cc);
cont.Add(cc2, Second Component);

Console.WriteLine(First message: + str);
str = cc.Encode(str);
Console.WriteLine(First message encoded: + str);

str = cc.Decode(str);
Console.WriteLine(First message decoded: + str);

str = one, two, three;
Console.WriteLine(Second message; + str);

str = cc2.Encode(str);
Console.WriteLine(Second message encoded: + str);

str = cc2.Decode(str);
Console.WriteLine(Second message decoded: + str);

Console.WriteLine(\ncc2s name: + cc2.Site.Name);

Console.WriteLine();

// Her iki bileseni de serbest birak.
cont.Dispose();
}
}
Programn kts aada gsterilmitir:
BLM 24: BLEENLERN OLUTURULMASI

HERKES N C#
733
First message: Using containers.
First message encoded: Vtjoh!dpoubjofst/
First message decoded: Using containers.
Second message: one, two, three
Second message encoded: pof -!uxp-!uisff
Second message decoded: one, two, three

cc2s name: Second Component
Dispose(True) for component 1
Closing file for component 1
Dispose(True) for component 0
Closing file for component 0
Grdnz gibi, konteyner zerinde Dispose() arlarak konteyner iindeki tm
bileenler dispose edilmektedir. Birok bileenle ya da bileen rnei ile alrken bu ok
byk yarar salar.
Bileenler, Programlamann Gelecei mi?
Bir uygulamay birtakm bileenler zerine ina etmek programlama iine son derece gl
bir yaklam oluturmaktadr, nk bileenler, daha karmak programlara hakim olmanza
olanak salamaktadr. Program karmaklnn artmas uzun sredir programclarn
karsndaki en byk sorun olarak kabul edilmektedir. Yeni balayanlar, programclk
kariyerlerinin bandan itibaren program uzadka hatadan arndrma sresinin de arttn
grmektedirler. Program uzadka, programn karmakl da artar. Biz insanlarn
ynetebilecei karmaklk dzeyinin de bir snr vardr. Sadece say asndan baklrsa,
programn satr says arttka yan etkilerin ve istenmeyen etkileimlerin ortaya kma olasl
da oalmaktadr. Bugn ou programcnn da bildii gibi, programlar giderek an karmak
bir hal almaktadr.
Yazlm bileenleri, karmakl bl ve ynet stratejisiyle ynetmemize yardmc olur.
levsellik birimlerinin bamsz bileenlere ayrlmas sayesinde programclar programn
yanstt karmakl azaltabilir. Bileen ynelimli bir yaklamla, bir program, net olarak
tanmlanm ve uygulama ayrntlaryla ilgilenmeye gerek kalmadan kullanlabilen yap talar
(bileenler) zerine ina edilir. Bu yaklamn net sonucu, karmakln azaltlmasdr. i
mantksal sonucuna gtrrsek, bir programn byk blm birbiriyle balanm, aralarnda
veri alverii yapan bileenlerden ibaret olacaktr. Byle bir yaklama bileen ynelimli
programlama denilebilir.
Bileenlerin gc ve C#ta nc kadar kolay oluturulabildikleri dikkate alnrsa, acaba
programcln gelecei bileenlerde midir? Pek ok programc asndan bu sorunun cevab
artsz olarak Evet!tir.



Y R M B E N C B L M


FORM TABANLI
WNDOWS
UYGULAMALARI
GELTRMEK


















25
BLM 25: FORM TABANLI WNDOWS UYGULAMALARI GELTRMEK

HERKES N C#
735
Bu kitapta gsterilen programlarn ou konsol uygulamalardr. Konsol uygulamalar, C#
dilinin elerini gstermek iin iyi bir yntemdir; ayrca, dosya filtreleri gibi baz yardmc
program trleri iin kullanma uygundur. Kukusuz, modern uygulamalarn pek ou Windows
grafik kullanc arayz (GUI) ortamna ynelik tasarlanmaktadr. C#n bir Windows
uygulamas oluturmak iin nasl kullanldn gstermeden elinizdeki kitap eksik olurdu.
Gemite Windows uygulamalar gelitirmek zorlu bir abayd. Yeni balayanlarn bir
Windows uygulamasnn yalnzca temel elerini renmek iin birka hafta harcamalar garip
deildi. Neyse ki, C# ve .NET btn bunlar tmden deitirdi. .NET ktphanesi, Windows
Formlarn destekleyen btn bir alt sistem iermektedir. Windows Formlar, bir Windows
program gelitirmeyi adamakll basitletirir. C# ve System.Windows.Forms ktphanesini
kullanarak Windows uygulamalar ok daha kolay gelitirilir ve btn gelitirme sreci nemli
lde standardize edilmi olur.
Windows programlama, bu konuya adanm seriler dolusu kitap ieren ok byk bir
konudur. Bunun btn ynlerini tek bir blmde anlatmak elbette mmkn deildir. Bunun
yerine, bu blm form tabanl Windows programlamaya atlayarak bir giri yapar. Bu
blmde bir pencerenin, bir mennn nasl oluturulaca; bir dmenin nasl uygulanaca ve
bir mesaja nasl yant verilecei aklanmaktadr. Bu blm balan sona altktan sonra,
form tabanl Windows programlamann dier ynlerine de kolaylkla ilerleyebileceksiniz.
Windows Programlamann Ksa Tarihesi
C# ve .NET Frameworkn Windows programlamaya getirdii avantajlar takdir etmeniz
iin Windows programlamann tarihini biraz bilmeniz gereklidir. Windows ilk gelitirildiinde
programlar dorudan Windows API (Application Programming. Interface - Uygulama
Programlama Arayz) ile etkileirdi. Windows API, Windows tarafndan tanmlanan ve
programlarn Windowsun salad eitli fonksiyonlara erimek iin ardklar kapsaml
metotlar btndr. API tabanl programlar ok uzun ve karmaktr. Sz gelii, API tabanl bir
program tasla bile yaklak 50 satr uzunluunda kod gerektirir. e yarar herhangi bir ilevde
bulunan API temelli programlar en azndan birka yz satr kod ierirler; gerek uygulamalar
ise binlerce satrlk koda sahiptir. Bu nedenle, ilk gnlerde Windows programlarn yazmak ve
bakmn yapmak zordu.
Bu probleme yant olarak APInin ilevselliini bir snf iine paketleyen snf
ktphaneleri gelitirildi. Bunlardan en nemlisi MFCdir (Microsoft Foundation Classes -
Microsoft Temel Snflar). Okuyucularn birou MFC ile aina olacaklardr. MFC, C++ta
yazlmtr; MFC tabanl programlar da C++ta yazlmtr. MFC, nesne ynelimli avantajlar
salad iin, bu sayede, Windows program gelitirme sreci basitlemitir. Ancak, MFC
programlar, ayr balk dosyalar, kod dosyalar ve kaynak dosyalar gerektirerek her eye
ramen olduka karmak ilerdi. stelik MFC, APInin etrafnda yalnzca ince bir zar
gibiydi. Bu nedenle, birok Windows tabanl etkinlik halen nemli miktarda ak program
ifadesi gerektiriyordu.

HERKES N C#
KISIM III C#'I UYGULAMAYA GERMEK

736
C# ve .NET Frameworkn Forms ktphanesi, Windows programlama yaklamna tama-
men nesne ynelimli bir boyut katmaktadr. Forms ktphanesi APInin etrafnda yalnzca bir
ambalaj salamak yerine, bir Windows uygulamas gelitirilirken, bu srecin standardize edil-
mi, entegre ve mantksal adan tutarl bir ekilde ynetilmesini salayan bir yntem tanmlar.
B tr bir entegrasyon dzeyi C#n delegeler ve olaylar gibi benzersiz zellikleri sayesinde
mmkn klnr. Ayrca, C#n anlamsz veri toplaycs (garbage collector) sayesinde zellikle
sknt veren bellek sznts problemi neredeyse tamamen ortadan kalkmtr.
API ya da MFC kullanarak daha nceden Windows iin programlama yapmsanz, C#n
yaklamn dikkat ekici lde ferahlatc bulacaksnz. Windowsun douundan beri ilk kez
bir Windows uygulamas gelitirmek, hemen hemen bir konsol uygulamas gelitirmek kadar
kolay olmaktadr.
Form Tabanl Bir Windows Uygulamas Yazmann ki
Yntemi
Balamadan nce nemli bir noktay vurgulamamz gereklidir. Visual Studio, bir Windows
uygulamas oluturma srecinin byk ksmn otomatize eden tasarm aralarndan oluan
sofistike bir set ierir. Bu aralar kullanarak, uygulamanz tarafndan kullanlan eitli kontrol-
leri ve menleri grsel adan kurabilir ve konumlandrabilirsiniz. Visual Studio ayrca her
zellik iin gerekli snflar ve metotlar da ayarlar. Akas, Visual Studio tasarm aralar,
gerek dnyaya ait Windows uygulamalarnn birounun gelitirilmesinde iyi bir tercihtir.
Ancak, bu aralar kullanmanz iin hibir gerek yoktur. Tpk konsol tabanl uygulamalarda
olduu gibi bir metin editr kullanarak ve sonra bunu derleyerek de bir Windows program
gelitirebilirsiniz.
Bu kitap Visual Studio yerine C# ile ilgili olduu iin ve bu blmde yer alan Windows
programlar olduka ksa olduu iin tm programlar, bir metin editr kullanlarak
kodlanabilecek ekilde gsterileceklerdir. Yine de, programlarn genel yaps, tasarm ve
organizasyonu tasarm aralar tarafndan gelitirilen programlarla ayndr. Bu nedenle, bu
kitaptaki malzeme her iki yntem iin de geerlidir.
Windowsun Kullanc ile Etkileimi
Windows programlama ile ilgili renmeniz gereken ilk ey kullancnn ve Windowsun
nasl etkiletikleridir, nk bu, tm Windows programlarnn paylat ortak mimariyi
tanmlamaktadr. Bu etkileim, bu kitabn dier blmlerinde gsterilen konsol tabanl
programlardan esasen farkldr. Bir konsol program yazdnzda, iletim sistemi ile etkileimi
balatan sizin programnzdr. Sz gelii, Read() ya da WriteLine() ararak girdi ya da
kt gibi isteklerde bulunan programn kendisidir. Yani, geleneksel biimde yazlan
programlar iletim sistemini arrlar. letim sistemi sizin programnz armaz. Ancak,
geni lekte, Windows bunun tam ters biiminde alr. Sizin programnz aran
Windowsdur. Bu sre u ekilde gereklenir: Bir program kendisine Windows tarafndan bir
mesaj gnderilene kadar bekler. Mesaj alnr alnmaz programnzn uygun bir eylemde
BLM 25: FORM TABANLI WNDOWS UYGULAMALARI GELTRMEK

HERKES N C#
737
bulunmas beklenir. Programnz mesaja yant verirken Windows tarafndan tanmlanan bir
metodu arabilir, ancak etkinlii balatan her eye ramen Windowstur. Tm Windows
programlarnn genel eklini belirleyen, her eyden ok, Windows ile gerekletirilen mesaja
dayal etkileimdir.
Windowsun programnza gnderebilecei farkl tipte birok mesaj mevcuttur. Sz gelii,
programnza ait bir pencere iinde ne zaman fare tklansa, fare tkland anlamnda bir mesaj
gnderilecektir. Bir dmeye basldnda ya da bir men seenei iaretlendiinde baka tipte
bir mesaj gnderilir. Bir gerei beyninize kazyn: Sizin programnz sz konusu olduu
srece mesajlar rasgele gelir. Windows programlarnn, kesme gdml (interrupt driven)
programlara benzemesinin nedeni budur. Bir sonraki mesajn nasl bir mesaj olacan
bilemezsiniz.
Windows Formlar
Bir C# Windows programnn ekirdeinde form yer alr. Form, bir pencere oluturmak,
bunu ekranda grntlemek ve mesajlar almak iin gerekli temel ilevsellii bir btn halinde
paketler. Bir form her trl pencereyi simgeleyebilir. Uygulamann ana penceresi, ocuk pen-
cere, hatta bir iletiim kutusu bile bu kapsamda yer alr.
Form ilk oluturulduunda botur, ilevsellik katmak iin, sz gelii, menler ve dmeler,
listeler ve onay kutular gibi kontroller eklersiniz. Bu nedenle, bir formu, dier Windows
nesneleri iin bir konteyner gibi dnebilirsiniz.
Pencereye bir mesaj gnderildiinde bu bir olaya dntrlr. Bu yzden, bir Windows
mesajn kontrol altna almak amacyla bu mesaj iin formla birlikte bir olay yneticisi
kaydetmeniz yeterli olacaktr. Sonra, mesaj ne zaman alnrsa alnsn olay yneticiniz otomatik
olarak arlr.
Form Snf
Bir form Form snfndan ya da Formdan tretilen herhangi bir snftan bir nesne
rneklenerek oluturulur. Form kendisine zg nemli bir ilevsellie sahiptir; ayrca, kaltm
yoluyla ek ilevsellik de edinir. Formun en nemli temel snrlarndan ikisi Bolm 24te ele
alnan System.ComponentModel.Component ve System.Windows.Forms.Controldr.
Control snf tm Windows kontrollerinde ortak olan zellikleri tanmlar. Form, kaltm
yoluyla Controlden tredii iin Form da aslnda bir kontroldr. Bu gerek sayesinde
formlarn kontrol oluturmak amacyla kullanlmalar mmkn olur. Form ve Controln
yelerinden birka takip eden rneklerde kullanlmtr.
Form Tabanl Bir Windows Program Tasla
Kk apta bir form tabanl Windows uygulamas gelitirerek balayacaz. Bu uygulama
yalnzca bir pencere oluturur ve bunu grntler. Baka zellikler iermez. Ancak, bu taslak

HERKES N C#
KISIM III C#'I UYGULAMAYA GERMEK

738
tmyle fonksiyonel bir pencere oluturmak iin gerekli admlar kesinlikle gstermektedir. Bu
taslak, birok tipte Windows uygulamasnn zerine ina edilecei bir balang noktasdr.
Form tabanl Windows programnn tasla aada gsterilmitir:
// Form tabanli Windows program taslagi.

using System;
using System.Windows.Forms;

// WinSkel, Formdan turetilmitir.
class WinSkel : Form {

public WinSkel() {
// Pencereye bir isim ver.
Text = A Windows Skeleton;
}

// Main, sadece uygulamayi baslatmak icin kullanilir.
[STAThread]
public static void Main() {
WinSkel skel = new winSkel(); // bir form olustur

// pencereyi calistirmaya basla.
Application.Run(skel);
}
}
Bu programla oluturulan pencere ekil 25.lde gsterilmitir.
Gelin imdi, bu program satr satr inceleyelim. ncelikle, hem Systemin hem de
System.Windows.Formsun programa dahil edildiine dikkat edin. System, Main()in
hemen ncesinde yer alan STAThread niteliinden dolay gereklidir.
System.Windows.Forms az nce bahsedildii gibi Windows Forms alt sistemini destekler.
Daha sonra, WinSkel adnda bir snf oluturulur. Bu snf, Formdan kaltm yoluyla
tretilir. Bylece, WinSkel belirli tipte bir form tanmlar. Bu rnekte, bu kk apl bir
formdur.
WinSkel yaplandrcs iinde aadaki kod satr mevcuttur:
Text = A Windows Skeleton;
Text, pencerenin baln ayarlayan zelliktir. Bylece, bu atama, pencerenin balk
ubuunun A Windows Skeleton yazsn iermesine neden olur. Text u ekilde
tanmlanr:
public virtual string Text { get; set; }
Text, Controlden tretilmitir.
BLM 25: FORM TABANLI WNDOWS UYGULAMALARI GELTRMEK

HERKES N C#
739


EKL 25.1: Form tabanl pencere tasla.

Sonra, Main() metodu gelir. Bu, elinizdeki kitabn geri kalan blmlerinde yer alan
Main()e ok benzer ekilde deklare edilmitir. Bu, programn almaya balad metottur.
Ancak, dikkat ederseniz, Main() ncesinde STAThread zellii gelmektedir. Microsoft, bir
Windows programnn Main() metodunun bu zellie sahip olmas gerektiini bildirmektedir.
Bu, programn kanal modelini (threading model) single-threaded apartment (STA) olarak
ayarlar. (Kanal modelleri ve apartmanlar bu kitabn kapsam dndadr, ancak ksaca
bahsetmek gerekirse, bir Windows uygulamas iki farkl kanal modelinden birini kullanabilir:
tek kanall apartman [single-threaded apartment] ya da ok kanall apartman [multi-threaded
apartment].)
Main() iinde bir WinSkel nesnesi oluturulur. Bu nesne, sonra Applications snf
tarafndan tanmlanan Run() metoduna, aada gsterildii ekliyle aktarlr:
Application.Run(skel);
Bu, pencerenin almasn balatr. Application snf System.Windows.Form iinde
tanmldr ve tm Windows uygulamalarnda ortak olan zellikleri btnyle paketler. Taslakta
kullanlan Run() metodu aada gsterilmitir:
public static void Run{Form nesne)

HERKES N C#
KISIM III C#'I UYGULAMAYA GERMEK

740
Metot, bir forma atfta bulunan bir referans parametre olarak alr. WinSkel, Formdan
tretildii iin WinSkel tipinde bir nesne Run()a aktarlabilir.
Program altrldnda ekil 25.2de gsterilen pencereyi oluturur. Pencere varsaylan
boyutlara sahiptir: 300 piksel genilik ve 300 piksel ykseklik. Pencere tam anlamyla
fonksiyoneldir. Yeniden boyutlandrlabilir, tanabilir, kltlebilir, bytlebilir ve
kapatlabilir. Bylece, hemen hemen tm pencereler iin gerekli olan temel zellikler, forma
dayal birka satr kod yazlarak elde edilmitir. te yandan, ayn program C dili kullanarak ya
da dorudan Windows API ararak yazmak yaklak be kat kadar daha fazla kod satr
gerektirirdi!
nceki taslak, forma dayal Windows uygulamalarnn birounun eklini alaca
anahatlar tanmlamaktadr. Genel olarak, bir form oluturmak iin Formdan tretilen bir snf
oluturursunuz. Formu gereksinimlerinize uygun biimde kullanma hazrlayn, tretilmi
snfnzdan bir nesne oluturun ve bu nesne zerinde Application.Run() arn.
Windows Taslan Derlemek
Bir Windows programn komut satr derleyicisi ya da Visual Studio kullanarak
derleyebilirsiniz. Bu blmdeki ok ksa programlar iin komut satr derleyicisi en kolay
yntemdir, fakat gerek uygulamalarda muhtemelen IDEyi kullanmak isteyeceksiniz. (Ayrca,
bu blmn banda da akland gibi, Visual Studio tarafndan sunulan tasarm aralarn da
muhtemelen kullanacaksnz.) Her iki yntem de burada gsterilmitir.
Komut Satrndan Derlemek
Taslaa WinSkel.cs adn verdiinizi varsayarsak, tasla komut satrndan derlemek iin
u komutu kullann:
csc /t:winexe WirtSkel.cs
/t:winexe seenei derleyiciye bir konsol program yerine bir Windows uygulamas
oluturmasn bildirir. Program altrmak iin komut satrndan yalnzca WinSkeli girmeniz
yeterlidir.
IDEden Derlemek
Program Visual Studio IDE kullanarak derlemek iin ncelikle yeni bir Windows
Application projesi oluturun. Bunu File | New | Project komutunu seerek gerekletirin.
Sonra, New Project iletiim kutusundan Windows Application seeneini iaretleyin. Projeye
WinSkel adn verin. Bu proje, kendisi ile ilikilendirilmi Form1.cs adnda bir dosya
ierecektir. Bu dosyay silin. Sonra, WinSkel proje ismi zerinde farenin sa tuu ile tklayn.
Add seeneini, sonra da Add New Item seeneini iaretleyin. Aada gsterilen iletiim
kutusunu greceksiniz:

BLM 25: FORM TABANLI WNDOWS UYGULAMALARI GELTRMEK

HERKES N C#
741


C# Code File seeneini iaretleyin ve dosyay WinSkel.cs olarak isimlendirin. imdi,
taslak kodu aynen gsterildii gibi girin ve zm kurun. Projeyi altrmak iin Debug |
Start Without Debugging komutunu sein.
Dme Eklemek
Genel olarak, bir pencerenin ilevsellii iki tip e ile ifade edilir: Kontroller ve menler.
Kullanc bu eler aracl ile programnzla eklileebilir. Menler bu blmn ileriki
sayfalarnda anlatlmaktadr. Burada bir pencereye nasl kontrol ekleyebileceinizi
reneceksiniz.
Windows birok farkl tipte kontrol tanmlar. Bunlardan birkan sralayacak olursak,
dmeler, onay kutular, radyo dmeleri ve liste kutular bu kapsamda yer alr. Her kontrol
tipi farkl olmasna ragmen bunlarn tm az ok ayn ekilde alrlar. Burada, bir pencereye
bir dme ekleyeceiz. Fakat, dier kontrol tiplerini eklemek iin de ayn temel prosedr
kullanlabilir.
Button Snfnn Esaslar
Bir dme Button snf iinde paketlenmitir. Button, ButtonBase zet snfndan
kaltm yoluyla tretilir. Kendisi bir kontrol olduu iin Control snfnn ieriini kaltm
yoluyla elde eder. Buttonda yalnzca tek bir yaplandrc tanmldr:

HERKES N C#
KISIM III C#'I UYGULAMAYA GERMEK

742
public Button()
Bu, varsaylan bir bykle sahip ve pencere iinde bir konumu olan bir dme oluturur.
Bir dme kullanlmadan nce, sz konusu dmenin Text zeliine bir karakter katar atana-
rak dmeye bir tanm verilmesi gerekecektir.
Dmenin pencere iindeki konumunu belirtmek iin Location zelliine dmenin sol
st kesinin koordinatlarn atamalsnz. Location zellii kaltmla Controlden alnr ve
u ekilde tanmlanr:
public Point Location { get; set; }
Koordinatlar bir Point yaps iinde tutulur. Point, System.Drawing isim uzaynda
tanmldr. Point, iki zellik ierir:
public int X { get; set; }
public int Y { get; set; }
Bylece, Press Here tanmn ieren ve 100,200 konumuna yerletirilmi bir dme
oluturmak iin aadaki sekans kullann:
Button MyButton = new Button();
MyButton.Text = Press Here;
MyButton.Location = new Point(100, 200);
Bir Forma Dme Eklemek
Bir dme oluturduktan sonra bunu bir forma eklemelisiniz. Bunu, sz konusu forma
bal kontrollerden oluan koleksiyon zerinde Add() metodunu ararak yaparsnz. Bu
koleksiyon, Control snfndan kaltmla elde edilen Controls zellii araclyla
kullanlabilir. Add() metodu u ekilde tanmlanr:
public virtual void Add(Control kntl)
Burada kntl, eklenmekte olan kontroldr. Bir kez bir forma bir kontrol eklenince form
grntlendiinde artk kontrol de grntlenecektir.
Basit Bir Dme rnei
Aadaki program daha nce gsterilen taslaa bir dme ekler. u aamada dme bir
ie yaramaz, fakat formda mevcuttur ve tklanabilir.
// Bir dugme ekler.

using System;
using System.Windows.Forms;
using System.Drawing;

BLM 25: FORM TABANLI WNDOWS UYGULAMALARI GELTRMEK

HERKES N C#
743
class ButtonForm : Form {
Button MyButton = new Button();

public ButtonForm() {
Text = Using a Button;

MyButton = new Button();

MyButton.Text = Press Here;

MyButton.Location = new Point(100, 200);

Controls.Add(MyButton);
}

[STAThread]
public static void Main() {
ButtonForm skel = new ButtonForm();

Application.Run(skel);
}
}
Bu program. Formdan tretilen ButtonForm adnda bir snf oluturur. ButtonForm;
MyButton adnda, Button tipinde bir alan ierir. Yaplandrc iinde dme oluturulur,
dmeye ilk deer atanr ve dme forma eklenir. Program altrldnda ekil 25.2de
gsterilen pencereyi grntler. Dmeyi tklayabilirsiniz, fakat hibir ey meydana gelmez.
Dmenin bir eyler yapmasn salamak iin, bir sonraki konuda anlatld gibi bir mesaj
yneticisi eklemelisiniz.
Mesajlar Ynetmek
Bir programn tklanan bir dmeye yant vermesi (ya da dier herhangi tipte bir kontrol
etkileimi) iin sz konusu dme tarafndan retilen mesaj ele almas gereklidir. Genel
olarak, bir kullanc bir programla etkiletii zaman bu etkileimler sizin programnza mesaj
olarak aktarlr. Form tabanl bir C# programnda bu mesajlar olay yneticileri tarafndan
retilir. Bu nedenle, mesajlar almak iin, bir mesaj retildiinde arlan yneticiler listesine
programnz kendi olay yneticisini ekler. Bu, dme tklandnda retilen mesajlar asndan,
yneticinizi Click olayna eklemeniz anlamna gelir.
Click olay Button tarafndan tanmlanr. (Click, kaltmla Controlden elde edilir.)
Click aada gsterilen ekle sahiptir:
public Event EventHandler Click;


HERKES N C#
KISIM III C#'I UYGULAMAYA GERMEK

744


EKL 25.2: Bir dme eklemek.
EventHandler delegesi aadaki gibi tanmlanr:
public delegate void EventHandler(object kim, EventArgs arglar)
Sz konusu olay reten nesne kim zerinden aktarlr. Bu olayla ilintili tm bilgiler
arglar zerinden geirilir. Birok olay iin arglar, EventArgsdan tretilen bir snfn
nesnesi olacaktr. Dmeyi tklamak ek bilgi gerektirmedii iin, dmeyi ele alrken olay
argmanlarn dert etmemize gerek yoktur.
Aadaki program, nceki programdaki dmeye bir yant (tepki) kodu ekler. Dmenin
her tklan, dmenin konumunun deimesine neden olur.
// Dugme mesajlirini ele almak.

using System;
using System.Windows.Forms;
using System.Drawing;

class ButtonForm : Form {
Button MyButton = new Button();

public ButtonForm(} {
Text = Respond to a Button;

MyButton = new Button();
MyButton.Text = Press Here;
MyButton.Location = new Point(100, 200);

// Olay yoneticisini listeye ekle.
MyButton.Click += new EventHandler(MyButtonClick);

Controls.Add(MyButton);
BLM 25: FORM TABANLI WNDOWS UYGULAMALARI GELTRMEK

HERKES N C#
745
}

[STAThread]
public static void Main() {
ButtonForm skel = new ButtonForm();

Application.Run(skel);
}

// MyButton icin ynetici.
protected void MyButtonClick(object who, EventArgs e) {

if(MyButton.Top == 200)
MyButton.Location = new Point(10, 10);
else
MyButton.Location = new Point(100, 200);
}
}
Gelin, bu programdaki olay ynetimini gerekletiren koda yakndan bakalm. Dmenin
tklanmasyla ilikili olay yneticisi aada gsterilmitir:
// MyButton icin ynetici.
protected void MyButtonClick(object who, EventArgs e) {

if(MyButton.Top == 200)
MyButton.Location = new Point(10, 10);
else
MyButton.Location = new Point(100, 200);
}
MyButtonClick(), daha nce gsterilen EventHandler delegesi ile ayn imzay
kullanr. Bu, MyButtonClick()in de Click olay zincirine eklenebilecei anlamna gelir.
Metodun protected olarak nitelendiine dikkat edin. Bu teknik olarak gerekli deildir; fakat,
iyi bir fikirdir, nk olay yneticilerinin olaylara yant olarak kullanlmalarnn haricinde
arlmalar dnlmez.
Olay yneticisi iinde, dmenin st konumu Top zellii ile belirlenir. Tm kontroller
aadaki zellikleri tanmlar. Bu zellikler, sol st ve sa alt kelerin koordinatlarn belirtir.
Public int Top { get- set; }
public int Bottom { get; }
public int Left { get; set; }
public int Right { get ; }
Dikkat ederseniz, kontroln konumu Top ve Left ayarlanarak deitirilebilir: fakat,
Bottom ve Right ayarlanarak deitirilemez, nk bunlar salt okunur zelliklerdir. (Bir
kontroln bykln deitirmek iin Width ve Height zelliklerini kullanabilirsiniz.)
Dmenin tklanmas ile ilikili olay alnd zaman, kontrol eer orijinal 200
konumundaysa konum 10, 10 olacak ekilde deitirilir. Aksi halde, orijinal konumu olan 100,
200 noktasna dndrlr. Bu nedenle, dmeyi her tklaynzda dmenin konumu deiir.

HERKES N C#
KISIM III C#'I UYGULAMAYA GERMEK

746
MyButtonClick()in mesajlar alabiliyor olmas iin, dmenin Click olayna bal
olay yneticileri listesine kendisinin eklenmesi gereklidir. Bu, ButtonForm yaplandrcs
iinde aadaki ifade kullanlarak gerekletirilir:
MyButton.Click += new EventHandler(MyButtonClick);
Bu ilem tamamlandktan sonra, dmenin her ijklammda MyButtonClick() arlr.
Alternatif Uygulama
lgin bir husus udur: MyButtonClick() biraz farkl bir ekilde de yazlabilirdi.
Hatrlarsanz, bir olay yneticisinin kim parametresi, ary reten nesneye atfta bulunan bir
referans alr. Dme tklama olaynda bu, tklanan dmedir. Bu nedenle, MyButtonClick()
u ekilde de yazlabilirdi:
// Alternatif dugme yoneticisi.
protected void MyButtonClick(object who, EventArgs e) {
Button b = (Button) who;

if(b.Top == 200)
b.Location = new Point(10, 10);
else
b.Location = new Point(100, 200);
}
Bu versiyonda who, Button tipine dntrlr ve bu referans (MyButton alan yerine)
dme nesnesine erimek iin kullanlr. Bu rnekte bu yaklamn salad bir avantaj
olmamasna ramen, bunun olduka deerli olabilecei durumlar kolaylkla hayal edilebilir.
rnein, bu tr bu yaklam, herhangi spesifik bir dme iin bamsz bir dme olay yneti-
cisi yazlmasna olanak tanr.
Mesaj Kutusunun Kullanm
Windowsun en kullanl standart zelliklerinden biri mesaj kutusudur. Mesaj kutusu, bir
mesaj grntlemenize imkan veren, sistemde nceden tanml bir penceredir. Kullancdan
Evet, Hayr ya da Tamam gibi basit yantlar da alabilirsiniz. Forma dayal bir programda bir
mesaj kutusu MessageBox snf tarafndan desteklenir. Ancak, bu snfa ait bir nesne
oluturmazsnz.
Bunun yerine, bir mesaj kutusunu grntlemek iin MessageBox tarafndan tanmlanan
static metot Show()u arn.
Show() metodunun birka farkl kullanm mevcuttur. Bizim kullanacamz ekli aada
gsterilmitir:
public static DialogResult Show(string msj, string altyaz,
MsssageBoxButtons mbb)
BLM 25: FORM TABANLI WNDOWS UYGULAMALARI GELTRMEK

HERKES N C#
747
msj zerinden aktarlan karakter katar kutunun gvdesinde grntlenir. Mesaj kutusu
penceresinin ismi altyaz ile aktarlr. Grntlenecek olan dmeler mbb ile belirtilir.
Kullancnn yant dndrlr.
MessageBoxButtons aadaki deerleri tanmlayan bir numaralandrmadr:
AbortRetryIgnore OK OKCanccl
RetryCancel YesNo YesNocancel
Bu deerlerin her biri, bir mesaj kutusu iine dahil edilecek dmeleri tarif eder. rnein,
eer mbb YesNo deerini ieriyorsa, Yes ve No dmeleri mesaj kutusuna dahil edilir.
Show()un dndrd deer hangi dmenin basldn gsterir. Bu, u deerlerden biri
olacaktr:
Abort Cancel Ignore No
None OK Retry Yes
Programnz, kullancnn istedii eylemin biimini belirlemek amacyla dndrlen deeri
inceleyebilir. Sz gelii, mesaj kutusu bir dosyann zerine yazmadan nce kullancya haber
veriyorsa, kullanc Cancel dmesini (ptal) tklad takdirde programnz zerine yazma ile-
mini nleyebilir. Kullanc OK dmesini tklarsa zerine yazma ilemine izin verilebilir.
Aadaki program, nceki programa bir Stop dmesi ve bir mesaj kutusu ekler. Stop
dmesi yneticisinde, kullancya program durdurmak isteyip istemediini soran bir mesaj
kutusu grntlenir. Kullanc Evet dmesini tklarsa program durdurulur. Hayr dmesini
tklarsa program almaya devam eder.
// Stop dugmesi ekler

using System;
using System.Windows.Forms;
using System.Drawing;

class ButtonForm : Form {
Button MyButton;
Button StopButton;

public ButtonForm() {
Text = Adding a Stop Button;

// Dugmeleri olustur.
MyButton = new Button();
MyButton.Text = Press Here;
MyButton.Location = new Point(100, 200);

StopButton = new Button();
StopButton.Text = Stop;
StopButton.Location = new Point(100, 100);

// Dugme ile iliskili olay yoneticilerini pencereye ekle.
MyButton.Click += new EventHandler(MyButtonClick);

HERKES N C#
KISIM III C#'I UYGULAMAYA GERMEK

748
Controls.Add(MyButton);
StopButton.Click += new EventHandler(StopButtonClick);
Controls.Add(StopButton);
}

[STAThread]
public static void Main() {
ButtonForm skel = new ButtonForm();

Application.Run(skel);
}

// MyButton icin yonetici.
protected void MyButtonClick(object who, EventArgs e) {

if(MyButton.Top == 200)
MyButton.Location = new Point(10, 10);
else
MyButton.Location = new Point(100, 200);
}

// StopButton icin yonetici.
protected void StopButtonClick(object who, EventArgs e) {

// Kullanici Yes yanitini verirse, programi sona erdir.
DialogResult result = MessageBox.Show(Stop Program?,
Terminate,
MessageBoxButtons.YesNo);

if(result == DialogResult.Yes) Application.Exit();
}
}
Gelin imdi mesaj kutusunun nasl kullanldna yakndan bakalm. ButtonForm
yaplandrcs iine ikinci bir dme eklenmitir. Bu dme Stop metnini ierir ve bununla
ilgili olay yneticisi StopButtonClick()e balanr.
StopButtonClick() iinde mesaj kutusu aadaki ifade kullanlarak grntlenir:
// Kullanici Evet yanitini verirse, programi sona erdir.
DialogResult result = MessageBox.Show(Stop Program?,
Terminate,
MsssageBoxButtons.YesNo);
Burada kutunun iindeki mesaj Stop Program?dr. Kutunun ismi Terminate ve
grntlenecek dmeler Evet ve Hayrdr. Show() dndnde kullancnn yant
result'a atanr. Bu yant daha sonra eylemin biimini belirlemek iin aadaki kod
tarafndan incelenir:
if(result == DialogResult.Yes) Application.Exit();
BLM 25: FORM TABANLI WNDOWS UYGULAMALARI GELTRMEK

HERKES N C#
749
Kullanc eer Evet dmesini tklarsa program, Application.Exit() arlarak
durdurulur. Bu, programn derhal durdurulmasna neden olur. Aksi halde, bir eylem
gerekletirilmez ve program almaya devam eder.
rnek kt ekil 25.3te gsterilmitir.

EKL 25.3: Stop Dmesi programnn rnek kts.
Men Eklemek
Hemen hemen tm Windows uygulamalarnn ana penceresinin en stnde bir men yer
alr. Buna ana men denir. Ana men genellikle File, Edit ya da Tools gibi st dzey
kategoriler ierir. Ana menden aaya doru alan (drop down) menler inen Bu menler,
kategorilerle ilintili asl seenekleri ierirler. Bir men esi seildiinde bir mesaj retilir. Bu
nedenle, bir men seimini ilemek iin programnz her men esine bir olay yneticisi
atayacaktr.
Bir ana men iki snfn bileimiyle kurulur. Bunlardan birincisi MainMenudr.
MainMenu, mennn btn yapsn snf iine paketler. kincisi, yalnzca tek bir seimi snf
iine paketleyen MenuItemdr. Bir men seimi ya Close gibi nihai bir eylemi simgeler ya da
bir baka alan meny etkin klar. MainMenu ve MenuItemn her ikisi de Menu snfndan
kaltmla tretilir. Menler, Windows programlamada temel bir kaynak olduklar iin,
menlerle ilgili pek ok seenek mevcuttur ve men konusu olduka genitir. Neyse ki,
standart bir ana men oluturmak kolaydr.
Bir men esi seildiinde bir Click olay retilir. Click, MenuItem tarafndan
tanmlanr. Bu nedenle, programnz bir men seimini ele almak iin bu e ile ilikili Click
olay listesine kendi yneticisini ekleyecektir.
Her form u ekilde tanmlanan bir Menu zelliine sahiptir:

HERKES N C#
KISIM III C#'I UYGULAMAYA GERMEK

750
public MainMenu Menu { get; set; }
Bu zellie varsaylan deer olarak bir men atanmaz. Bir men esini grntlemek iin
bu zellik, sizin oluturduunuz menye ayarlanmaldr.
Bir ana men oluturmak basittir, fakat birka adm ierir:
1. Bir MainMenu nesnesi oluturun.

2. MainMenu nesnesine st dzey kategorileri tarif eden MenuItems ekleyin. Bu men
eleri, ana men ile ilikili MenuItems koleksiyonuna eklenir.

3. Her st dzey MenuItemna, bu st dzey e ile ilikili alan menleri tarif eden
MenuItems listesi ekleyin. Bu men eleri, her st dzey men ile ilikili
MenuItems koleksiyonuna eklenir.

4. Her seenek iin olay yneticilerini ekleyin.

5. MainMenu nesnesini formla ilikili Menu zelliine atayn.
Aadaki sekans, seenek ieren bir File mensnn nasl oluturulduunu
gstermektedir. Seenekler Open, Close ve Exittir.
// Ana menu nesnesi olusturun.
MainMenu MyMenu = new MainMenu();

// Menuye ust dzey menu ogesi ekleyin.
MenuItem m1 = new MenuItem(File);
MyMenu.MenuItems.Add(m1);

// File icin bir alt menu olusturun.
MenuItem subm1 = new MenuItem(Open);
m1.MenuItems.Add(subm1);

MenuItem subm2 = new MenuItem(Close);
m1.MenuItems.Add(subm2);

MenuItem subm3 = new MenuItem(Exit);
m1.MenuItems.Add(subm3);
imdi bu sekans ok dikkatli inceleyelim. Sekans, MyMenu adnda bir MainMenu nesnesi
oluturarak balamaktadr. Bu nesne, men yaps iinde en stte olacaktr. Sonra, m1 adnda
bir men esi oluturulur. Bu, dosya baldr. Dorudan ana menye eklenir ve st dzey
seenek konumunu alr. Sonra, File ile ilintili alan men oluturulur. Bu men elerinin File
men esi olan m1e eklendiine dikkat edin. Bir MenuItem bir dierine eklendiinde
eklenen e, eklendii e ile ilikili alan mennn bir paras olur. Bylece, subm1den
subm3e kadarki eler m1eklendikten sonra File semek Open, Close ve Exiti ieren bir
alan mennn ekranda grntlenmesine neden olur.
BLM 25: FORM TABANLI WNDOWS UYGULAMALARI GELTRMEK

HERKES N C#
751
Men oluturulur oluturulmaz her e ile ilikili olay yneticilerine de deerleri atanmal-
dr. Daha nce akland gibi, seim yapan bir kullanc bir Click olay retir. Bu nedenle,
aadaki sekans subm1den subm3e kadar yneticilere deer atamaktadr:
// Menu geleri icin olay yoneticileri ekle.
subm1.Click += new EventHandler(MMOpenClick);
subm2.Click += new Eventnandler(MMCloseClick);
subm3.Click += new EvantHandler(MMExitClick);
Bu yzden, kullanc eer Exiti seerse, MMExitClick() altrlr.
Son olarak, MainMenu nesnesi, aada gsterildii gibi, formun Menu zelliine
atanmaldr:
Menu = MyMenu;
Bu atama gereklendikten sonra, pencere oluturulduunda sz konusu men grntlene-
cektir ve tercihler doru yneticiye gnderilecektir.
Aadaki program tm paralar birletirir ve bir ana mennn nasl oluturulacan ve
men seeneklerinin nasl ele alnacan gsterir:
// Ana menu ekler.

using System;
using System.Windows.Forms;

class MenuForm : Form {
MainMenu MyMenu;

public MenuForm() {
Text = Adding a Main Menu;

// Bir ana menu nesnesi olusturun.
MyMenu = new MainMenu();

// Menuye ust dzey ogeler ekleyin.
MenuItem m1 = new MenuItem(File);
MyMenu.MenuItems.Add(m1);

MenuItem m2 = new MenuItem(Tools);
MyMenu.MenuItems.Add(m2);

// File icin bir alt menu olusturun
MenuItem subm1 = new MenuItem(Open);
m1.MenuItems.Add(subm1);

MenuItem subm2 = new MenuItem(Close);
m1 .MenuItems.Add(subm2);

MenuItem subm3 = new MenuItem(Exit);
m1.MenuItems.Add(subm3);


HERKES N C#
KISIM III C#'I UYGULAMAYA GERMEK

752
// Tools icin bir alt menu olusturun.
MenuItem subm4 = new MenuItem(Coordinates);
m2.MenuItems.Add(subm4);

MenuItem subm5 = new MenuItem(Change Size);
m2.MenuItems.Add(subm5);

MenuItem subm6 = new MenuItem(Restore);
m2.MenuItems.Add(subm6);

// Menu ogeleri icin yoneticiler ekleyin.
subm1.Click += new EventHandler(MMOpenClick);
subm2.Click += new EventHandler(MMCloseClick);
subm3.Click += new EventHandler(MMExitClick);
subm4.Click += new EventHandler(MMCoordClick);
subm5.Click += new EventHandler(MMChangeClick);
subm6.CIick += new EventHandler(MMRestoreClick);

// Menuyu forma ekleyin.
Menu = MyMenu;
}

[STAThread]
public static void Main() {
MenuForm skel = new MenuForm();

Application.Run(skel);
}

// Ana menudeki Coordinates secimi icin yonetici.
protected void MMCoordClick(object who, EventArgs e) {
// Koordinatlari iceren bir karakter katari olusturun.
string size =
String.Format({0}: {1}, {2}\n{3}: {4}, {5},
Top, Left, Top, Left,
Bottom, Right, Bottom, Right);

// Bir mesaj kutusu goruntuleyin.
MessageBox.Show(size, Window Coordinates,
MessageBoxButtons.OK);
}

// Ana menudeki Change secimi icin yonetici.
protected void MMChangeClick(object who, EventArgs e) {
Width = Height = 200;
}

// Ana menudeki Restore secimi icin yonetici.
protected void MMRestoreClick(object who, EventArgs e) {
Width = Height = 300;
}

// Ana menudeki Open secimi icin yonetici.
protected void MMOpenClick(object who, EventArgs e) {

BLM 25: FORM TABANLI WNDOWS UYGULAMALARI GELTRMEK

HERKES N C#
753
MessageBox.Show(Inactive, Inactive,
MessageBoxButtons.OK);
}

// Ana menudeki Close secimi icin yonetici.
protected void MMCloseClick(object who, EventArgs e) {

MessageBox.Show(Inactive, Inactive,
MessageBoxButtons,OK);
}

// Ana menudeki Exit secimi icin yonetici.
protected void MMExitClick(object who, EventArgs e) {

DialogResult result = MessageBox.Show(Stop Program?,
Terminate,
MessageBoxButtons.YesNo);

if(result == DialogResult.Yes) Application.Exit();
}
}
rnek kt ekil 25.4te gsterilmitir.
Bu programda iki alan men tanmlanmaktadr. Bunlardan ilki File mens ile eriilir.
Bu men Open, Close ve Exit seeneklerini ierir. Open ve Close ile ilikili men yneticileri,
ekranda bir mesaj kutusu grntlemekten baka bir ilevi olmayan yalnzca birer yer
gstericisidir. Close yneticisi program durdurmak isteyip istemediinizi sorar. Evet yantn
verirseniz, program sonlandrlr.


EKL 25.4: Men programnn rnek kts.
Tools menusu seenek ierir: Coordinates, Change Size ve Restore. Coordinatesin
seilmesi, bir mesaj kutusu iinde grntlenecek pencerenin sol st ve sa alt kelerinin

HERKES N C#
KISIM III C#'I UYGULAMAYA GERMEK

754
koordinatlarnn grntlenmesine neden olur. Pencereyi tayp, koordinatlarn grntlemeyi
deneyin. Pencere ne zaman yeni bir konuma tansa koordinatlar deiir.
Change Size seildiinde pencerenin boyutlarnn, eni ve boyu 200 piksel uzunluunda
olacak ekilde kltlmesine neden olur. Bu, aada gsterilen Width ve Height zellikleri
araclyla gerekletirilir:
public int width { get; set; }
public int Height { get; set; }
Form tabanl bir pencerenin varsaylan boyutu 300x300dr. Restore seilerek pencere
varsaylan boyutuna dndrlr.
imdi Ne Yapabilirsiniz?
Balarken bildirildii gibi Windows programlama ok geni bir konudur. Formlar
kukusuz bu sreci standardize ediyor olsa da, sizin yaklamnz ne ekilde olursa olsun bu
dorudur. Windows, programclardan nemli taleplerde bulunan zengin zelliklere sahip bir
ortamdr. Windows programlamaya yeni balyorsanz, Windowsun eitli alt sistemlerini
renmek iin birka hafta harcayacanz umabilirsiniz. almaya
System.Windows.Forms iinde tanml kontrollerden balayabilirsiniz. Aynca, Windowsun
ska kullanlan mesajlarndan birkan, sz gelii bir pencerenin yeniden izilmesi isteminde
bulunan bir mesaj gibi, nasl ele alacanz da renmeniz gerekecektir. Bir dier nemli alt
sistem System.Drawingde yer alr. System.Drawing, ktnn pencere iinde nasl
grntlendiini kontrol eden eitli snflar tanmlar. System.Drawing, Windows GDI
(Grafik Cihaz Arayz - Graphics Device Interface) tarafndan salanan ilevsellii snf iine
paketler. Birok ksa program yazmay deneyin; her yeni seenek ya da teknikle ilintili olarak
bu programlarn her birinin tam davrann ve nasl grndn gzleyin.



Y R M A L T I N C I B L M


YNELENEREK NEN BR
DEYM AYRITIRICISI





















26

HERKES N C#
KISIM III C#'I UYGULAMAYA GERMEK

756
(10 - 59) *3 gibi bir nmerik deyim ieren bir karakter katarn girdi olarak alan ve
duru yant hesaplayan bir program nasl yazarsnz? Programclarn arasnda hala
programcln piri kavram kaldysa, bunlar, bu iin nasl yapldn bilen az sayda kii
olmaldr. Bu konu haricinde becerikli birok programc, yksek dzeyli bir dilin, cebirsel
deyimleri bir bilgisayarn altrabilecei komutlara dntrme eklinden hayrete derler.
Bu prosedre deyim ayrtrma (expression parsing) denir ve bu, tm dil derleyicilerinin ve
yorumlayclarnn, elektronik formlarn ve nmerik deyimleri bir bilgisayarn kullanabilecei
bir forma dntrmeyi gerektiren her trl eyin omurgasn oluturur.
Yeni balayanlar iin gizemli gelse de deyim ayrtrma, olduka zarif bir zm sunan net
olarak tanmlanm bir grevdir. Bunun nedeni, deyim ayrtrma ileminin kat cebir kuralla-
rna gre alyor olmasdr. Bu blmde, ounlukla yinelenerek inen ayrtrc (recursive-
descent parser) olarak bilinen bir ayrtrc gelitirilmektedir. Ayrca, nmerik deyimleri
hesaplamanz mmkn klan gerekli tm destek rutinleri de gelitirilmektedir. Ayrtrcnn
ileyii zerinde uzmanlatktan sonra bunu kendi ihtiyalarnza uyacak ekilde kolayca
gelitirip, deitirebilirsiniz.
Burada gelitirilen ayrtrc, kendi bana yararl bir kod paras olmasnn yan sra,
ayrca ikinci bir amaca da hizmet eder: C# dilinin gcn ve menzilini gzler nne serer. Bir
ayrtrc bir saf kod uygulamasdr. Bir GUI olarak aa arayz olmaz ya da snrl sistem
kaynaklarndan yararlanmaz. Bu, gemite normal olarak C++ta yazlacak trde bir koddur.
Bir ayrtrcnn C# kullanlarak kolaylkla oluturulabilir olmas gerei, C#n her trl prog-
ramlama grevi iin uygun olduunu kantlamaktadr.
Deyimler
Bir deyim ayrtrcs cebirsel bir deyimin deerini hesaplad iin bir deyimi oluturan
paralar anlamanz nemlidir. Deyimler her trde bilgiden oluturulabilir olsalar da, bu
blmde yalnzca nmerik deyimler ele alnmaktadr. Kendi amacmz asndan nmerik
deyimler aadaki elerden oluur:
Saylar
Operatrler +, -, /, *, ^, %, =
Parantezler
Deikenler
Burada karet operatr (^) stel ilemleri (ayn operatrn C#taki XOR ilevi ile
kartrmayn) iaret eder. Eittir iareti (=) de atama operatrdr. Bu eler, deyimler iinde
cebir kurallarna gre birletirilebilirler. te birka rnek:
10 - 8
(100 - 5) * 14 / 6
a + b - c
10 ^ 5
a = 10 - b
BLM 26: YNELENEREK NEN BR DEYM AYRITIRICISI

HERKES N C#
757
Her operatrn u ekilde ncelii olduunu varsayn:
en yksek + - (tekli)
^
* / %
+ -
en dk =
Eit ncelik srasna sahip operatrler soldan saa doru hesaplanrlar.
Bu blmde gelitirilen ayrtrc birka kstlamaya tabi tutulacaktr. ncelikle, tm
deikenler tek harften oluur (bir baka deyile, Adan Zye 26 deiken sz konusudur).
Deikenlerde byk-kk harf ayrm yaplmaz (a ve A ayn deiken olarak ele alnr).
kincisi, tm nmerik deerlerin double olduu varsaylr. Ayrtrcy kukusuz dier deer
tiplerini ele alacak ekilde deitirmeniz mmkndr. Son olarak, ayrtrcnn mantn net
ve kolay anlalr tutmak iin yalnzca temel dzeyde hata kontrol dahil edilmitir.
Deyimleri Ayrtrmak: Problem
Deyim ayrtrma problemi hakknda ok fazla dnmemiseniz, bunun basit bir i
olduunu farz edebilirsiniz, fakat deildir. Problemi daha iyi anlamak iin u rnek deyimi
hesaplamay deneyin:
10 - 2 * 3
Bu deyimin 4 deerine eit olduunu biliyorsunuz. Bu spesifik deyimi hesaplayacak bir
program kolaylkla oluturabilirsiniz. Ancak asl problem, herhangi keyfi bir deyim iin doru
yant veren bir programn nasl oluturulacadr. lk nce u tr bir rutin dnebilirsiniz:
a = ilk operandi al
while(operand mevcut ise) {
op = operatoru al
b = ikinci operandi al
a = a op b
}
Bu rutin, ilk ilemi gerekletirmek iin birinci operand, operatr ve ikinci operand alr.
Sonra, bir sonraki ilemi gerekletirmek iin bir sonraki operatr ve operand alr vs. Ancak,
bu temel yaklam kullanrsanz eer, 10 - 2 * 3 deyimi 4 yerine 24 (yani, 8 * 3) olarak
hesaplanr, nk bu prosedr, operatrlerin ncelik srasn dikkate almamaktadr. Operandlar
ve operatrleri soldan saa doru hesaplayamazsnz, nk cebir kurallar arpmann
kartmadan nce yaplmasn dikte ekmektedir. Yeni balayanlarn bir ksm bu problemin
kolaylkla stesinden gelinebileceini dnrler; bazen ok snrl durumlarda gelinebilir de.
Ancak, parantezleri, stel ifadeleri, deikenleri, tekli operatrleri ve benzerini eklerseniz
problem yalnzca daha da ktye gider.
Deyimleri hesaplayan bir rutin yazmann ok sayda yolu olsa da, burada gelitirilen, birisi
tarafndan yazlabilecek en kolay yaklamdr. Bu yaklam yinelenerek inen ayrtrc

HERKES N C#
KISIM III C#'I UYGULAMAYA GERMEK

758
(recursive-descent parser) olarak adlandrlr. Bu blmn ak iinde bu yaklamn isminin
nereden geldiini anlayacaksnz. (Ayrtrc yazmak iin kullanlan dier metotlardan bazlar,
bir baka bilgisayar program tarafndan retilmesi gereken karmak tablolar kullanrlar.
Bunlara kimi zaman tablo gdml (table-driven) ayrtrc da denir.)
Bir Deyimi Ayrtrmak
Bir deyimi ayrtrmann ve hesaplamann bir ok yolu mevcuttur. Yinelenerek inen bir
ayrtrc asndan deyimleri, yinelenen veri yaplar - yani, kendi kendilerince tanmlanan
deyimler olarak dnn. imdilik deyimlerin yalnzca +, -, *, / ve parantezleri kullandn
varsayarsak, tm deyimler aadaki kurallara gre tanmlanabilir:
deyim -> terim [+ terim] [- terim]
terim -> faktr [* faktr] [/ faktr]
faktr -> deiken, say ya da (deyim)
Keli parantezler istee bal bir eleman iaret eder; -> iareti ise retir anlamna gelir.
Aslnda bu kurallar genellikle deyim retim kurallar olarak adlandrlr. Bu nedenle, terimin
tanmn u ekilde ifade edebilirsiniz: Terim, faktr arp faktr ya da faktr bl faktr sonu-
cunu retir. Dikkat ederseniz, operatrlerin ncelik sras, deyimin tanmlanma eklinde gizli-
dir.
10 + 5 * B
Yukardaki deyim iki terime sahiptir: 10 ve 5 * B. kinci terim iki faktr ierir: 5 ve B. Bu
faktrler bir say ve bir de deikenden ibarettir. te yandan, u deyim iki faktre sahiptir:
14 * (7 - C)
Bu faktrler 14 ve (7 - C)dir. Faktrler br say ve bir de parantez iine alnm bir
deyimden oluur. Parantez iine alnm deyim iki terim ierir: Bir say ve bir deiken.
Bu sre, yinelenerek inen bir ayrtrcnn temelini oluturur. Yinelenerek inen bir
ayrtrc, zincirleme bir dzende alan ve retim kurallarn uygulayan, karlkl yinelenen
metotlar btndr. Ayrtrc, her uygun admda, belirtilen ilemleri cebirsel olarak doru
sekansta gerekletirir. retim kurallarnn bir deyimi ayrtrmak iin nasl kullanldn
anlamak amacyla gelin imdi aadaki deyimi kullanarak bir rnek zerinden gidelim:
9/3-(100 + 56)
te takip edeceiniz admlar:
1. lk terimi aln: 9/3.

2. Faktrlerin her birini aln ve tamsaylar bln. Elde edilen sonu 3tr.

3. kinci terimi aln: (100 + 56). Bu noktada, ikinci alt deyimi yineleyerek analiz
etmeye balayn.

4. Terimlerin her birini atn ve toplayn. Elde edilen sonu 156dr.
BLM 26: YNELENEREK NEN BR DEYM AYRITIRICISI

HERKES N C#
759

5. Yinelen ardan dnn ve 156y 3ten karn. Yant 153tr.

Bu noktada aklnz biraz kartysa kendinizi kt hissetmeyin. Bu, almas biraz zaman
alan olduka karmak bir kavramdr. Deyimlerin bu yinelenen grntsnden hatrlamanz
gereken iki temel husus vardr. Birincisi, operatrlerin ncelik sralar retim kurallarnn
tanmlanma eklinde gizlidir. kincisi, deyimleri bu ekilde ayrtrmak ve hesaplamak, biz
insanlarn matematiksel deyimleri hesaplamamza ok benzemektedir.
Bu blmn geri kalannda iki ayrtrc gelitirilmektedir. lki, yalnzca literal
deerlerden oluan double tipinde kayan noktal deyimleri ayrtrp, hesaplayacaktr. Bu
ayrtrc, yinelenerek inen ayrtrma metodunun esaslarn gzler nne serer. ikinci
ayrtrc ise deiken kullanma becerisini ekler.
Bir Deyimi Paralara Ayrmak
Bir deyimin deerini hesaplamak iin sz konusu deyimin bileenlerini ayrtrcya ayr
ayr beslemek gereklidir. rnein, u deyim
A * B (W + 10)
ayr ayr u blmleri ierir: A, *, B, -, (, w, +, 10 ve ). Ayrtrma dilinde bir deyimin her
bileenine simge (token) denir ve her simge deyimin ayr bir birimini temsil eder. Bir deyimi
simgeselletirme, ayrtrmann temelidir. Bu nedenle, ayrtrcnn kendisini incelemeden nce
gelin simgeselletirmeye gz atalm.
Br deyimi simgelere ayrmak iin deyimin bandan balayp sonuna kadar tek tek
ilerleyerek srayla karlk gelen simgeleri dndren bir metoda ihtiyacnz vardr. Metot ayrca
boluklar atlayabilmeli ve deyimin sonunu alglayabilmelidir. Burada gelitirilen ayrtrcda
bu grevi gren metot GetToken() olarak adlandrlmtr.
Bu blmdeki her iki ayrtrc da Parser snf iine pakellenmilerdir. Bu snf daha
sonra ayrntl olarak ele alnacak olsa da, GetToken()n nasl altn aklayabilmek iin
sz konusu snfn ilk blmnn gsterilmesi gereklidir Parser, aada gsterilen
numaralandrmalar ve alanlar tanmlayarak balar:
class Parser {
// Simge tiplerini numaralandir..
enum Types { NONE, DELIMITER, VARIABLE, NUMBER };
// Hata tiplerini numaralandir..
enum Errors { SYNTAX, UNBALPARENS, NOEXP, DIVBYZERO };

string exp; // deyimi tutan karakter katarini gosterir
int expIdx; // deyim icindeki mevcut indeks
string token; // mevcut simgeyi tutar
Types tokType; // simgenin tipini tutar

HERKES N C#
KISIM III C#'I UYGULAMAYA GERMEK

760
Parser iki numaralandrma tanmlayarak balar. Birincisi Typesdr. Bir deyimi
ayrtrrken bir simge ounlukla bir tip ile ilikilendirilir. Bu blmde gelitirilen ayrtrclar
iin yalnzca tip gereklidir: deiken, say ve snrlayc (delimiter), Bunlar Types
numaralandrmas tarafndan tanmlanan VARIABLE, NUMBER ve DELIMITER deerleri ile
simgelenirler. DELIMITER kategorisi hem operatrler hem de parantezler iin kullanlr. NONE
tipi yalnzca tanmsz bir simge iin bir yer gstericisidir. Errors numaralandrmas eitli
ayrtrma hatalarn simgeler.
Ayrtrlmakta olan deyimi tutan karakter katarna atfta bulunan referans exp iinde
saklanr. Dolaysyla, exp 10+4 gibi bir karakter katarna atfta bulunacaktr. Sz konusu
karakter katar iindeki bir sonraki semboln indeksi expIdx iinde tutulur. expIdxin ilk
deeri sfrdr. Elde edilen simge token iinde; tipi ise tokType iinde saklanr.
Ayrtrc tarafndan kullanlan GetToken() metodu aada gsterilmitir. Bu metot ne
zaman arlsa, expIdxten balayarak, exp tarafndan atfta bulunulan karakter katar iindeki
deyimde yer alan bir sonraki sembol elde eder. Baka bir ifadeyle, GetToken() ne zaman
agnlsa, exp[expIdx]teki bir sonraki sembol alr. Metot daha sonra bu sembol token
alanna yerletirir. Semboln tipini de tokTypea yerletirir. GetToken(), isDelim()
metodunu kullanr. Bu metot da aada gsterilmitir:
// Bir sonraki sembolu elde et.
void GetToken()
{
tokType = Types.NONE;
token = ;

if(expIdx == exp.Length) return; // deyimin sonu

// bosluklari atla
while(expIdx < exp.Length &&
Char.IsWhiteSpace(exp[expIdx])) ++expIdx;

/* deyimin sonundaki bosluklar ve gorunmeyen karakterler
deyimi sonlandirir */
if[expIdx == exp.Length) return;

if(IsDelim(exp[expIdx])) { // operator mu?
token += exp[expIdx];
expIdx++;
tokType = Types.DELIMITER;
}
else if(Char.IsLetter(exp[eXpIdx])) { // degisken mi?
while(!IsDelim(exp[expIdx])) {
token += exp[expIdx];
expIdx++;
if(expIdx >= exp.Length) break;
}
tokType = Types.VARIABLE;
}
else if(Char.IsDigit(exp[expIdx])) { // sayi mi?
BLM 26: YNELENEREK NEN BR DEYM AYRITIRICISI

HERKES N C#
761
while(IsDelim(exp[expIdx])) {
token += exp[expIdx];
expIdx++;
if(expIdx >= exp.Length) break;
tokType = Types.NUMBER;
}
}

// c bir sinirlandirici ise true dondur.
bool IsDelim(char c)
{
if(( +-/*%^=(), IndexOf(c) != -1))
return true;
return false;
}
GetToken()a yakndan gz atn. lk birka deer atamadan sonra GetToken(), deyimin
sonuna ulalp ulalmadn belirlemek iin expIdxin exp.Lengthe eit olup olmadn
kontrol eder. expIdx incelenmekte olan deyimin indeksi olduu iin eer o, deyimi tutan
karakter katarnn uzunluuna eitse deyim tamamyla ayrtrlmtr.
Eer deyimden alnmas gereken daha hala simge varsa, GetToken() nce bataki
boluklar atlar. Boluklar atlandktan sonra exp[expIdx] artk ya bir rakam, bir deiken, bir
operatr ya da deyimi sondaki boluklar sonlandryorsa bir boluk ierir. Bir sonraki karakter
eer bir operatr ise bu, token iinde bir karakter katar olarak dndrlr ve DELIMITER,
tokType iinde saklanr. Eer bir sonraki karakter bir harf ise, bu, deikenlerden biri olarak
kabul edilir. token iinde bir karakter katar olarak dndrlr ve tokTypea VARIABLE
deeri atanr. Bir sonraki karakter bir rakam ise btn say okunur ve karakter katar ekliyle
tokenda saklanr. Tipi NUMBERdr. Son olarak, eer karakter bunlarn hibiri deilse, token
bir null karakter katar ierecektir.
GetToken()un kodunun anlalrln korumak iin belirli miktar hata kontrol
atlanmtr ve birtakm varsaymlarda bulunulmutur. Sz gelii, nnde bir boluk olmas
kaydyla tannmayan herhangi bir karakter deyimi sona erdirebilir. Ayrca, bu versiyonda
deikenler herhangi uzunlukta olabilir, fakat yalnzca ilk harfleri nem tar. Sizin spesifik
uygulamanza bal olarak daha fazla hata kontrol ya da dier ayrntlar ekleyebilirsiniz.
GetToken()n nasl altn daha iyi anlamak iin u deyimi ele aln:
A + 100 - (B * C) / 2
Bu deyim simgeselletirildiinde GetToken() aadaki simgeleri ve simge tiplerini elde
eder:
Simge Simge tipi
A VARIABLE
+ DELIMITER
100 NUMBER
- DELIMITER

HERKES N C#
KISIM III C#'I UYGULAMAYA GERMEK

762
( DELIMITER
B VARIABLE
* DELIMITER
C VARIABLE
) DELIMITER
/ DELIMITER
2 NUMBER
unu hatrnzda tutun: token yalnzca tek bir karakter ierse bile daima bir karakter katar
tutar.
Basit Bir Deyim Ayrtrcs
te, ayrtrcnn ilk versiyonu. Bu. yalnzca literal, operatr ve parantezlerden oluan
deyimlerin deerini hesaplayabilir. GetToken() deikenleri ileyebiliyor olsa da
ayrtrcnn bunlarla bir ii yoktur. Bu basitletirilmi ayrtrcnn nasl altn bir kez
anladktan sonra deikenleri ele alma becerisini de ekleyeceiz.
/*
Bu nodul, degiskenleri kullanmayan,
yinelenerek inen bir ayristirici icerir.
*/

using System;

// Ayristirici hatalari icin kural disi durum sinifi.
class Parser(Exception : ApplicationException {
public ParserException(string str) : base(str) { }

public override string ToString() {
return Message;
}
}

class Parser {
// Simge tiplerini numaralandir..
enum Types { NONE, DELIMITER, VARIABLE, NUMBER };
// Hata tiplerini numaralandir..
enum Errors { SYNTAX, UNBALPARENS, NOEXP, DIVBYZERO };

string exp; // deyimi tutan karakter katarini gosterir
int expIdx; // deyim icindeki mevcut indeks
string token; // mevcut simgeyi tutar
Types tokType; // simgenin tipini tutar

// Ayristiricinin giris noktasi.
public double Evaluate(string expstr)
{
double result;

exp = expstr;
expIdx = 0;

BLM 26: YNELENEREK NEN BR DEYM AYRITIRICISI

HERKES N C#
763
try {
GetToken();
if(token == ) {
SyntaxErr(Errors.NOEXP); // Deyim mevcut degil
return 0.0;
}

EvalExp2(out result);

if(token != ) // son simge null olmali
SyntaxErr(Errors.SYNTAX);

return result;
} catch (ParserException exc) {
// istege gore baska bir hata yonetimi ekle.
Console.WriteLine(exc);
return 0.0;
}
}

// iki terimi ekle ya da cikart.
void EvalExp2(out double result)
{
string op;
double partialResult;

EvalExp3(out result);
while((op = token) == + || op == -) {
GetToken ();
EvalExp3(out partialResult);
switch(op) {
case -:
result = result - partialResult;
break;
case +:
result = result + partialResult;
break;
}
}
}

// Iki faktoru carp ya da bol.
void EvalExp3(out double result)
{
string op;
double partialResult = 0.0;

EvalExp4(out result);
while((op = token) == * ||
op == / || op == %) {
GetToken();
EvalExp4(out partialResult);
switch(op) {
case *;
result = result * partialResult;

HERKES N C#
KISIM III C#'I UYGULAMAYA GERMEK

764
break;
case /:
if(partialResult == 0.0)
SyntaxErr(Errors.DIVBYZERO);
result = result / partialResult;
break;
case %:
if(partialResult == 0.0)
SyntaxErr(Errors.DIVBYZERO);
result = (int) result % (int) partialResult;
break;
}
}
}

// Ustel ifadeyi hesapla.
void EvalExp4 (out double result)
{
double partialResult, ex;
int t;

EvalExp5(out result);
if(token == ^) {
GetToken();
EvalExp4(out partialResult);
ex = result;
if(partialResult == 0.0) {
result = 1.0;
return;
}
for(t=(int)partialResult-1; t > 0; t--)
result = result * (double)ex;
}
}

// Tekli + ya da -nin degerini hesapla.
void EvalExp5(out double result)
{
string op;

op = ;
if((tokType == Types.DELIMITER) &&
token == + || token == -) {
op = token;
GetToken();
}

EvalExp6(out result);
if(op == -) result = -result;
}

// Parantez iindeki deyimi hesapla.
void EvalExp6(out double result)
{
if((token == ()) {
BLM 26: YNELENEREK NEN BR DEYM AYRITIRICISI

HERKES N C#
765
GetToken();
EvalExp2(out result);
if(token != ))
SyntaxErr(Errors.UNBALPARENS);
GetToken();
}
else Atom(out result);
}

// Bir sayinin degerini al.
void Atom(out double result)
{
switch(tokType) {
case Types.NUMBER:
try {
result = Double.Parse(token);
} catch (FormatException) {
result = 0.0;
SyntexErr(Errors.SYNTAX);
}
GetToken();
return;
default:
result = 0.0;
SyntaxErr(Errors.SYNTAX);
break;
}
}

// Soz dizimi hatasini kontrol altina al.
void SyntaxErr(Errors error)
{
string[] err = {
Syntax Error,
Unbalanced Parentheses,
No Expression Present,
Division by Zero
};

throw new ParserException(err[(int)error));
}

// Bir sonraki sembolu elde et.
void GetToken()
{
tokType = Types.NONE;
token = ;

if(expIdx == exp.Length) return;
// deyim sonu ise bosluklari ve gorunmeyen karakterleri atla
while(expIdx < exp.Length &&
Char.IswhiteSpace(exp[expIdx])) ++expIdx;

/* deyimin sonundaki bosluklar ve gorunmeyen karakterler
deyimi sonlandirir */

HERKES N C#
KISIM III C#'I UYGULAMAYA GERMEK

766
if(expIdx == exp.Length) return;

if(IsDelim(exp[expIdx])) { // operator mu?
token += exp[expIdx];
expIdx++;
tokType = Types.DELIMITER;
}
else if(Char.IsLetter(exp[expIdx])) { // degisken mi?
while(!IsDelim(exp[expIdxl)) {
token += exp[expIdx];
expIdx++;
if(expIdx >= exp.Length) break;
}
tokType = Types.VARIABLE;
}
else if(Char.IsDigit(exp[expIdx])) { // sayi mi?
while(!IsDelim(exp[expIdx])) {
token += exp[expIdx];
expIdx++;
if(expIdx >= exp.Length) break;
}
tokType = Types.NUMBER;
}
}

// c bir sinirlandirici ise true dondur.
bool IsDelim(char c)
{
if(( +-/*%^=().IndexOf(c) != -1))
return true;
return false;
}
}
Grld gibi ayrtrc, u operatrleri ele alabilmektedir: +, -, *, / ve %. laveten, stel
tamsay operatrn (^) ve tekli eksi operatrn de ele alabilmektedir. Ayrtrc ayrca
parantezlerle de doru biimde ilgilenebilir.
Ayrtrcy kullanmak iin ncelikle Parser tipinde bir nesne oluturun. Sonra,
deerinin hesaplanmasn istediiniz deyimi tutan karakter katarn argman olarak aktararak
Evaluate()i arn. Evaluate() sonucu dndrr. Aadaki program ayrtrcy
gstermektedir:
// Ayristiriciyi gosterir.

using System;

class ParserDemo {
public static void Wain() {
{
string expr;
Parser p = new Parser();

Console.WriteLine(Enter an empty expression to stop.);
BLM 26: YNELENEREK NEN BR DEYM AYRITIRICISI

HERKES N C#
767

for(;;) {
Console.Write(Enter expression: );
expr = Console.ReadLine();
if(expr == ) break;
Console.WriteLine(Result: + p.Evaluate(expr));
}
}
}
te rnek kt:
Enter an empty expression to stop.
Enter expression: 10.2*3
Result: 4

Enter expression: (l0-2)*3
Result: 24

Enter expression: 10/3.5
Result: 2.85714285714286
Ayrtrcy Anlayalm
Gelin imdi, Parsera ayrntl olarak gz atalm. GetToken() anlatlrken de
bahsedildii gibi, Parser drt zel alan iermektedir. Sonucu hesaplanacak deyimi ieren
karakter katar exp ile gsterilir. Evaluate()e yaplan her arda bu alan ayarlanr.
Ayrtrcnn, standart C# karakter katarlarnda saklanan deyimleri hesapladn hatrnzda
tutmak nemlidir. rnein, aadaki karakter katarlar ayrtrcnn hesaplayabilecei
deyimleri iermekteler:
10 - 5
2 * 3.3 / (3.1416 * 3.3)
exp iindeki mevcut indeks konumu expIdxte saklanr. Ayrtrma ilemi balaynca
expIdxe sfr deeri verilir. Ayrtrc deyim rerinde ilerledike expIdx birer birer artrlr.
token alan mevcut sembol tutar. tokType ise simge tipini ierir.
Ayrtrcnn giri noktas Evaluated() iindendir. Evaluate(), analiz edilecek
deyimi ieren karakter katar ile birlikte arlmaldr. EvalExp2()den EvalExp6()ya
kadar yer alan metotlar Atom() ile birlikte, yinelenerek inen ayrtrcy olutururlar. Bu
metotlar, daha nce anlatlan deyim retim kurallarnn gelitirilmi bir btnn uygularlar.
Metotlarn stnde yer alan aklamalar, onlarn gerekletirdikleri ilevleri tarif etmektedir.
Ayrtrcnn bir sonraki versiyonunda EvalExp1() adnda bir metot daha eklenecektir.
SyntaxErr(), deyim iindeki sz dizimi halalarn kontrol altna alr. GetToken() ve
isDelim() metotlar, nceden anlatld ekliyle deyimi bileenlerine ayrr. Ayrtrc,
deyimin bandan balayp sonuna kadar ilerlerken deyimden simgeleri elde etmek iin
GetToken() kullanr. Elde edilen semboln tipine gre farkl eylemlerde bulunulur.

HERKES N C#
KISIM III C#'I UYGULAMAYA GERMEK

768
Ayrtrcnn bir deyimin deerini tam olarak ne ekilde hesapladn anlamak iin
aadaki deyim zerinde aln:
10 - 3 * 2
Ayrtrcya giri noktas olan Evaluate() arlnca metot ilk sembol alr. Eer simge
bir null karakter katar ise No Expression Present mesaj ekranda grntlenir ve
Evaluate() 0.0 dndrr. Ancak, bu rnekte simge 10 deerini iermektedir. Sonra,
EvalExp2() arlr. EvalExp2(), EvalExp3() arr; EvalExp3(), EvalExp4()
arr; EvalExp4() ise sras geldiinde EvalExp5()i arr. Daha sonra, EvalExp5(),
sz konusu semboln tekli art ya da eksi olup olmadn belirler. Bu rnekte simge, tekli art
ya da eksi deildir; dolaysyla, EvalExp6() arlr. Bu noktada EvalExp6(), saynn
deerini bulmak iin ya yinelenerek EvalExp2()yi (parantezli bir deyim sz konusu
olduunda) ya da Atom()u arr. Simge, sol parantez olmad iin Atom() gereklenir ve
resulta 10 deeri atanr. Sonra, bir baka simge alnr ve metotlar zincir boyunca yukar
ynde geri dnmeye balar. imdi simge - operatr olduu iin metotlar EvalExp2()ye
kadar dner.
Bir sonraki aamada meydana gelenler ok nemlidir. Sz konusu simge - olduu iin bu
simge op iinde saklanr. Ayrtrc sonra, bir sonraki sembol alr; bu 3tr ve zincir boyunca
tekrar aa ynde inmeye balar. nceki gibi yine Atom()a girilir, result iinde 3 deeri
dndrlr ve * simgesi okunur. Bu, zincir boyunca yukar ynde EvalExp3()e kadar geri
dnmeye neden olur. Burada en son simge olan 2 okunur. Bu noktada ilk aritmetik ilem
meydana gelir: 2 ile 3n arpm. Sonu EvalExp2()ye dndrlr ve kartma ilemi
gerekletirilir. kartma ileminden 4 sonucu elde edilir. Bu sre balangta karmak gibi
grnse de, bu metodun her zaman doru olarak ilediini dorulamak iin dier birka rnek
zerinde bunu deneyebilirsiniz.
Ayrtrma srasnda bir hata meydana gelirse, SyntaxErr() metodu arlr. Bu metot,
hatay tarif eden bir ParserException frlatr. ParserException, ayrtrc dosyasnn
banda tanmlanan kendi oluturduumuz bir kural d durumdur.
Bu ayrtrc, nceki rnekte gsterildii gibi, basit masa st hesap makinesinde
kullanmak iin uygun olur. Ancak, bir bilgisayar dilinde, veri tabannda ya da sofistike bir
hesap makinesinde kullanlabilmesi iin ncelikle deikenleri ele alabilmesi gerekir. Bu, bir
sonraki blmn konusudur.
Ayrtrcya Deiken Eklemek
Tm programlama dilleri, pek ok hesap makinesi ve elektronik form deerlerin daha
sonradan kullanlabilmesi iin deiken kullanrlar. Ayrtrcnn bu tr uygulamalarda
kullanlabilmesi iin ncelikle deikenleri dahil edecek ekilde geniletilmesi gerekir. Bunu
gerekletirmek iin ayrtrcya birka e eklemeniz gereklidir. ncelikle, kukusuz,
deikenlerin kendileri eklenmelidir. nceden de bildirildii gibi. deikenler iin Adan Zye
BLM 26: YNELENEREK NEN BR DEYM AYRITIRICISI

HERKES N C#
769
kadar harfleri kullanacaz. Deikenler Parser snf iinde bir dizide saklanrlar. Her
deiken, 26 elemanl bir double dizisinde tek dizi konumunu kullanr. Bu nedenle, Parser
snfna u satr ekleyin:
double[] vars = new double[26];
Ayrca, deikenlere ilk deerlerini atayan aadaki Parser yaplandrcsn da
eklemeniz gerekecek:
public Parser() {
// Degiskenlere sifir degeri ata.
for(int i = 0; i < vars.Length; i++)
vars[i] = 0.0;
}
Kullancya yardmc olmak adna deikenlere ilk deer olarak 0.0 atanmtr.
Verilen bir deikenin deerini aramak iin de ayrca bir metoda ihtiyacnz olacaktr.
Deikenler, Adan Zye isimlendirildikleri iin vars dizisini indekslemek amacyla kolaylkla
kullanlabilirler. Ann ASCII deerini deikenin isminden kartmak yeterlidir. Aada
gsterilen FindVars() metodu bunu gerekletirir:
// Degiskenin degerini dondur.
double FindVar(string vname)
{
if(!Char.IsLetter(vname[0])) {
SyntaxErr(Errors.SYNTAX);
return 0.0;
}
return vars[Char.ToUpper(vname[0]) - A];
}
Bu metot yazld ekliyle aslnda uzun deiken isimlerini de kabul edecektir, sz gelii
sA12 ya da test. Fakat, yalnzca ilk harf nemlidir. Kendi ihtiyalarnza uyacak ekilde bu
zellii deitirebilirsiniz.
Atom() metodunu da hem saylar hem de deikenleri ele alacak ekilde
deitirmelisiniz. Yeni versiyon aada gsterilmitir:
// Sayi ya da degiskenin degerini al.
void Atom(out double result)
{
switch(tokType) {
case Types.NUMBER:
try {
result = Double.Parse(token);
} catch (FormatException) {
result = 0.0;
SyntaxErr(Errors.SYNTAX);
}
GetToken();
return;

HERKES N C#
KISIM III C#'I UYGULAMAYA GERMEK

770
case Types.VARIABLE:
result = FindVar(token);
GetToken();
return;
default:
result = 0.0;
SyntaxErr(Errors.SYNTAX);
break;
}
}
Ayntrcnn deikenleri doru kullanmas iin gerekli olan eklemeler teknik olarak
bunlardan ibarettir. Ancak, bu deikenlere deer atanmas hibir ekilde mmkn deildir. Bir
deikene bir deer verilebilmesi iin ayrtrcnn atama operatrn (=) ele alabilmesi
gereklidir. Atamalar gereklemek iin Parser snfna bir baka metot daha ekleyeceiz:
EvalExp1(). Bu metot artk yinelenerek inen zinciri balatacaktr. Bunun anlam udur:
Deyimi ayrtrma ilemini balatmak iin Evaluate() tarafndan arlmas gereken bu
metottur: EvalExp2() deildir. EvalExp1() aada gsterilmitir:
// Atama ifadesini hesapla.
void Evalexp1(out double result)
{
int varIdx;
Types ttokType;
string temptoken;

if(tokType == Types.VARIABLE) {
// eski sembolu sakla
temptoken = String.Copy(token);
ttokType = tokType;

// Degiskenin indeksini hesapla.
varIdx = Char.ToUpper(token[0]) A;

GetToken();
if(token != =) {
PutBack(); // mevcut sembolu dondur
// eski sembolu geri al - bu bir atama degil
token = String.Copy(temptoken);
tokType = ttokType;
}
else {
GetToken(); // deyimin bir sonraki parcasini al
EvalExp2(out result);
Vars[varIdx] = result;
return;
}
}

EvalExp2(out result);
}
BLM 26: YNELENEREK NEN BR DEYM AYRITIRICISI

HERKES N C#
771
EvalExp1(), esasen bir atamann yaplp yaplmadn belirlemek iin ileriye
bakmaldr. Bunun nedeni udur: Bir deiken ismi daima bir atamann nnde gelir, fakat bir
deiken ismi, peinden bir atama deyiminin geldiini garanti etmez. Yani, ayrtrc A = 100
deyimini bir atama olarak alacaktr, fakat A/10 deyiminin bir atama olmadn bilecek kadar
da aklldr. Bunu gerekletirmek iin EvalExp1(), girdi akndan bir sonraki sembol okur.
Eer simge eittir iareti deilse, simge PutBack() arlarak daha sonra kullanlmak zere
girdi akna geri dndrlr. PutBack() aada gsterilmitir
// Sembolu girdi akisina dondur.
void PutBack()
{
for(int i = 0; i < token.Length; i++) expIdx--;
}
Gerekli tm deiiklikler yapldktan sonra ayrtrc artk u ekilde grnecektir:
/*
B modul, degiskenleri algilayan,
yinelenerek inen bir ayristirici icerir.
*/

using System;

// Ayristirici hatalari icin kural disi durum sinifi.
class ParserExcaption : ApplicationException {
public ParserException(string str) : base(str) { }

public override string ToString() {
return Message;
}
}

class Parser {
// Simge tiplerini numaralandir..
enum Types { NONE, DELIMITER, VARIABLE, NUMBER };
// Hata tiplerini numaralandir..
enum Errors { SYNTAX, UNBALPARENS, NOEXP, DIVBYZERO };

string exp; // deyimi tutan karakter katarini gosterir
int expIdx; // deyim icindeki mevcut indeks
string token; // mevcut simgeyi tutar
Types tokType; // simgenin tipini tutar

// Degiskenler iin dizi.
double[] vars = new double[26];

public Parser() {
// Degiskenlere sifir degerini ata.
for(int i = 0; i < vars.Length; i++)
vars[i] = 0.0;
}

// Ayristiricinin giris noktasi.

HERKES N C#
KISIM III C#'I UYGULAMAYA GERMEK

772
public double Evaluate(string expstr)
{
double result;

exp = expstr;
expIdx = 0;

try {
GetToken();
if(token == ) {
SyntaxErr(Errors.NOEXP); // deyim mevcut degil
return 0.0;
}

EvalExp1(out result); // simdi baslamak icin
// EvalExp1()i cagir

if(token != ) // son simge null olmali
SyntaxErr(Errors.SYNTAX);

return result;
} catch (ParserException exc) {
// Istege gore baska bir hata yonetimi ekle.
Console.WriteLine(exc);
return 0.0;
}
}

// Atama ifadesini hesapla.
void EvalExp1(out double result)
{
int varIdx;
Types ttokType;
string temptoken;

if(tokType == Types.VARIABLE) {
// eski sembolu sakla
temptoken = String.Copy(token);
ttokType = tokType;

// Degiskenin indeksini hesapla.
varIdx = Char.ToUpper(token[0]) - A;

GetToken();
if(token != =) {
PutBack(); // mevcut simgeyi dondur
// eski sembolu geri al - bu bir atama deil
token = String.Copy(temptoken);
tokType = ttokType;
}
else {
GetToken(); // deyimin bir sonraki parcasini al
EvalExp2(out result);
vars[varIdx] = result;
return;
BLM 26: YNELENEREK NEN BR DEYM AYRITIRICISI

HERKES N C#
773
}
}

EvalExp2(out result);
}

// iki terimi ekle ya da cikart.
void EvalExp2(out double result)
{
string op;
double partialResult;

EvalExp3(out result);
while((op = token) == + || op == -) {
GetToken();
EvalExp3(out partialResult);
switch(op) {
case -:
result = result - partialResult;
break;
case +:
result = result + partialResult;
break;
}
}
}

// Iki faktoru carp ya da bol.
void EvalExp3(out double result) {
{
string op;
double partialResult = 0.0;

EvalExp4(out result);
while((op = token) == * || op == / || op == %) {
GetToken();
EvalExp4(out partialResult);
switch(op) {
case *:
result = result * partialResult;
break;
case /:
if(partialResult == 0.0)
SyntaxErr(Errors.DIVBYZERO);
result = result / partialResult;
break;
case %:
if(partialResult == 0.0)
SyntaxErr(Errors.DIVBYZERO);
result = (int) result % (int) partialResult;
break;
}
}
}


HERKES N C#
KISIM III C#'I UYGULAMAYA GERMEK

774
// Ustel ifadeyi hesapla.
void EvalExp4(out double result)
{
double partialResult, ex;
int t;

EvalExp5(out result);
if(token == *) {
GetToken();
EvalExp4(out partialResult);
ex = result;
if(partialResult == 0.0) {
result = 1.0;
return;
}
for(t = (int) partialResult - 1; t > 0; t--)
result = result * (double) ex;
}
}

// Tekli + ya da -nin degerini hesapla.
void EvalExp5(out double result)
{
string op;

op = ;
if((tokType == Types.DELIMITER) &&
token == + || token == -) {
op = token;
GetToken();
}
EvalExp6(out result);
if(op == -) result = -result;
}

// Parantez icindeki deyimi hesapla.
void EvalExp6(out double result)
{
if((token == ()) {
GetToken();
EvalExp2(out result);
if(token != ))
SyntaxErr(Errors.UNBALPARENS);
GetToken();
}
else Atom(out result);
}

// Sayinin ya da degiskenin degerini al.
void Atom(out double result)
{
switch(tokType) {
case Types.NUMBER:
try {
result = Double.Parse(token);
BLM 26: YNELENEREK NEN BR DEYM AYRITIRICISI

HERKES N C#
775
} catch (FormatException) {
result = 0.0;
SyntaxErr(Errors.SYNTAX);
}
GetToken();
return;
case Types.VARIABLE:
result = FindVar(token);
GetToken();
return;
default;
result = 0.0;
SyntaxErr(Errors.SYNTAX);
break;
}
}

// Degiskenin degerini dondur.
double FindVar(string vname)
{
if(!Char.IsLetter(vname[0])) {
SyntaxErr(Errors.SYNTAX);
return 0.0;
}
return vars[Char.ToUpper(vname[0]) - A];
}

// Girdi akisina bir simge dondur.
void PutBack()
{
for(int i = 0; i < token.Length; i++) expIdx--;
}

// Soz dizimi hatasini kontrol altina al.
void SyntaxErr(Errors error)
{
string[] err = {
Syntax Error,
Unbalanced Parentheses,
No Expression Present,
Division by Zero
};

throw new ParserException(err[(int)error]);
}

// Bir sonraki simgeyi elde et.
void GetToken()
{
tokType = Types.NONE;
token = ;

if(expIdx == exp.Length) return; // deyim sonu ise

// bosluklari atla

HERKES N C#
KISIM III C#'I UYGULAMAYA GERMEK

776
while(expIdx < exp.Length &&
Char.IsWhiteSpace(exp[expIdx])) ++expIdx;

// deyimin sonundaki bosluklar deyimi sonlandirir
if(expIdx == exp.Length) return;

if(IsDelim(exp[expIdx])) { // operator mu?
token += exp[expIdx];
expIdx++;
tokType = Types.DELIMITER;
}
else if(Char.IsLetter(exp[expIdx])) { // degisken mi?
while(!IsDelim(exp[expIdx])) {
token += exp[expIdx];
expIdx++;
if(expIdx >= exp.Length) break;
}
tokType = Types.VARIABLE;
}
else if(Char.IsDigit(exp[expIdx])) { // sayi mi?
while(!IsDelim(exp[expIdx])) {
token += exp[expIdx];
expIdx++;
if(expIdx = exp.Length) break;
}
tokType = Types.NUMBER;
}
}

// c bir sinirlandirici ise true dondur.
bool IsDelim(char c)
{
if(( +-/*%^=().IndexOf(c) != -1))
return true;
return false;
}
}
Gelitirilmi ayrtrcy denemek iin basit ayrtrcda kullandnz programn aynsn
kullanabilirsiniz. Gelitirilmi ayrtrcy kullanarak artk u tr deyimleri girebilirsiniz:
A = 10/4
A - B
C = A * (F - 21)
Yinelenerek nen Ayrtrcda Sz Dizimi Kontrol
Deyim ayrtrma ileminde bir sz dizimi hatas, basite, ayrtrcnn gerektirdii kat
kurallara girdi deyiminin uymamas durumudur. Buna ounlukla insanlarn hatalar neden olur
- bunlar genellikle yazm hatalardr. rnein, aadaki deyimler bu blmde yer alan
ayrtrclar iin geerli deildir:
10 ** 8e
BLM 26: YNELENEREK NEN BR DEYM AYRITIRICISI

HERKES N C#
777
((10 5) * 9
/8
lk deyim ayn satrda iki operatr iermektedir; ikincisinde elenmeyen parantez vardr ve
sonuncusu, deyimin banda bol iaretine sahiptir. Ayrtrc, bu koullarn hibirine izin ver-
mez. Sz dizimi hatalar ayrtrcnn hatal sonular vermesine neden olabildii iin bunlara
kar tedbirli olmalsnz.
Ayrtrc kodu zerinde altysanz, yalnzca belirli durumlarda arlan Syntax()
metodunu muhtemelen fark etmisinizdir. Dier ayrtrc tiplerinden farkl olarak yinelenerek
inen ayrtrc metodu, sz dizimi kontroln kolaylatrmaktadr, nk sz dizimi kontrol
ou kez Atom()da, FindVar()da ya da parantezlerin kontrol edildii EvalExp6()da
meydana gelmektedir.
SyntaxErr() arld zaman hatann tanmn ieren bir ParserException frlatr.
Parsern mevcut ekliyle bu kural d durum, Evaluate() iinde yakalanr. Dolaysyla;
ayrtrc, bir hata ile karlanca hemen durur. Kukusuz, siz kendi ihtiyalarnza uygun ola-
cak ekilde bu davran deitirebilirsiniz.
Denenecek Birka ey
Bu blmn balarnda bahsedildii gibi, ayrtrc tarafndan yalnzca asgari dzeyde
hata kontrol gerekletirilmektedir. Siz ayrntl hata bildirimini eklemek isteyebilirsiniz.
rnein, deyim iinde hatann tespit edildii noktann iaretlenmesini salayabilirsiniz. Bu,
kullancnn bir sz dizimi hatasn bulup, dzeltmesine olanak tanyacaktr.
Ayrtrc u haliyle yalnzca nmerik deyimleri hesaplayabilir. Ancak, birka eklemeyle
dier tipte deyimleri de hesaplamasn salayabilirsiniz. rnein, karakter katarlar, uzaysal
koordinatlar ya da karmak saylar gibi. Ayrtrcnn, sz gelii, karakter katar nesnelerinin
deerini hesaplamas iin aadaki deiiklikleri yapmanz gereklidir.
1. STRING adnda yeni bir simge tanmlayn.

2. GetToken() karakter katarlarn alglayacak ekilde gelitirin.

3. Atom()un iine STRING tipinde simgeleri ele alan yeni bir case ekleyin.
Bu admlan uyguladktan sonra ayrtrc, karakter katar eklindeki u tr deyimleri ele
alabilir:
a = one
b = two
c = a + b
cdeki sonu, a ve bnin pe pee eklenmi ekli, ya da onetwo, olmaldr.

HERKES N C#
KISIM III C#'I UYGULAMAYA GERMEK

778
te, ayrtrc iin iyi bir uygulama: Kullancnn girdii bir deyimi alan ve sonra sonucu
ekrannda gsteren basit, alr bir mini hesap makinesi oluturun. Bu, hemen hemen tm ticari
uygulamalar iin mkemmel bir ek olacaktr.
Son olarak, Parser bir bileene dntrmeyi deneyin. Bunu yapmak kolaydr. nce,
Parsern Componenttan kaltmla elde edilmesini salayn. Sonra, Dispose(bool)u
uygulayn. te bu kadar! Bunu yaparsanz, yazdnz tm uygulamalarda kullanabileceiniz
bir ayrtrcya sahip olacaksnz.



E K A


XML AIKLAMALARI
REFERANSI





















A

HERKES N C#
EK A:

780
C#ta tane aklama iareti vardr. Bunlarn ilk ikisi // ve /* ...*/ iaretleridir.
nc tip ise XML imlerine dayaldr ve XML aklamas olarak adlandrlr. (XML
aklamalarna belgeleme aklamalar da denir.) Bir XML aklamasnn her satr /// ile
balar. XML aklamalar; snf, isim uzay, metot, zellik ve olay gibi elerin
deklarasyonlarndan nce gelir. XML aklamalarn kullanarak program hakkndaki bilgileri
programn iine gmebilirsiniz. Programnz derlerken XML aklamalarn bir XML
dosyasnn iine yerletirebilirsiniz. XML aklamalar ayrca Visual Studionun IntelliSense
zellii tarafndan kullanlmaya da uygundur.
XML Aklama mleri
C#, Tablo A.1de gsterilen XML belgeleme imlerini destekler. XML aklama imlerinin
ounluu kolayca anlalabilir niteliktedir. Bunlar, ou programcnn zaten bildii dier
XML imleri gibi ilev grrler. Ancak <list> imi dierlerinden daha karmaktr. Bir listede
iki bileen bulunur: Liste bal ve liste elemanlar. Bir liste balnn genel ekli yledir:
<listheader>
<term> isim < /term>
< description> metin < /description>
</listheader>
Burada metin, listenin isimini tanmlar. Tablo iin metin kullanlmaz. Bir liste
elemannn genel ekli aada gsterilmitir:
<item>
<term> eleman-ismi < /term>
<description> metin </description>
</item>
Burada metin, sz konusu eleman-ismini belirtir. Noktal ya da numaral listelerde
veya tablolarda eleman-ismi kullanlmaz. Bir listede birden fazla <item> esi bulunabilir.

TABLO A.1: XML Aklama mleri


Etiket Aklama
<c> code < /c> code ile belirtilen metni program kodu olarak
belirtir.
<code> code </code> code ile belirtilen birden fazla satrdan oluan
metni program kodu olarak belirtir.
<example> explanation </example> explanation ile ilintili metin, bir kod rnei
tarif eder.
<exception cref = name>
explanation
</exception>

Kural d bir durumu tarif eder. Kural d durum
name ile belirtilir.
XML AIKLAMALARI REFERANSI

HERKES N C#
781
<include file = fname path = path
[@tagName = tagID] />
Mevcut dosya iin XML aklamalarn ieren bir
dosya belirtir. Dosya fname ile belirtilir. m iin
dosya yolu, im ismi ve im kodu srasyla path,
tagName ve tagID ile belirtilir.
<list type = type>
list-header
list-items
</list> Bir liste belirtir. Listenin tipi type ile belirtilir.
type ya noktal, numaral ya da bir tablo
olmaldr.
<para> text </para> Bir baka im iinde bir paragraf uzunluunda
metni belirtir.
<para name = param-name>
explanation
</param> paramname ile belirtilen parametreyi belgeler.
explanation ile ilintili metin parametreyi
tarif eder.
<paramref name = param-name />
<permission cref = identifier>
param-namein bir parametre ismi olduunu
belirtir.

explanation
</permission> identifier ile belirtilen snf yeleri ile ilintili
izin ayarlarn tarif eder. explanation ile
ilintili metin, izin ayarlarn gsterir.
remarks> explanation< /remarks> explanation ile belirtilen metin genel bir
aklamadr. Genellikle bir snf ya da yap gibi
bir tipi tarif etmek iin kullanlr.
returns> explanation< /returns> explanation ile belirtilen metin, bir metodun
dn deerini belgeler.
<see cref = identifier /> identifier ile belirtilen bir baka elemana bir
balant deklare eder.
<seealso cref = identifier /> identifier iin ayrca baknz balants
deklare eder.
<summary> explanation< /summary> explanation ile belirtilen metin genel bir
aklamadr. Genellikle bir metot ya da bir baka
snf yesini tarif etmek iin kullanlr.
<value> explanation< /value> explanation ile belirtilen metin bir zellii
tarif eder.
XML Belgelemesinin Derlenmesi
Belgeleme aklamalar ieren bir XML dosyas retmek iin derleyicinin /doc seeneini
belirtin. rnein, XML aklamalar ieren ve ad DocTest.cs olan bir dosyay derlemek iin
u komut satrn kullann:

HERKES N C#
EK A:

782
csc DocTest.cs /doc:DocTest.xml
Visual Studio IDE kullanrken bir XML kt dosyas kullanmak iin Property Pages
iletiim kutusundan yararlanmanz gereklidir. Bu iletiim kutusuna View | Property Pages
komutu
zerinden ulaabilirsiniz. Sz konusu menye gittikten sonra Configuration Properties |
Build seeneini iaretleyin. Ardndan, XMLin adn, XML Documentation File zelliinde
belirtin.
XML Belgeleme rnei
Aadaki rnek eitli XML aklamalarnn kullanmn gstermektedir:
// XML belgeleme ornegi.

using system;
/// <remark>
/// Bu bir XML belgeleme ornegidir.
/// Test snf cesitli im orneklerini gosterir.
/// <remark>

class Test {
/// <Summary>
/// Programin calismasi Mainde baslar.
/// </summary>
public static void Main() {
int sum;

sum = Summation(5};
Console.WriteLine(Summation of + 5 + is + sum);
}

/// <summary>
/// Summation, 1den argumana kadar olan sayilarin
/// toplamini verir.
/// <param> name = val
/// Toplanacak sayi, val paramteresinde gecilir.
/// </param>
/// <see> cref-int </see>
/// <returns>
/// Toplam, bir int degeri olarak dondurulur.
/// </returns>
/// </summary>
static int Summation(int val) {
int result = 0;

for(int i = 1; i <= val; i++)
result += i;

return result;
}
}
XML AIKLAMALARI REFERANSI

HERKES N C#
783
Yukardaki programn XmlTest.cs olarak adlandrldn varsayarsak, aadaki satrda
yer alan ifade, bu program derleyecek ve aklamalarn bulunduu XmlTest.xml adl bir
dosya retecektir:
csc XmlTest.cs /doc:XmlTest.xml
Derleme bittikten sonra aadaki XML dosyas retilir:
<?xml version=1.0?>
<doc>
<assembly>
<name>t</name>
</assembly>
<members>
<member name=T:Test>
<remark>
Bu bir XML belgeleme ornegidir.
Test sinifi cesitli im orneklerini gosterir.
</remark>
</member>
<member name=M:Test.Main>
<summary>
Programin calismasi Mainde baslar.
</summary>
</member>
<member name=M:Test.Summation(System.Int32)>
<summary>
Summation, 1den argumana kadar olan sayilarin
toplamini verir.
<param name=val>
Toplanacak sayi, val paramteresinde gecilir.
</param>
<see cref=T:System.Int32> </see>
<returns>
Toplam, bir int degeri olarak dondurulur.
</returns>
</summary>
</member>
</members>
</doc>
Dikkat ederseniz, belgelenen her elemana benzersiz bir tanmlayc verilmitir. Bu
tanmlayclar, XML belgelemesi kullanan dier programlarn kullanmna da aktr.



E K B


C# VE ROBOTK






















B
C# VE ROBOTK

HERKES N C#
785
Hakknda pek fazla yazmam olsam da, robotik benim hobimdir. Aslnda robotik uzun
yllar nce ayn zamanda benim iimdi. Endstriyel robot kontrol dilleri tasarlar ve uygulardm.
Robotlar heyecan vericidir, nk yazdmz programlarn mantn canlandrrlar. Robotlar
ayn zamanda gerek dnya ile etkileirler. Uzun zamandr robotik ile profesyonel dzeyde ak-
tif olarak ilgilenmiyor olmama ramen, robotik her zaman ilgi alanma girmitir. Robotik konu-
sunu burada gndeme getirmemin nedeni, C#n robotik programcsna baz avantajlar
salamasdr.
Normal olarak robotik kontrol kodu dendiinde C++ta yazlan yksek performansl rutin-
ler akla gelir. Ancak C# bu varsaymn sorgulanmasna neden olabilir. nk robot kontrol
programlar gayet byk olabilir; ynlendirme, grme, desen tanma, motor kontrol gibi pek
ok alt sistem ierebilir. Bu alt sistemler C# bileenleri olarak organize edilebilirler (ve
uygulanabilirler). Robotik kodunu bileen yaklam ile yazmak, robot kontrolnde mevcut olan
karmakl ynetmeye katk salar Bu sayede, ayrca alt sistemlerin kolayca deitirilmesi ve
terfi ettirilmesi de mmkn olur.
Robotik konusu ile ilgileniyorsanz - zellikle de deney amal olarak kendi robotunuzu
yapmaya ilgi duyuyorsanz - ekil B.Ideki robot ilginizi ekebilir. Bu, benim test robotumdur.
Bu robotu ilgin klan birka zellik mevcuttur. Birincisi, robotta temel motor kontrol ve
alglayc geri beslemesi salayan dahili bir mikroilemci yer almaktadr. kinci olarak, ana
bilgisayardan veri almak ve sonular ana bilgisayara geri iletmek zere bir RS 232 alc/verici
bulunmaktadr. Sz konusu yaklam sayesinde robotik iin ihtiya duyulan ilem gc, robotu
arlatrmadan uzaktaki bir bilgisayar tarafndan salanabilmektedir. nc olarak, robotta
kablosuz bir grnt vericisine bal bir video kamera yer almaktadr.


EKL B.1: Basit ama ayn zamanda etkili deneysel bir robot.
Robot, bir Hobbico MI Abrams R/C tank asisi zerine ina edilmitir. (R/C model
tanklarn ve otomobillerin asisinin robot taban olarak ok iyi ie yaradn grdm.) Tankn
i sistemlerinin ounu sktm. Alc ve hz kontrol devreleri de buna dahil. Ancak motorlar
braktm. Hobico tank olduka gl bir yapya sahip olduu iin bir robotik platformu olarak
olduka uygundur. Motorlar iyi, olduka fazla miktarda yk tayabilmekte ve paletleri

HERKES N C#
EK B:

786
yerinden kmamaktadr. Paletli bir ara olduu iin olduu yerde manevra yapabilmekte ve
bozuk yzeylerde de hareket edebilmektedir. asi 18 in uzunluunda, 8 in enindedir.
asiyi boalttktan sonra yeni bileenler ekledim. Dahili kontrol sistemi iin bir BASIC
Stamp 2 kullandm. Bu, Parallax Inc. (www.parallaxinc.com) tarafndan retilen basit ama
gl bir mikroilemcidir. RS-232 alc/verici ile grnt kameras ve vericisi de yine
Parallaxa ait. Kablosuz RS-232 alc/vericisi ve grnt vericisinin menzili yaklak 300 ayak
(100 m). Tank motorlarna ayrca elektronik hz kontrolrleri ekledim. Yksek performansl
R/C arabalar tarafndan kullanlan trden olan bu kontrolrler BASIC Stamp mikroilemciye
bal olarak almaktadrlar.
Robot yle alr: Uzaktaki bilgisayar ana robotik kontrol programn altrr. Bu
program; grnt, ynlendirme ve uzaysal konumlandrma gibi tm ar ileri halleder.
Ayrca bir dizi hareketi renebilir ve gerekletirebilir. Uzaktan kontrol bilgisayar, hareket
kontrol komutlarn (telsiz RS-232 balants zerinden) robota gnderir. BASIC Stamp, bu
komutlar alr ve uygular. rnein bir ileri hareket et komutu gelmise, BASIC Stamp,
gerekli sinyalleri, motorlara bal elektronik hz kontrolrlerine gnderir. Robot bir komutu
tamamlad zaman alnd kodunu dndrr. Bylece uzaktan kontrol bilgisayar ile robot
arasnda iki ynl iletiim salanr ve her komutun baaryla tamamlanp tamamlanmad
takip edilebilir.
Robotla ilgili ana ilemler uzaktan kontrol bilgisayarnda yapld iin bu sistemin ilem
gc konusunda ciddi bir snrlama bulunmamaktadr. rnein, bu yaznn hazrland srada
robot, grme sistemini kullanarak bir nesneyi izleyebilmekteydi. Bu yetenek ciddi bir ilem
gc gerektirir ve byle bir ilem gcn robot zerinde tamak zordur.
Bu yaznn hazrland srada robotik kontrol kodunun ounluu hala C++ dilinde yazl-
m olarak duruyordu. Ancak, kodun paralarn ilk frsatta C#a geirmeyi planlamaktaym. lk
dntreceim alt sistem, bir seri komutu altran alt sistem olacak. Liste tabanl olan bu
grev, bir C# koleksiyonu tarafndan kolaylkla ele alnabilir.

You might also like