Aracılığıyla paylaş


Tanımlama kümeleri ve anonim türler

Tuple'lar, birden fazla üyeyi tek bir yapı içinde barındıran hafif bir veri yapısı sağlar. Bunlar anonim türlere göre tercih edilen seçenektir. Tanımlama kümeleri daha iyi performans sağlar, parçalamayı destekler ve daha esnek söz dizimi sunar.

Anonim türler, bir tür kümesini açıkça tanımlamak zorunda kalmadan tek bir nesnede salt okunur özellikler kümesini kapsüllemek için kullanışlı bir yol sağlar. Derleyici tür adını oluşturur ve kaynak kod düzeyinde kullanılamaz. Derleyici her özelliğin türünü çıkarsar. Öncelikle ifade ağacı desteğine ihtiyacınız olduğunda veya başvuru türleri gerektiren kodla çalışırken anonim türleri kullanın.

Tanımlama demetleri ile anonim türler karşılaştırması

Hem tupler hem de anonim türler, adlandırılmış bir tür tanımlamadan birden çok değeri gruplandırmanıza olanak sağlar. Ancak, demetler daha iyi bir dil desteğine sahiptir ve daha verimli bir veri yapısına derlenir. Aşağıdaki tabloda önemli farklar özetlemektedir:

Özellik Anonim türler Demetler
Türü Referans türü (class) Değer türü (struct)
Performance Yığın ayırma Yığın tahsisi (daha iyi performans)
Mutability Salt okunur özellikler Değiştirilebilir alanlar
Yapısızlaştırma Desteklenmez Destekleniyor
İfade ağaçları Destekleniyor Desteklenmez
Erişim değiştiricisi internal public
Üye adları Gerekli veya çıkarsanmış İsteğe bağlı (gibi Item1Item2varsayılan adlarla )

Demetler ne zaman kullanılmalı?

Şu durumlarda demetleri kullanın:

  • Yığın ayırma ile daha iyi performansa ihtiyacınız vardır.
  • Değerleri ayrı değişkenlere ayırmak istiyorsunuz.
  • Bir yöntemden birden çok değer döndürebilirsiniz.
  • İfade ağacı desteğine ihtiyacınız yoktur.

Aşağıdaki örnek, demetlerin daha temiz bir söz dizimi ile anonim türlere benzer işlevsellik sunduğunu göstermektedir:

// Tuple with named elements.
var tupleProduct = (Name: "Widget", Price: 19.99M);
Console.WriteLine($"Tuple: {tupleProduct.Name} costs ${tupleProduct.Price}");

// Equivalent example using anonymous types.
var anonymousProduct = new { Name = "Widget", Price = 19.99M };
Console.WriteLine($"Anonymous: {anonymousProduct.Name} costs ${anonymousProduct.Price}");

Tanımlama grubu yapısı

Bir demeti ayrı değişkenlere ayırarak, demet öğeleriyle tek tek çalışmak için kullanışlı bir yol sağlayabilirsiniz. C# demetleri çözümlemek için çeşitli yolları destekler.

static (string Name, int Age, string City) GetPersonInfo()
{
    return ("Alice", 30, "Seattle");
}
// Deconstruct using var for all variables
var (name, age, city) = GetPersonInfo();
Console.WriteLine($"{name} is {age} years old and lives in {city}");
// Output: Alice is 30 years old and lives in Seattle

// Deconstruct with explicit types
(string personName, int personAge, string personCity) = GetPersonInfo();
Console.WriteLine($"{personName}, {personAge}, {personCity}");

// Deconstruct into existing variables
string existingName;
int existingAge;
string existingCity;
(existingName, existingAge, existingCity) = GetPersonInfo();

// Deconstruct and discard unwanted values using the discard pattern (_)
var (name2, _, city2) = GetPersonInfo();
Console.WriteLine($"{name2} lives in {city2}");
// Output: Alice lives in Seattle

Yapısızlaştırma döngülerde ve desen eşleştirme senaryolarında kullanışlıdır:

var people = new List<(string Name, int Age)>
{
    ("Bob", 25),
    ("Carol", 35),
    ("Dave", 40)
};

foreach (var (personName2, personAge2) in people)
{
    Console.WriteLine($"{personName2} is {personAge2} years old");
}

Yöntem dönüş türü olarak tuple'lar

Demetlerin yaygın bir kullanım örneği, yöntem dönüş türü olarak kullanılmasıdır. Parametreleri out tanımlamak yerine, yöntem sonuçlarını bir dizi olarak gruplandırabilirsiniz. Adı olmadığından ve dönüş türü bildirilemediğinden, bir yöntemden anonim bir tür döndüremezsiniz.

