Tanımlama grubu türleri (C# başvurusu)
Tanımlama grupları özelliği, basit bir veri yapısında birden çok veri öğesini gruplandırmak için kısa söz dizimi sağlar. Aşağıdaki örnek, bir tanımlama grubu değişkenini nasıl bildirebileceğinizi, başlatabileceğinizi ve veri üyelerine nasıl erişebileceğinizi gösterir:
(double, int) t1 = (4.5, 3);
Console.WriteLine($"Tuple with elements {t1.Item1} and {t1.Item2}.");
// Output:
// Tuple with elements 4.5 and 3.
(double Sum, int Count) t2 = (4.5, 3);
Console.WriteLine($"Sum of {t2.Count} elements is {t2.Sum}.");
// Output:
// Sum of 3 elements is 4.5.
Yukarıdaki örnekte gösterildiği gibi, bir tanımlama grubu türünü tanımlamak için tüm veri üyelerinin türlerini ve isteğe bağlı olarak alan adlarını belirtirsiniz. Bir tanımlama grubu türünde yöntem tanımlayamazsınız, ancak aşağıdaki örnekte gösterildiği gibi .NET tarafından sağlanan yöntemleri kullanabilirsiniz:
(double, int) t = (4.5, 3);
Console.WriteLine(t.ToString());
Console.WriteLine($"Hash code of {t} is {t.GetHashCode()}.");
// Output:
// (4.5, 3)
// Hash code of (4.5, 3) is 718460086.
Tanımlama grubu türleri eşitlik işleçlerini ve !=
' ==
ı destekler. Daha fazla bilgi için Demet eşitliği bölümüne bakın.
Tanımlama grubu türleri değer türleridir; tanımlama grubu öğeleri genel alanlardır. Bu, demetleri değiştirilebilir değer türleri yapar.
Rastgele çok sayıda öğeyle tanımlama demetleri tanımlayabilirsiniz:
var t =
(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);
Console.WriteLine(t.Item26); // output: 26
Tanımlama grubu kullanım örnekleri
Tanımlama demetlerinin en yaygın kullanım örneklerinden biri yöntem dönüş türüdür. Diğer bir ifadeyle, yöntem parametrelerini tanımlamak out
yerine, aşağıdaki örnekte gösterildiği gibi yöntem sonuçlarını bir tanımlama grubu dönüş türünde gruplandırabilirsiniz:
int[] xs = new int[] { 4, 7, 9 };
var limits = FindMinMax(xs);
Console.WriteLine($"Limits of [{string.Join(" ", xs)}] are {limits.min} and {limits.max}");
// Output:
// Limits of [4 7 9] are 4 and 9
int[] ys = new int[] { -9, 0, 67, 100 };
var (minimum, maximum) = FindMinMax(ys);
Console.WriteLine($"Limits of [{string.Join(" ", ys)}] are {minimum} and {maximum}");
// Output:
// Limits of [-9 0 67 100] are -9 and 100
(int min, int max) FindMinMax(int[] input)
{
if (input is null || input.Length == 0)
{
throw new ArgumentException("Cannot find minimum and maximum of a null or empty array.");
}
// Initialize min to MaxValue so every value in the input
// is less than this initial value.
var min = int.MaxValue;
// Initialize max to MinValue so every value in the input
// is greater than this initial value.
var max = int.MinValue;
foreach (var i in input)
{
if (i < min)
{
min = i;
}
if (i > max)
{
max = i;
}
}
return (min, max);
}
Yukarıdaki örnekte gösterildiği gibi, döndürülen tanımlama grubu örneğiyle doğrudan çalışabilir veya ayrı değişkenlerde bu tanımlama grubu örneğinin yapısını kaldırabilirsiniz .
Ayrıca anonim türler yerine tanımlama grubu türlerini de kullanabilirsiniz; örneğin LINQ sorgularında. Daha fazla bilgi için bkz . Anonim ve tanımlama grubu türleri arasında seçim yapma.
Genellikle, gevşek ilişkili veri öğelerini gruplandırmak için tanımlama grupları kullanırsınız. Genel API'lerde bir sınıf veya yapı türü tanımlamayı göz önünde bulundurun.
Tanımlama grubu alan adları
Aşağıdaki örnekte gösterildiği gibi, tanımlama grubu başlatma ifadesinde veya tanımlama grubu türünün tanımında demet alanları adlarını açıkça belirtirsiniz:
var t = (Sum: 4.5, Count: 3);
Console.WriteLine($"Sum of {t.Count} elements is {t.Sum}.");
(double Sum, int Count) d = (4.5, 3);
Console.WriteLine($"Sum of {d.Count} elements is {d.Sum}.");
Bir alan adı belirtmezseniz, aşağıdaki örnekte gösterildiği gibi bir tanımlama grubu başlatma ifadesindeki karşılık gelen değişkenin adından çıkarılabilir:
var sum = 4.5;
var count = 3;
var t = (sum, count);
Console.WriteLine($"Sum of {t.count} elements is {t.sum}.");
Buna tanımlama grubu projeksiyon başlatıcıları denir. Bir değişkenin adı, aşağıdaki durumlarda bir tanımlama grubu alan adına yansıtılamaz:
- Aday adı, bir tanımlama grubu türünün üye adıdır; örneğin,
Item3
,ToString
veyaRest
. - Aday adı, açık veya örtük başka bir tanımlama grubu alan adının yinelemesidir.
Önceki durumlarda, bir alanın adını açıkça belirtirsiniz veya bir alana varsayılan adıyla erişebilirsiniz.
Tanımlama grubu alanlarının varsayılan adları , Item2
ve Item3
benzeridirItem1
. Aşağıdaki örnekte gösterildiği gibi, bir alan adı açıkça belirtildiğinde veya çıkarıldığında bile her zaman alanın varsayılan adını kullanabilirsiniz:
var a = 1;
var t = (a, b: 2, 3);
Console.WriteLine($"The 1st element is {t.Item1} (same as {t.a}).");
Console.WriteLine($"The 2nd element is {t.Item2} (same as {t.b}).");
Console.WriteLine($"The 3rd element is {t.Item3}.");
// Output:
// The 1st element is 1 (same as 1).
// The 2nd element is 2 (same as 2).
// The 3rd element is 3.
Tanımlama grubu ataması ve tanımlama grubu eşitliği karşılaştırmaları alan adlarını hesaba katmıyor.
Derleme zamanında, derleyici varsayılan olmayan alan adlarını karşılık gelen varsayılan adlarla değiştirir. Sonuç olarak, açıkça belirtilen veya çıkarsanan alan adları çalışma zamanında kullanılamaz.
İpucu
Çıkarsanan veya açık tanımlama grubu alan adlarında bir tercih ayarlamak için .NET kod stili kuralı IDE0037 etkinleştirin.
C# 12 ile başlayarak, yönergesi olan bir tanımlama grubu türü için bir using
diğer ad belirtebilirsiniz. Aşağıdaki örnek, izin verilen Min
ve global using
Max
değer için iki tamsayı değeri içeren bir tanımlama grubu türü için diğer ad ekler:
global using BandPass = (int Min, int Max);
Diğer adı bildirdikten sonra, bu tanımlama grubu türü için diğer ad olarak kullanabilirsiniz BandPass
:
BandPass bracket = (40, 100);
Console.WriteLine($"The bandpass filter is {bracket.Min} to {bracket.Max}");
Diğer ad yeni bir tür sunmaz, ancak yalnızca var olan bir tür için eş anlamlı oluşturur. Diğer adla BandPass
bildirilen bir tanımlama kümesini, temel alınan tanımlama grubu türüyle yaptığınız gibi çözebilirsiniz:
(int a , int b) = bracket;
Console.WriteLine($"The bracket is {a} to {b}");
Tanımlama grubu ataması veya yapısızlaştırmada olduğu gibi, tanımlama grubu üye adlarının eşleşmesi gerekmez; türleri bunu yapar.
Benzer şekilde, aynı arity ve üye türlerine sahip ikinci bir diğer ad, özgün diğer adla birbirinin yerine kullanılabilir. İkinci bir diğer ad bildirebilirsiniz:
using Range = (int Minimum, int Maximum);
Tanımlama grubuna bir BandPass
tanımlama grubu atayabilirsinizRange
. Tüm tanımlama grubu atamaları gibi, alan adlarının eşleşmesi gerekmez, yalnızca türler ve arity gerekir.
Range r = bracket;
Console.WriteLine($"The range is {r.Minimum} to {r.Maximum}");
Tanımlama grubu türünün diğer adı, tanımlama kümeleri kullandığınızda daha fazla anlam bilgisi sağlar. Yeni bir tür sunmaz. Tür güvenliği sağlamak için bunun yerine bir konumsal record
bildirmeniz gerekir.
Tanımlama grubu ataması ve yapısı kaldırma
C# aşağıdaki koşulların her ikisini de karşılayan tanımlama grubu türleri arasında atamayı destekler:
- her iki tanımlama grubu türü de aynı sayıda öğeye sahiptir
- her tanımlama grubu konumu için sağ taraftaki tanımlama grubu öğesinin türü, karşılık gelen sol tanımlama grubu öğesinin türüyle aynıdır veya örtük olarak dönüştürülebilir
Tanımlama grubu öğesi değerleri, tanımlama grubu öğelerinin sırasına göre atanır. Aşağıdaki örnekte gösterildiği gibi, tanımlama grubu alanlarının adları yoksayılır ve atanamaz:
(int, double) t1 = (17, 3.14);
(double First, double Second) t2 = (0.0, 1.0);
t2 = t1;
Console.WriteLine($"{nameof(t2)}: {t2.First} and {t2.Second}");
// Output:
// t2: 17 and 3.14
(double A, double B) t3 = (2.0, 3.0);
t3 = t2;
Console.WriteLine($"{nameof(t3)}: {t3.A} and {t3.B}");
// Output:
// t3: 17 and 3.14
Ayrıca atama işlecini =
kullanarak bir tanımlama grubu örneğini ayrı değişkenlerde de oluşturabilirsiniz . Bunu birçok yolla yapabilirsiniz:
var
Örtük olarak yazılan değişkenleri bildirmek ve derleyicinin türlerini çıkarmasına izin vermek için parantez dışında anahtar sözcüğünü kullanın:var t = ("post office", 3.6); var (destination, distance) = t; Console.WriteLine($"Distance to {destination} is {distance} kilometers."); // Output: // Distance to post office is 3.6 kilometers.
Her değişkenin türünü parantez içinde açıkça bildirin:
var t = ("post office", 3.6); (string destination, double distance) = t; Console.WriteLine($"Distance to {destination} is {distance} kilometers."); // Output: // Distance to post office is 3.6 kilometers.
Bazı türleri açıkça ve diğer türleri parantez içinde örtük olarak (ile
var
) bildirin:var t = ("post office", 3.6); (var destination, double distance) = t; Console.WriteLine($"Distance to {destination} is {distance} kilometers."); // Output: // Distance to post office is 3.6 kilometers.
Mevcut değişkenleri kullanın:
var destination = string.Empty; var distance = 0.0; var t = ("post office", 3.6); (destination, distance) = t; Console.WriteLine($"Distance to {destination} is {distance} kilometers."); // Output: // Distance to post office is 3.6 kilometers.
Bir yapısızlaştırma ifadesinin hedefi, hem var olan değişkenleri hem de yapısızlaştırma bildiriminde bildirilen değişkenleri içerebilir.
Bir tanımlama grubundaki alanların özelliklerini incelemek için yapısızlaştırmayı desen eşleştirme ile de birleştirebilirsiniz. Aşağıdaki örnek birkaç tamsayı arasında döngü yapar ve 3 ile bölünebilenleri yazdırır. Tanımlama grubu sonucunu Int32.DivRem ve 0 ile eşleşir Remainder
:
for (int i = 4; i < 20; i++)
{
if (Math.DivRem(i, 3) is ( Quotient: var q, Remainder: 0 ))
{
Console.WriteLine($"{i} is divisible by 3, with quotient {q}");
}
}
Tanımlama demetlerinin ve diğer türlerin yapısı hakkında daha fazla bilgi için bkz . Tanımlama demetlerini ve diğer türleri yapılandırma.
Tanımlama grubu eşitliği
Tanımlama grubu türleri ve !=
işleçlerini ==
destekler. Bu işleçler, tanımlama grubu öğelerinin sırasını izleyerek sol işlenenin üyelerini sağ işlenenin ilgili üyeleriyle karşılaştırır.
(int a, byte b) left = (5, 10);
(long a, int b) right = (5, 10);
Console.WriteLine(left == right); // output: True
Console.WriteLine(left != right); // output: False
var t1 = (A: 5, B: 10);
var t2 = (B: 5, A: 10);
Console.WriteLine(t1 == t2); // output: True
Console.WriteLine(t1 != t2); // output: False
Yukarıdaki örnekte gösterildiği gibi ve !=
işlemleri tanımlama ==
grubu alan adlarını dikkate almaz.
Aşağıdaki koşulların her ikisi de karşılandığında iki tanımlama grubu karşılaştırılabilir:
- Her iki tanımlama grubu da aynı sayıda öğeye sahiptir. Örneğin,
t1 != t2
farklı sayıda öğe varsa vet2
varsat1
derlemez. - Her tanımlama grubu konumu için, sol ve sağ tanımlama grubu işlenenlerindeki karşılık gelen öğeler ve
!=
işleçleriyle==
karşılaştırılabilir. Örneğin,(1, (2, 3)) == ((1, 2), 3)
ile(1, 2)
karşılaştırılabilir olmadığından derlenmemiştir1
.
==
ve !=
işleçleri demetleri kısa devre yöntemiyle karşılaştırır. Diğer bir ifadeyle, bir işlem eşit olmayan bir öğe çiftini karşılar veya tanımlama demetlerinin uçlarına ulaşır ulaşmaz durur. Ancak, herhangi bir karşılaştırmadan önce, aşağıdaki örnekte gösterildiği gibi tüm tanımlama grubu öğeleri değerlendirilir:
Console.WriteLine((Display(1), Display(2)) == (Display(3), Display(4)));
int Display(int s)
{
Console.WriteLine(s);
return s;
}
// Output:
// 1
// 2
// 3
// 4
// False
Dış parametre olarak demetler
Genellikle, bir tanımlama grubu döndüren out
bir yöntemde parametreleri olan bir yöntemi yeniden düzenlemeniz gerekir. Ancak, bir out
parametrenin tanımlama grubu türünde olabileceği durumlar vardır. Aşağıdaki örnekte, tanımlama demetleriyle parametre olarak out
çalışma gösterilmektedir:
var limitsLookup = new Dictionary<int, (int Min, int Max)>()
{
[2] = (4, 10),
[4] = (10, 20),
[6] = (0, 23)
};
if (limitsLookup.TryGetValue(4, out (int Min, int Max) limits))
{
Console.WriteLine($"Found limits: min is {limits.Min}, max is {limits.Max}");
}
// Output:
// Found limits: min is 10, max is 20
Tanımlama demetleri ve System.Tuple
Türler tarafından System.ValueTuple desteklenen C# demetleri, türlerle temsil edilen System.Tuple demetlerden farklıdır. Başlıca farklar şunlardır:
System.ValueTuple
türleri değer türleridir.System.Tuple
türleri başvuru türleridir.System.ValueTuple
türleri değişebilir.System.Tuple
türleri sabittir.- Türlerin
System.ValueTuple
veri üyeleri alanlardır. TürlerinSystem.Tuple
veri üyeleri özelliklerdir.
C# dili belirtimi
Daha fazla bilgi için bkz.