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 = [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 = [-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, ToStringveya Rest.
  • 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ı , Item2ve 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 usingMax 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 ve t2 varsa t1 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.ValueTupletürleri değer türleridir. System.Tupletü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ürlerin System.Tuple veri üyeleri özelliklerdir.

C# dili belirtimi

Daha fazla bilgi için bkz.

Ayrıca bkz.