24 Mayıs 2013 Cuma
C# - Convert.ToInt32(), Int32.Parse() ve Int32.TryParse() Farklılıkları
Merhabalar, Bu makalemde Convert.ToInt32() , Int32.Parse() ve Int32.TryParse() Farklılıkları’na değineceğim. String tipindeki bir değişkeninizi Integer veri tipine dönüştürürken genelde Convert.ToInt32() Method ve Sınıfını kullanırız. Fakat bu yöntem bazı durumlarda hatalar verecektir.
Method ve Sınıflarımızı örneklerle inceleyelim; ilk olarak dört adet değişken belirleyelim, Değişkenlerin hepsi String veri tipinden değişik veriler içersin.
Convert.ToInt32(); Değer Null olarak geldiğinde sıfır olarak döndürülür. Yukarda ki resmi inceleyerek anlatacak olursak erkan2 değişkeni Format dışarısında olduğu için Convert.Int32() ile döndürülemez bu nedenle uygulandığında FormatException hatası belirir. erkan3 değişkenine bakacak olursak içerisindeki veri Maxvalue değerini aşıyor. Bu nedenle uygulandığında OverFlowException hatası ile karşılaşacaksınız. Şimdi soracaksınız MaxValue ve MinValue Nedir?
– MaxValue: Dokuz basamaklı maksimum değerdir.(örn:999999999)
– MinValue: MaxValue’nin tam tersi eksi yönde dokuz basamaklı minimum değerdir.
(örn: -999999999)
erkan4 değişkenine baktığımızda Convert.Int32() formatlarına uygun veri içeriyor bu nedenle uygulandığında veri tipi Integer’a sorunsuz olarak dönecektir. Basit bir uygulamasını yapalım;
Int32.Parse(); Değer Null olarak geldiğinde ArgumentNullException hatası ile karşılaşılır. Eğer değer Integer değilse FormatException hatası ile karşılaşılır. Değişken içerisindeki veri Maxvalue değerini aşıyorsa veya MinValue değerinin altında ise uygulandığında OverFlowException hatası ile karşılaşacaksınız. MaxValue ve MinValue değerlerini yukarıda açıkladım.
Int32.Parse(); ile basit bir uygulama yapalım;
Int32.TryParse(); Değişken Null veya Integer olmayan bir tipte geliyor ise sıfır olarak döndürülür. MaxValue veya MinValue belirtilmemiştir bu nedenle diğer dönüştürme metotlarında karşılaştığımız tüm hatalar Int32.TryParse(); ile sıfır olarak döndürülür.
Bu sebepten dolayı diğerlerine göre daha iyi ve daha faydalıdır.Riskleri en aza indirir.Basit bir örnek ile açıklayalım;
C# koleksiyonlar
Collection’lar veriyi saklamak,gruplamak ve içerisinde gezinmek için kullanılırlar.Array’ler de bu işe yarar fakat collection’lar array’lerin geliştirilmiş versiyonudur.
System.Collections namespace’i : Arraylist, Collection interfaces, iterators, Hastable, CollectionBase sınıfı,ReadOnlyCollectionBase sınıfı, DictionaryBase sınıfı, DictionaryEntry sınıfı, Comparer sınıfı, Queue sınıfı, SortedList, BitArray, Stack,
System.Collections.Specialized namespace’i : Specialized String sınıfları, Specialized Dictionary, NameValueCollection sınıfı, CollectionsUtil , BitVector32 structure içerir
System.Collections.Generic namespace’i : Collection.Generic interfaces, Generic Dictionary, Generic Comparer, GenericEquality Comparer, Generic KeyValuePair Structure, Generic List,Generic List.Enumerator structure, Generic Sorted List, Generic Queue, Generic SortedDictionary, Generic LinkedList, Generic Stack içerir.
Kendi Sort sınıfınızı yazmak :
Normalde arrayler ve listelerin standart Compare metodu vardır bu metod iki değeri karşılaştırır ve birinci değer büyük ise -1 , ikinci değer büyükse 1 , eşitse 0 döndürür. Biz IComparer interface’ini implemente etmiş kendi sınıfımızı yazıp daha sonra Sort metoduna bu Comparer’ı verirsek artık sort işlemi bizim belirlediğimiz kriterlere göre karşılaştırma yapar. Aşağıdaki örnek Comparer tersten sıralamayı anlatmaya çalışmaktadır.
public class DescendingStringComparer : IComparer
{
CaseInsensitiveComparer _comparer = new CaseInsensitiveComparer();
#region IComparer Members
public int Compare(object x, object y)
{
//Bu kod sayesinde (x,y değil y,x) testen sıralama yapılır.
return _comparer.Compare(y, x);
}
#endregion
}
list.Sort(new DescendingStringComparer());
şeklinde bir listeyi sort edersek bu sefer küçükten büyüğe değil büyükten küçüğe sıralama yapacaktır.
Sequential Lists:Queue : Kuyruk FIFO ilk giren ilk çıkar şeklinde çalışır. Bir kuyruğa yeni bir eleman eklemek için
Queue q = new Queue();
q.Enqueue("a");
q.Enqueue("b"); geriye bir değer döndürmez.
Kuyruktan bir eleman çıkarmak için ise q.Dequeue(); kullanılır ve ilk eleman listeden çıkarılır yani a çıkarılır ve geriye object olarak çıkardığı eleman döner. Eğer kuyruktan eleman çıkarmadan sıradaki elemanla ilgili işlem yapılmak isterse Peek() metodu kullanılabilir.
if (q.Peek() is String)
q.Dequeue();
Stack: Kuyruğun tam tersi mantıkta çalışır LIFO ilk giren son çıkar mantığıyla çalışır.
Stack’a eleman eklemek için Push çıkarmak için Pop metodu kullanılır.
Stack s = new Stack ();
s.Push("a");
s.Push("b");
object o = s.Pop();//Pop metodundan çıkarılan eleman döner.
Dictionaries:
Hastable : Key-Value şeklinde veri saklamak için kullanılır. Bir dataya bir anahtar yardımıyla erişmek için Hashtable çok kullanışlıdır ancak eleman sayısı az olan listelerde Hastable yerine ListDictionary kullanmak performans açısından daha etkilidir.Hashtable’a veri eklemek ve listelemek aşağıdaki gibidir.
Hashtable h = new Hashtable();
h["adi"] = "koray";
h["mail"] = "koraykirdinli@yahoo.com";
foreach (DictionaryEntry item in h)
{
listBox4.Items.Add(item.Key +" : "+ item.Value);
}
DictionaryEntry key/value çiftlerini saklamak için kullanılan bir konteyner nesnedir. Bütün Dictionary sınıfları IDictionary interface’ini implement eder. IDictionary interface’inin önemli property ve metodları şunlardır.
IsFixedSize,IsReadOnly,Item,Keys,Values – Add,Clear,Contains,GetEnumarator,Remove.
IDictionary interface’inde IList interface’inden farkı IList nesnelere indexi ile IDictionary nesneleri anahtar değeri ile erişir.
Hashtable listelerde bir key veya Value değerinin var olup olmadığını anlayabilmek için iki metod vardır:ContainsKey,ContainsValue. Hashtable listede aynı keye sahip birden fazla key olamaz.
Eğer Hashtable’a key olarak bir sınıf nesnesi vererek eklersek bu sefer Name’leri aynı olsa bile farklı olarak algılar.
Person p1 = new Person("Koray");
Person p2 = new Person("Koray");
Hashtable h2 = new Hashtable();
h2[p1] = "a";
h2[p2] = "a";
//Bu sefer Person sınıfının Equals ve GetHashCode metodlarını override ettiğimiz için
//bütün özellikleri aynı olsa da farklı iki eleman olarak alır.
public class Person
{
public string Name;
public Person(string name)
{
Name = name;
}
public override bool Equals(object obj)
{
Person other = obj as Person;
if (other == null) return false;
return other.Name == Name;
}
public override int GetHashCode()
{
return Name.GetHashCode();
}
}
//----------------------------------------------------------------------------------
public class InsensitiveComparer : IEqualityComparer
{
//Bu comparer karşılaştırmayı case-insensitive olarak yapmayı sağlar.
CaseInsensitiveComparer _comparer = new CaseInsensitiveComparer();
public int GetHashCode(object obj)
{
return obj.ToString().ToLowerInvariant().GetHashCode();
}
public new bool Equals(object x, object y)
{
if (_comparer.Compare(x, y) == 0)
{
return true;
}
else return false;
}
}
Hashtable h3 = new Hashtable(new InsensitiveComparer());
h3["aa"] = "a";
h3["Aa"] = "a";
h3["AA"] = "a";
Console.WriteLine(h3.Count);// insensitive comparer kullandığımız için 3 değil 1’dir.
//----------------------------------------------------------------------------------
SortedList:
//SortedListlerde Hashtable'a ek olarak bir elemana hem key ile hem de index ile //erişebiliriz. Elemanı eklediğimiz anda listede uygun yere ekleme yapar.
SortedList list = new SortedList();
list["First"] = 1;
list["Second"] = 2;
list["first"] = "1";
//Yukardaki listede indexler bu şekilde oluşur. 0:first,1:First,2:Second
list.GetByIndex(2);
foreach (DictionaryEntry item in list)
{
listBox5.Items.Add(item.Key+" : " +item.Value);
}
Özelleştirilmiş Dictionary’ler:
Eleman sayısı 10 dan az ise Hastable yerine ListDictionary kullanmak performans açısından daha iyidir.ListDictionary Hastable ile aynı interface’leri implement eder , kullanımı da aynıdır.
HybridDictionary: Eğer bir listenin eleman sayısının az veya çok olduğunu önceden kestiremiyorsak HybridDictionary kullanılmalıdır. Interface’leri ve kullanımı yine aynıdır.
OrderedDictionary: Keyleri sıralı bir listeye ihtiyacınız olduğunda Hastable işe yaramaz ayrıca bir elemana indexi ile erişmekte mümkün olmaz. SortedList ise keyler beklediğiniz gibi sıralanmıyorsa OrderedDictionary kullanılabilir. Ekstra birkaç özelliği daha vardır.
Özelleştirilmiş tipi olan Koleksiyonlar.
BitArray : true , false tutmak için kullanılır ve elemanları Xor , And gibi bitsel işlemler yapılabilir.
BitVector32 : bitleri 32 bit integer değer olarak saklamaya yarar.
StringCollection : ArrayList gibidir ancak sadece string içerir.
Bir Hashtable veya SortedList’i case insensitive yapmak için aşağıdaki şekilde yaratabiliriz.
Hashtable ht= CollectionsUtil.CreateCaseInsensitiveHashtable();
SortedList sl = CollectionsUtil.CreateCaseInsensitiveSortedList();
Normal şartlarda karşılaştırma işlemi o anki thread’in bölgesel ayarına göre yapılır ancak bunu değiştirmek aşağıdaki kod ile mümkün.
Hashtable ht2 = new Hashtable(StringComparer.InvariantCulture);
NameValueCollection : key/value alır ancak bir keye ait birden fazla value olabilir.
NameValueCollection list = new NameValueCollection();
list.Add("key1", "value1");
list.Add("key1","value2");
list.Add("key2", "value3");
foreach (string s in list.GetValues("key1"))
{
listBox6.Items.Add(s);
}
//----------------------------------------------------------------------------------
GENERIC COLLECTIONS
Generic koleksiyonların daha önce bahsettiğimiz Arralist,HashTable gibi koleksiyonlardan en önemli farkı type-safe yani belli bir tipte olması , boxing unboxing den kurtulmamızı ve dolayısıyla performansımızı artırmamızı sağlar. Böylece run time da istenmeyen hataları da azaltmış oluruz.
public class MyList
{
//Bu sınıf sadece T tipinde değere alan bir koleksiyondur. Kendimiz tip güvenli yapmış olduk. T bu sınıf tanımlanırken integer,string vs olarak tanımlanabilir.
ArrayList array = new ArrayList();
public void Add(T val)
{
array.Add(val);
}
public T this[int index]
{
get { return (T)array[index]; }
}
#region ICollection Members
#endregion
#region IEnumerable Members
#endregion
}
//Bu tanımlama sayesinde bu liste sadece integer değer alabilir hale geldi.Arraylistin sadece integer alan versiyonu aşağıdaki gibidir.
List
list.Add(1);
//list.Add("2"); ERROR
Generic Delegates:
public delegate int Comparison
Bunun avantajı örneğin bir listeyi testen yazdıran bir Comparison nesnesi yapmak istiyorsunuz ancak her bir tip için de bunu tek tek yapmak uzun sürecektir. Bunun yerine Comparison delegesi generic olduğundan tek bir metod ile işlem yapılabilir.
Generic queue ve stack da aşağıdaki gibi oluşturulur kullanımı generic olmayan versiyonu ile aynıdır.
Queue
Stack
Generic Dictionary : Hashtable,ListDictionary ve HybridDictionary koleksiyonlarının generic halidir.
Dictionary
list.Add(1, "koray");
list.Add(2,"kirdinli");
list[3] = "aaaaaa";
//Diğer bazı generic koleksiyonların tanımlanması aşağıdaki gibidir.
SortedList
SortedDictionary
LinkedList
.NET içerisinde kendi koleksiyonlarımızı yazabilmemiz için kolaylık olması bakımından base sınıflar mevcuttur.
Sınıfımızı CollectionBase’den türetirsek : IList,IEnumerable,ICollection interface lerini ekstra kod yazmadan implement etmiş oluruz.
ReadOnlyCollectionBase: IList,IEnumerable,ICollection interface lerini ekstra kod yazmadan implement eder.Sadece koleksiyona dışarıdan ekleme çıkarma yapılamaz. Örneğin kullanıcı listesi değişmesi istenmiyorsa kullanılabilir.
DictionaryBase:IDictionary,IEnumerable,ICollection ICollection interface lerini ekstra kod yazmadan implement eder.
C# - Referans ve Değer Türleri Arasındaki Dönüşüm
Referans ve Değer Türleri Arasındaki Dönüşüm :
- NET sınıf kütüphanesinde yer alan "Convert" sınıfı string değerleri ve temel veri türlerini birbirine çevirmek için kullanılır. Her bir veri türü için ayrı bir çevrim fonksiyonu sahiptir.
Aşağıda referans ve değer türleri arasındaki dönüşüme örnek verilmiştir.
- NET sınıf kütüphanesinde yer alan "Convert" sınıfı string değerleri ve temel veri türlerini birbirine çevirmek için kullanılır. Her bir veri türü için ayrı bir çevrim fonksiyonu sahiptir.
Aşağıda referans ve değer türleri arasındaki dönüşüme örnek verilmiştir.
using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace Convert1 { class Program { static void Main(string[] args) { string temp; double sonuc; Console.WriteLine("Lutfen bir deger giriniz:"); temp = Console.ReadLine(); sonuc = Convert.ToDouble(temp) * 5.2 + 4; Console.WriteLine("Sonuc=" + sonuc.ToString()); Console.WriteLine("Sonuc={0}", sonuc); Console.WriteLine("{0} * 5.2 + 4 = {1}", temp, sonuc); Console.WriteLine(temp + " * 5.2 + 4 = " + sonuc); } } }
C# - Casting
Casting
- Bilinçli tür dönüsümünlerinde "casting" yönetmi kullanırken “tür dönüstürme operatörleri” kullanılır. Tür dönüstürme operatörü parantez içinde değişken yada sabitten önce yazılır.
Aşağıda bilinçli tür dönüşümünlerinden casting'e örnek verilmiştir.
using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace Casting { class Program { static void Main(string[] args) { byte a; int b = 50; int c = 356; a = (byte) b; Console.WriteLine("a=" + a); a = (byte)c; Console.WriteLine("a=" + a); Console.Read(); } } }
C# - Bilinçsiz(Implicit) Tür Dönüşümleri
- Derleyici tarafından bir değişkeni tanımladığımız türün dışın geçici olarak başka bir türe çevirmeye bilinçsiz tür dönüşümü denir.
- Bilinçsiz yapılan tür dönüşümlerinde bir nesnenin türü asla kalıcı olarak değiştirilmez.
- Bilinçsiz yapılan tür dönüşümleri 2 şekilde gerçekleştirilebilir.
a.Küçük Türün Büyük Türe Dönüştürülmesi: Küçük türler büyük türlere dönüstürülürken fazla olan bitler yani büyük türden dolayi eklenen bitler sıfırla beslenirler. Küçük türün yüksek anlamli bitlerinin sifirla beslenmesi degiskendeki degeri değiştirmediği için tür dönüşümünde herhangi bir veri kaybı olmaz
b.Büyük Türün Küçük Türe Dönüştürülmesi: Büyük türlerin küçük türlere otomatik dönüştürülmesi C#’da yasaklanmıştır. Eğer bu tür bir dönüstürme(bilinçsiz olarak) mümkün olsaydı bir takim veri kayıpları yaşanacaktır.
Aşağıda bilinçsiz tür dönüşümüne örnek verilmiştir.
|
23 Mayıs 2013 Perşembe
Ağ kablosu nasıl hazırlanır?
Bir ağ kablosu hazırlamadan önce kablonun hangi amaçla kullanılacağına karar vermemiz gerekiyor. Kabloyu bir bilgisayar ile herhangi bir ağ cihazı arasında kullanacaksak düz bağlantı yapmalıyız. Eğer kabloyu iki bilgisayar arasında kullanacaksak (kablonun bir ucu A bilgisayarına takılı iken diğer ucuda B bilgisayarına takılacak ise) cross (çapraz) kablo kullanmalıyız. Yazımın devamında düz bağlantı renkleri, cross (çapraz) bağlantı renk sırası ve bu kabloları hazırlarken kullanacağımız rj45 konnektör, utp cat5 kablo ve sıkma pensesi hakkında açıklamaları bulabilirsiniz.
Cross kablo yada düz kablo kullanacakta olsak kullanacağımız malzemeler değişmeyecektir :
- Yeterli uzunlukta UTP Cat5 kablo
- Utp kablonun her iki ucuna takacağım Rj45 konnektör (tek seferde sorunsuz yaparım diyorsanız 2 tane yeterli)
- Rj45 konnektörleri kabloya çakmak (yada takmak) için kablo sıkma pensesi.
Çapraz bağlantı ve düz bağlantı renklerini vermeden önce bu malzemeleri çok kısa resimli olarak tanıtmak istiyorum.
1. UTP CAT5 KABLO
Bilgisayar ağlarında yaygın olarak kullanılan kablo tipi UTP kablodur. UTP kablolar belirli bir mesafede üzerinde taşıyabileceği veri miktarına göre cat1 den başlayarak cat7 ye kadar kategorilere ayrılır. Günümüzde neredeyse bütün bilgisayar ağlarında cat5 kablo kullanılır. 100 metreyi aşmayacak şekilde hazırlanan bir cat5 kablo 100Mbps’ lik veri taşıyabilir. Buda cat5 kablolar ile saniyede en fazla 100Mb veri aktarılabileceği anlamına gelir. Utp kablo içerisinde 8 adet renkli ince kablo bulunur. Hazırlayacağımız kablonun cross yada düz bağlantı olmasına göre bu 8 kablonun renk sırası farklılık gösterir.
2. RJ45 KONNEKTÖR
Utp Cat5 kablo içerisindeki kablolar doğru renk sırasıyla Rj45 konnektöre yerleştirilir. Bunun için Rj45 konnektör içerisinde 8 adet giriş vardır. Utp kablo içerisindeki 8 ince kablo bu girişlere doğru şekilde yerleştirilir. Bu yerleştirme işleminden önce kabloların uçları Rj45 konnektörün içerisindeki iletkenlere temas edecek kadar soyulur. Bu soyma işleminde kablo sıkma pensesinden faydalanabilirsiniz.
3. KABLO SIKMA PENSESİ
Yeteri kadar soyduğumuz ince kabloları doğru renk sırasıyla Rj45 konnektöre yerleştirdikten sonra yine aynı pense ile utp cat5 kablo ve Rj45 konnektörü sıkıştırıyoruz.
Kablo hazırlama işlemi sırasında kullanacağımız olmazsa olmaz olan 3 materyali tanıttıktan sonra kablolarımızdaki renk sıralarına geçiyoruz. İki kablo türü arasındaki farkı yazımın giriş kısmında vermiştim.
Düz Bağlantı Renk Sırası
Eğer hazırladığınız ağ kablosunu bir bilgisayardan bir ağ cihazına (modem, switch, hub vs.) bağlayacaksanız düz bağlantı kullanılmalıdır. Düz bağlantının özelliği kablonun her iki ucundada aynı renk sırasını kullanıyor olmamızdır. Bu renk sırasını uluslar arası standarda göre hazırlayabileceğiniz gibi her iki uçtaki renklerin sırasının aynı olması şartıyla istediğiniz bir sırayla da hazırlayabilirsiniz. Genel olarak kullanılan düz bağlantı renk sırası aşağıdaki gibidir. Resimdeki her iki uçtada renk sırasının aynı olduğuna dikkat ediniz.
Turuncu –Beyaz (TB)
Turuncu (T)
Yeşil – Beyaz (YB)
Mavi (M)
Mavi – Beyaz (MB)
Yeşil (Y)
Kahverengi – Beyaz (KB)
Kahverengi (K)
Cross (Çapraz Bağlantı Renk Sırası)
Çapraz Bağlantı Nedir? Cross Bağlantı Nasıl Hazırlanır?
Hazırlayacağınız ağ kablosunu iki bilgisayar arasında kullanacaksanız (arada hiçbir ağ cihazı bulunmadan, bir bilgisayardan diğerine takacaksanız) çapraz bağlantıyı tercih etmelisiniz. Bu durumda Ethernet kablonuzun bir ucunu düz bağlantıda renk sırasıyla hazırlarken diğer ucunda ise 1 ve 3. renkler ile 2 ve 6.renkler yer değiştirecek şekilde bağlamalısınız. Çapraz (cross) bağlantı renk dizilimi aşağıdaki gibi olmalıdır.
Kablonun 1.ucu Kablonun 2. ucu
Turuncu –Beyaz (TB) Yeşil-Beyaz (YB)
Turuncu (T) Yeşil (Y)
Yeşil – Beyaz (YB) Turuncu – Beyaz (TB)
Mavi (M) Mavi (M)
Mavi – Beyaz (MB) Mavi – Beyaz (MB)
Yeşil (Y) Turuncu (T)
Kahverengi – Beyaz (KB) Kahverengi – Beyaz (KB)
Kahverengi (K) Kahverengi (K)
22 Mayıs 2013 Çarşamba
VISUAL STUDIO KLAVYE KISAYOLLARI
Ctrl+K, Ctrl+D
Dökümanı düzenle
Ctrl+K, Ctrl+C
Seçili kodu yorum satırı (Comment) yap
Ctrl+K, Ctrl+U
Yorum satırı yapma işlemini geri al (Uncomment)
Ctrl+K, Ctrl+X
Hazır kod ekleme (Insert Snippet) seçeneklerini görüntüle
Ctrl+M
Kod blogunu (nodunu) aç (kapalıysa), kapat (açıksa)
Ctrl+M, Ctrl+O
Bütün kod bloglarını (nodları) kapat
Shift+F7
Designer görünümüne geç
F7
Kod görünümüne geç
F5
Hata ayıklama (Debug) işlemini başlat
Ctrl+F5
Hata ayıklama yapmadan başlat
F11
Hata ayıklamada sonraki satıra geç
F10
Hata ayıklamada sonraki satıra (metotları takip etmeden) geç
Ctrl+Shift+F5
Yeniden başlat
Ctrl+F
Bul ve Değiştir (Find and Replace) ekranını aç
Ctrl+H
Değiştir (Replace) ekranını aç
F1
Seçili öğe için arama yap
F4
Properties (Özellikler) ekranını aç
Ctrl+Alt+S
Server Explorer’ı aç
Ctrl+Alt+L
Solution Explorer’ı aç
Ctrl+Alt+X
Toolbox’ı (Araçlar) aç
Ctrl+Shift+A
Add New Item (Projeye yeni bir dosya ekle ) penceresini aç
Shift+Alt+A
Add Existing Item (Projeye Visual Studio dosyası ekle) penceresini aç
Ctrl+Shift+B
Projeyi derle (Build)
Ctrl+N
Yeni bir dosya oluşturma penceresini aç
Ctrl+Shift+N
Yeni bir proje oluşturma penceresini aç
Ctrl+F4
Açık olan dosyayı kapat
Shift+Esc
Toolbox’ı (Araçlar) kapat
Ctrl+F6
Açık olan dosyalar arasında gez
Ctrl+Tab
Açık olan dosyalar arasında gezinme penceresini aç
Alt+Shift+F10
Kütüphaneyi referans olarak ekle
Alt+Shift+Enter
Tam ekran moduna geç
Aşağıda ekran görüntüsü bulunan Microsoft tarafından hazırlanmış olan Pdf formatındaki klavye kısayolları dosyaları da oldukça faydalı olacaktır.
Kaydol:
Kayıtlar (Atom)