Aşağıdaki örnek, yapılandırma aralıklarını döndürmek için sözlük aramalarıyla tüplerin kullanılmasını açıklar.

var configLookup = new Dictionary<int, (int Min, int Max)>()
{
    [2] = (4, 10),
    [4] = (10, 20),
    [6] = (0, 23)
};

if (configLookup.TryGetValue(4, out (int Min, int Max) range))
{
    Console.WriteLine($"Found range: min is {range.Min}, max is {range.Max}");
}
// Output: Found range: min is 10, max is 20

Bu düzen, hem başarı göstergesi hem de birden çok sonuç değeri döndürmesi gereken yöntemlerle çalışırken kullanışlıdır. Tanımlama grubu, Min ve Max gibi genel adlar yerine (Item1 ve Item2) adlandırılmış alanları kullanmanıza olanak tanır, bu da kodun daha okunabilir ve kendini dökümante edebilmesini sağlar.

Anonim türler ne zaman kullanılır?

Aşağıdaki durumlarda anonim türleri kullanın:

  • İfade ağaçlarıyla çalışıyorsunuz (örneğin, bazı Microsoft Dil-İçinde Sorgu (LINQ) sağlayıcılarında).
  • Nesnenin bir başvuru türü olması gerekir.

En yaygın senaryo, başka bir türdeki özelliklerle anonim bir tür başlatmaktır. Aşağıdaki örnekte adlı Productbir sınıfın mevcut olduğunu varsayalım. Sınıf Product, Color ve Price özelliklerini, ilgilenmediğiniz diğer özelliklerle birlikte içerir:

class Product
{
    public string? Color { get; init; }
    public decimal Price { get; init; }
    public string? Name { get; init; }
    public string? Category { get; init; }
    public string? Size { get; init; }
}

Anonim tür bildirimi, new operatörüyle birlikte bir nesne başlatıcı ifade ile başlar. Bildirimi, 'den Productyalnızca iki özellik kullanan yeni bir tür başlatır. Anonim türler genellikle sorgu ifadesinin select yan tümcesinde daha az miktarda veri döndürmek için kullanılır. Sorgular hakkında daha fazla bilgi için bkz . C# dilinde LINQ.

Anonim türde üye adları belirtmezseniz, derleyici anonim tür üyelerine bunları başlatmak için kullanılan özellikle aynı adı verir. Önceki örnekte gösterildiği gibi bir ifadeyle başlatılan bir özellik için bir ad sağlarsınız.

Aşağıdaki örnekte anonim türün özelliklerinin adları ve ColorşeklindedirPrice. Örnekler, tür koleksiyonundan productsProduct öğelerdir:

var productQuery =
    from prod in products
    select new { prod.Color, prod.Price };

foreach (var v in productQuery)
{
    Console.WriteLine("Color={0}, Price={1}", v.Color, v.Price);
}

Anonim türleri olan projeksiyon başlatıcıları

Anonim türler, üye adını açıkça belirtmeden doğrudan yerel değişkenleri veya parametreleri kullanmanızı sağlayan projeksiyon başlatıcılarını destekler. Derleyici, değişken adlarından üye adlarını çıkarsar. Aşağıdaki örnekte bu basitleştirilmiş söz dizimi gösterilmektedir:

// Explicit member names.
var personExplicit = new { FirstName = "Kyle", LastName = "Mit" };

// Projection initializers (inferred member names).
var firstName = "Kyle";
var lastName = "Mit";
var personInferred = new { firstName, lastName };

// Both create equivalent anonymous types with the same property names.
Console.WriteLine($"Explicit: {personExplicit.FirstName} {personExplicit.LastName}");
Console.WriteLine($"Inferred: {personInferred.firstName} {personInferred.lastName}");

Bu basitleştirilmiş söz dizimi, birçok özelliğe sahip anonim türler oluştururken kullanışlıdır:

var title = "Software Engineer";
var department = "Engineering";
var salary = 75000;

// Using projection initializers.
var employee = new { title, department, salary };

// Equivalent to explicit syntax:
// var employee = new { title = title, department = department, salary = salary };

Console.WriteLine($"Title: {employee.title}, Department: {employee.department}, Salary: {employee.salary}");

Üye adı aşağıdaki durumlarda çıkarılamaz:

  • Aday adı, açık veya örtük olarak aynı anonim türdeki başka bir özellik üyesini yineler.
  • Aday adı geçerli bir tanımlayıcı değildir (örneğin, boşluklar veya özel karakterler içerir).

Bu durumlarda, üye adını açıkça belirtmeniz gerekir.

