Not
Bu sayfaya erişim yetkilendirme gerektiriyor. Oturum açmayı veya dizinleri değiştirmeyi deneyebilirsiniz.
Bu sayfaya erişim yetkilendirme gerektiriyor. Dizinleri değiştirmeyi deneyebilirsiniz.
Tavsiye
Yazılım geliştirme konusunda yeni misiniz? İlk olarak Başlangıç öğreticileri ile başlayın. gibi List<T>koleksiyonları kullanır kullanmaz genel türlerle karşılaşırsınız.
Başka bir dilde mi deneyimlisiniz? C# jenarikler, Java jenariklerine veya C++ şablonlarına benzer, ancak tam çalışma zamanı türü bilgilerinden faydalanır ve tür silinmesi olmaz. C#'ye özgü desenleri bulmak için koleksiyon ifadeleri ve kovaryans ve kontravaryans bölümlerini gözden geçirin.
Genel değerler , tam tür güvenliğini koruyarak herhangi bir türle çalışan kod yazmanıza olanak sağlar. Ayrı sınıflar veya yöntemler yazmak yerine int, string ve ihtiyaç duyduğunuz diğer her tür için, bir veya daha fazla tür parametresiyle (T, veya TKey ve TValue gibi) bir sürüm yazın ve kullandığınızda gerçek türleri belirtin. Derleyici derleme zamanında türleri denetler, bu nedenle çalışma zamanı atamalarına veya risklerine InvalidCastExceptionihtiyacınız yoktur.
Günlük C# dilinde sürekli olarak genel değerlerle karşılaşırsınız. Koleksiyonlar, asenkron dönüş türleri, delegeler ve LINQ hepsi genel türlere dayanır:
List<int> scores = [95, 87, 72, 91];
Dictionary<string, decimal> prices = new()
{
["Widget"] = 19.99m,
["Gadget"] = 29.99m
};
Task<string> greeting = Task.FromResult("Hello, generics!");
Func<int, bool> isPositive = n => n > 0;
Console.WriteLine($"First score: {scores[0]}");
Console.WriteLine($"Widget price: {prices["Widget"]:C}");
Console.WriteLine($"Greeting: {await greeting}");
Console.WriteLine($"Is 5 positive? {isPositive(5)}");
Her durumda, açılı köşeli ayraçlardaki tür bağımsız değişkeni (<int>, <string>, <Product>), genel tipe hangi türde veriler tuttuğunu veya işlettiğini bildirir. Derleyici tür güvenliğini sağlar. Yanlışlıkla bir string'i bir List<int>'e ekleyemezsiniz.
Genel türleri kullanma
Daha sık olarak, kendi sınıf kitaplığınızı oluşturmak yerine .NET sınıf kitaplığından genel türleri tüketirsiniz. Aşağıdaki bölümlerde kullanacağınız en yaygın genel türler gösterilmektedir.
Genel koleksiyonlar
Ad alanı System.Collections.Generic, tür güvenli koleksiyon sınıfları sağlar. Gibi ArrayListgenel olmayan koleksiyonlar yerine her zaman bu koleksiyonları kullanın:
// A strongly typed list of strings
List<string> names = ["Alice", "Bob", "Carol"];
names.Add("Dave");
// names.Add(42); // Compile-time error: can't add an int to List<string>
// A dictionary mapping string keys to int values
var inventory = new Dictionary<string, int>
{
["Apples"] = 50,
["Oranges"] = 30
};
inventory["Bananas"] = 25;
// A set that prevents duplicates
HashSet<int> uniqueIds = [1, 2, 3, 1, 2];
Console.WriteLine($"Unique count: {uniqueIds.Count}"); // 3
// A FIFO queue
Queue<string> tasks = new();
tasks.Enqueue("Build");
tasks.Enqueue("Test");
Console.WriteLine($"Next task: {tasks.Dequeue()}"); // Build
Genel koleksiyonlar, tür hatalarının çalışma zamanında oluşmasını engeller çünkü bu hatalar bunun yerine derleme zamanında ortaya çıkar. Bu koleksiyonlar ayrıca değer türleri için kutulama yapmaktan kaçınarak performansı artırır.
Genel yöntemler
Genel bir yöntem kendi tür parametresini bildirir. Derleyici genellikle geçirdiğiniz değerlerden tür bağımsız değişkenini çıkardığından açıkça belirtmeniz gerekmez:
static void Print<T>(T value) =>
Console.WriteLine($"Value: {value}");
Print(42); // Compiler infers T as int
Print("hello"); // Compiler infers T as string
Print(3.14); // Compiler infers T as double
ÇağrıPrint(42) sırasında, derleyici bağımsız değişkenden T'i int olarak sonuçlandırır. Açıkça yazabilirsiniz Print<int>(42) , ancak tür çıkarımı kodu daha temiz tutar.
Koleksiyon ifadeleri
Koleksiyon ifadeleri (C# 12), koleksiyon oluşturmak için kısa bir söz dizimi sağlar. Oluşturucu çağrıları veya başlatıcı söz dizimi yerine köşeli ayraç kullanın:
// Create a list with a collection expression
List<string> fruits = ["Apple", "Banana", "Cherry"];
// Create an array
int[] numbers = [1, 2, 3, 4, 5];
// Works with any supported collection type
IReadOnlyList<double> temperatures = [72.0, 68.5, 75.3];
Console.WriteLine($"Fruits: {string.Join(", ", fruits)}");
Console.WriteLine($"Numbers: {string.Join(", ", numbers)}");
Console.WriteLine($"Temps: {string.Join(", ", temperatures)}");
Spread işleci (..), bir koleksiyonun öğelerini başka bir koleksiyona yayar ve bu, dizileri birleştirmek için kullanışlıdır.
List<int> first = [1, 2, 3];
List<int> second = [4, 5, 6];
// Spread both lists into a new combined list
List<int> combined = [.. first, .. second];
Console.WriteLine(string.Join(", ", combined));
// Output: 1, 2, 3, 4, 5, 6
// Add extra elements alongside spreads
List<int> withExtras = [0, .. first, 99, .. second];
Console.WriteLine(string.Join(", ", withExtras));
// Output: 0, 1, 2, 3, 99, 4, 5, 6
Koleksiyon ifadeleri diziler, List<T>, Span<T>, ImmutableArray<T>ve koleksiyon oluşturucu desenini destekleyen herhangi bir türle çalışır. Tam söz dizimi başvurusu için bkz. Koleksiyon ifadeleri.
Sözlük başlatma
Sözlükleri dizin oluşturucu başlatıcılarıyla kısa bir şekilde başlatabilirsiniz. Bu söz diziminde anahtar-değer çiftlerini ayarlamak için köşeli ayraçlar kullanılır:
Dictionary<string, int> scores = new()
{
["Alice"] = 95,
["Bob"] = 87,
["Carol"] = 92
};
foreach (var (name, score) in scores)
{
Console.WriteLine($"{name}: {score}");
}
Bir sözlük kopyalayıp geçersiz kılmalar uygulayarak sözlükleri birleştirebilirsiniz:
Dictionary<string, int> defaults = new()
{
["Timeout"] = 30,
["Retries"] = 3
};
Dictionary<string, int> overrides = new()
{
["Timeout"] = 60
};
// Merge defaults and overrides into a new dictionary
Dictionary<string, int> config = new(defaults);
foreach (var (key, value) in overrides)
{
config[key] = value;
}
Console.WriteLine($"Timeout: {config["Timeout"]}"); // 60
Console.WriteLine($"Retries: {config["Retries"]}"); // 3
Tür kısıtlamaları
Kısıtlamalar, bir genel türün veya yöntemin kabul ettiği tür bağımsız değişkenlerini sınırlar. Kısıtlamalar, tür parametresinde tek başına kullanılamayabilecek object yöntemleri çağırmanıza veya özelliklere erişmenize olanak sağlar:
static T Max<T>(T a, T b) where T : IComparable<T> =>
a.CompareTo(b) >= 0 ? a : b;
Console.WriteLine(Max(3, 7)); // 7
Console.WriteLine(Max("apple", "banana")); // banana
static T CreateDefault<T>() where T : new() => new T();
var list = CreateDefault<List<int>>(); // Creates an empty List<int>
Console.WriteLine($"Empty list count: {list.Count}"); // 0
En yaygın kısıtlamalar şunlardır:
| Kısıtlama | Anlamı |
|---|---|
where T : class |
T bir başvuru türü olmalıdır |
where T : struct |
T null atanamayan bir değer türü olmalıdır |
where T : new() |
T ortak bir parametresiz oluşturucuya sahip olmalıdır |
where T : BaseClass |
T şu kaynaktan türetilmelidir: BaseClass |
where T : IInterface |
T uygulamak zorundadır IInterface |
Kısıtlamaları birleştirebilirsiniz: where T : class, IComparable<T>, new(). Daha az yaygın sınırlamalar, özel senaryolar için where T : System.Enum, where T : System.Delegate ve where T : unmanaged içerir. Listenin tamamı için bkz. Tür parametrelerindeki kısıtlamalar.
Kovaryans ve kontravaryans
Kovaryans ve kontravaryans , genel türlerin devralma ile nasıl davrandığını açıklar. Başlangıçta belirtilenden daha fazla veya daha az türetilmiş bir tür bağımsız değişkeni kullanıp kullanamayacağınızı onlar belirler.
// Covariance: IEnumerable<Dog> can be used as IEnumerable<Animal>
// because IEnumerable<out T> is covariant
List<Dog> dogs = [new("Rex"), new("Buddy")];
IEnumerable<Animal> animals = dogs; // Allowed because Dog derives from Animal
foreach (var animal in animals)
{
Console.WriteLine(animal.Name);
}
// Contravariance: Action<Animal> can be used as Action<Dog>
// because Action<in T> is contravariant
Action<Animal> printAnimal = a => Console.WriteLine($"Animal: {a.Name}");
Action<Dog> printDog = printAnimal; // Allowed because any Animal handler can handle Dog
printDog(new Dog("Spot"));
-
Kovaryans (
out T): ÇünküDog,Animal'den türetilmiştir,IEnumerable<Animal>yerineIEnumerable<Dog>kullanılabilir.outtür parametresindeki anahtar sözcük bunu etkinleştirir. Kovarant tür parametreleri yalnızca çıkış konumlarında (dönüş türleri) görünebilir. -
Kontravaryans (
in T): BirAction<Animal>ınAction<Dog>ın beklendiği yerde kullanılabilmesi mümkündür çünküAction<Dog>'ü işleyebilen herhangi bir işlemDog'i de işleyebilir. anahtarinsözcüğü bunu etkinleştirir. Kontravaryant tür parametreleri yalnızca giriş konumlarında (parametreler) görünebilir.
Birçok yerleşik arabirim ve temsilci zaten değişkendir: IEnumerable<out T>, IReadOnlyList<out T>, Func<out TResult>ve Action<in T>. Bu türlerle çalışırken varyanstan otomatik olarak yararlanabilirsiniz. Değişken arabirimleri ve temsilciler tasarlamaya yönelik ayrıntılı bir işlem için bkz. Kovaryans ve ters değişken.
Kendi genel türlerinizi oluşturma
Kendi genel sınıflarınızı, yapılarınızı, arabirimlerinizi ve yöntemlerinizi tanımlayabilirsiniz. Aşağıdaki örnekte, çizim için basit bir genel bağlantılı liste gösterilmektedir. Uygulamada List<T> veya başka bir yerleşik koleksiyon kullanın.
public class GenericList<T>
{
private class Node(T data)
{
public T Data { get; set; } = data;
public Node? Next { get; set; }
}
private Node? head;
public void AddHead(T data)
{
var node = new Node(data) { Next = head };
head = node;
}
public IEnumerator<T> GetEnumerator()
{
var current = head;
while (current is not null)
{
yield return current.Data;
current = current.Next;
}
}
}
var list = new GenericList<int>();
for (var i = 0; i < 5; i++)
{
list.AddHead(i);
}
foreach (var item in list)
{
Console.Write($"{item} ");
}
Console.WriteLine();
// Output: 4 3 2 1 0
Genel türler sınıflar ile sınırlı değildir. Genel interface, structve record türlerini tanımlayabilirsiniz. Genel algoritmalar ve karmaşık kısıtlama bileşimleri tasarlama hakkında daha fazla bilgi için bkz. .NET'da