İpucu

Çıkarsanan veya açık üye adlarının tercih edilip edilmediğini zorlamak için .NET stil kuralı IDE0037 kullanabilirsiniz.

Bir alanı başka bir türe sahip bir nesne kullanarak da tanımlayabilirsiniz: sınıf, yapı, hatta başka bir anonim tür. Bunu yapmak için bu nesneyi barındıran değişkeni kullanın. Aşağıdaki örnekte, önceden örnek oluşturulmuş kullanıcı tanımlı türleri kullanan iki anonim tür gösterilmektedir. Her iki durumda da, product anonim türdeki shipment ve shipmentWithBonus türündeki Product alan her alanın varsayılan değerlerini içerir. alanı bonus , derleyici tarafından oluşturulan anonim bir türdür.

var product = new Product();
var bonus = new { note = "You won!" };
var shipment = new { address = "Nowhere St.", product };
var shipmentWithBonus = new { address = "Somewhere St.", product, bonus };

Genellikle, bir değişkeni başlatmak için anonim bir tür kullandığınızda, değişkenini var kullanarak örtük olarak yazılan bir yerel değişken olarak bildirirsiniz. Yalnızca derleyicinin anonim türün temel adına erişimi olduğundan, değişken bildiriminde tür adını belirtemezsiniz. hakkında vardaha fazla bilgi için bkz . Örtük Olarak Yazılan Yerel Değişkenler.

Aşağıdaki örnekte gösterildiği gibi, örtük olarak yazılan bir yerel değişkeni ve örtük olarak yazılan bir diziyi birleştirerek anonim olarak yazılan öğeler dizisi oluşturabilirsiniz.

var anonArray = new[] { new { name = "apple", diam = 4 }, new { name = "grape", diam = 1 }};

Anonim türler, doğrudan class öğesinden türetilen türlerdir ve object dışında herhangi bir türe dönüştürülemezler. Derleyici, her anonim tür için bir ad sağlar, ancak uygulamanız bu türe erişemez. Ortak dil çalışma zamanı açısından bakıldığında, anonim bir tür diğer başvuru türlerinden farklı değildir.

Bir derlemedeki iki veya daha fazla anonim nesne başlatıcı aynı sırada ve aynı adlara ve türlere sahip bir özellik dizisi belirtirse, derleyici nesneleri aynı türde örnekler olarak ele alır. Derleyici tarafından oluşturulan aynı tür bilgilerini paylaşırlar.

Anonim türler, yıkıcı olmayan mutasyonu ifadeler biçiminde destekler. Bu özellik, bir veya daha fazla özelliğin yeni değerlere sahip olduğu anonim bir türün yeni bir örneğini oluşturmanıza olanak tanır:

var apple = new { Item = "apples", Price = 1.35 };
var onSale = apple with { Price = 0.79 };
Console.WriteLine(apple);
Console.WriteLine(onSale);

Bir alanı, özelliği, olayı veya yöntemin dönüş türünü anonim bir türe sahip olarak bildiremezsiniz. Benzer şekilde, bir yöntemin, özelliğin, oluşturucunun veya dizin oluşturucunun resmi parametresini anonim bir türe sahip olarak bildiremezsiniz. Anonim bir türü veya anonim türler içeren bir koleksiyonu bir yönteme bağımsız değişken olarak geçirmek için parametresini türü objectolarak bildirebilirsiniz. Ancak, anonim türler için kullanmak object güçlü yazma amacını yener. Sorgu sonuçlarını depolamanız veya yöntem sınırının dışına geçirmeniz gerekiyorsa, anonim bir tür yerine sıradan bir adlandırılmış yapı veya sınıf kullanmayı göz önünde bulundurun.

Equals Anonim türlerdeki ve GetHashCode yöntemleri özelliklerin Equals ve GetHashCode yöntemleri açısından tanımlandığından, aynı anonim türün iki örneği yalnızca tüm özellikleri eşitse eşittir.

Not

Anonim bir türün erişilebilirlik düzeyi şeklindedir internal. Bu nedenle, farklı derlemelerde tanımlanan iki anonim tür aynı türde değildir. Bu nedenle, anonim türlerin örnekleri, tüm özellikleri eşit olsa bile farklı derlemelerde tanımlandığında birbirine eşit olamaz.

Anonim türler, küme ayraçlarıyla çevrelenen her özelliğin adını ve ToString çıkışını birleştirerek yöntemini geçersiz kılarToString.

var v = new { Title = "Hello", Age = 24 };

Console.WriteLine(v.ToString()); // "{ Title = Hello, Age = 24 }"

Ayrıca bakınız