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.
Demet, bir yöntem çağrısından birden fazla değeri hafif bir şekilde almak için bir yol sağlar. Ancak demeti aldıktan sonra, onun bireysel öğelerini işlemeniz gerekir. Öğe bazında çalışmak, aşağıdaki örnekte de gösterildiği gibi, zahmetli bir süreçtir.
QueryCityData yöntemi üçlü döndürür ve öğelerinin her biri ayrı bir işlemde bir değişkene atanır.
public class Example
{
public static void Main()
{
var result = QueryCityData("New York City");
var city = result.Item1;
var pop = result.Item2;
var size = result.Item3;
// Do something with the data.
}
private static (string, int, double) QueryCityData(string name)
{
if (name == "New York City")
return (name, 8175133, 468.48);
return ("", 0, 0);
}
}
Bir nesneden birden çok alan ve özellik değeri almak da aynı derecede hantal olabilir: Bir değişkene üye bazında alan veya özellik değeri atamanız gerekir.
Bir demetten birden çok öğe veya tek bir yapıyı çözme operasyonunda bir nesneden birden çok alan, özellik ve hesaplanan değer alabilirsiniz. Bir tanımlama kümesinin yapısını çözmek için öğelerini bağımsız değişkenlere atarsınız. Bir nesnenin yapısını kaldırdığınızda, seçilen değerleri tek tek değişkenlere atarsınız.
Demetler
C#, bir tanım grubu içindeki tüm öğeleri tek bir işlemle çözmenize olanak tanıyan tanım gruplarını ayrıştırma için yerleşik desteğe sahiptir. Genel olarak bir kümeyi parçalama söz dizimi, bir küme tanımlama söz dizimi ile benzerdir: Her öğenin atanacağı değişkenleri, atama ifadesinin sol tarafında parantez içine alırsınız. Örneğin, aşağıdaki deyim dörtli bir tanımlama grubunun öğelerini dört ayrı değişkene atar:
var (name, address, city, zip) = contact.GetAddressInfo();
Bir tanımlama kümesinin yapısını kaldırmanın üç yolu vardır:
Her alanın türünü parantez içinde açıkça bildirebilirsiniz. Aşağıdaki örnek,
QueryCityDatayönteminden döndürülen üçlü yapısını çözmek için bu yaklaşımı kullanır.public static void Main() { (string city, int population, double area) = QueryCityData("New York City"); // Do something with the data. }C# öğesinin her değişkenin
vartürünü çıkarması için anahtar sözcüğünü kullanabilirsiniz. Anahtar sözcüğü parantezlerin dışına yerleştirirsinizvar. Aşağıdaki örnek,QueryCityDatayöntemi tarafından döndürülen üçlü parçalanırken tür çıkarımı kullanır.public static void Main() { var (city, population, area) = QueryCityData("New York City"); // Do something with the data. }Anahtar sözcüğünü
varparantez içindeki değişken bildirimlerinden herhangi biriyle veya tümüyle tek tek de kullanabilirsiniz.public static void Main() { (string city, var population, var area) = QueryCityData("New York City"); // Do something with the data. }Yukarıdaki örnek hantaldır ve önerilmez.
Son olarak, tanımlama demetini önceden bildirilen değişkenlere dönüştürebilirsiniz.
public static void Main() { string city = "Raleigh"; int population = 458880; double area = 144.8; (city, population, area) = QueryCityData("New York City"); // Do something with the data. }Değişken bildirimi ve atamasını bir yapısızlaştırmada birlikte kullanabilirsiniz.
public static void Main() { string city = "Raleigh"; int population = 458880; (city, population, double area) = QueryCityData("New York City"); // Do something with the data. }
Tuple içindeki tüm alanlar aynı türe sahip olsa bile parantez dışına belirli bir tür belirtemezsiniz. Bunu yaptığınızda CS8136, "'var (...)' yapısızlaştırma formu 'var' için belirli bir türe izin vermemektedir" derleyici hatası oluşturur.
Tuple'un her öğesini bir değişkene atamanız gerekir. Herhangi bir öğeyi atlarsanız, derleyici CS8132 "'x' öğelerinin bir demetini 'y' değişkenlerine dönüştüremez" hatasını oluşturur.
Atılan öğelerle tanımlama grubu
Genellikle bir demeti parçalayarak yalnızca bazı öğelerin değerleriyle ilgilenirsiniz. C#'nin atmadesteğinden yararlanabilirsiniz. Bunlar, değerlerini yoksaymayı seçtiğiniz salt yazma değişkenleridir. Bir atamada alt çizgi karakteri ("_") ile bir atılma bildirirsiniz. İstediğiniz kadar değer iptal edebilirsiniz; yalnızca _, iptal edilen tüm değerleri temsil eder.
Aşağıdaki örnek, tuple'ların atmaları kullanma şeklini göstermektedir.
QueryCityDataForYears yöntemi, bir şehrin adı, alanı, bir yıl, o yılın şehir nüfusu, ikinci bir yıl ve o ikinci yılın şehir nüfusu ile altılı bir dizi döndürür. Örnekte, bu iki yıl arasındaki nüfus değişikliği gösterilmektedir. Tuple'daki mevcut verilerden, şehir alanıyla ilgilenmiyoruz ve tasarım zamanında şehir adını ve iki tarihi biliyoruz. Sonuç olarak, yalnızca demette depolanan iki popülasyon değeriyle ilgileniyoruz ve kalan değerlerini göz ardı edebiliriz.
using System;
public class ExampleDiscard
{
public static void Main()
{
var (_, _, _, pop1, _, pop2) = QueryCityDataForYears("New York City", 1960, 2010);
Console.WriteLine($"Population change, 1960 to 2010: {pop2 - pop1:N0}");
}
private static (string, double, int, int, int, int) QueryCityDataForYears(string name, int year1, int year2)
{
int population1 = 0, population2 = 0;
double area = 0;
if (name == "New York City")
{
area = 468.48;
if (year1 == 1960)
{
population1 = 7781984;
}
if (year2 == 2010)
{
population2 = 8175133;
}
return (name, area, year1, population1, year2, population2);
}
return ("", 0, 0, 0, 0, 0);
}
}
// The example displays the following output:
// Population change, 1960 to 2010: 393,149
Kullanıcı tanımlı türler
C# tanımlama grubu türlerini decompose etmek, recordve DictionaryEntry türleri için yerleşik destek sunar. Ancak, bir sınıfın, yapının veya arayüzün yazarı olarak, bir veya daha fazla Deconstruct yöntem uygulayarak tür örneklerinin ayrıştırılmasına izin verebilirsiniz. Yöntem void döndürür. Yöntem imzasında parametresi, yapısı kaldırılacak her değeri temsil eder. Örneğin, bir Deconstruct sınıfının aşağıdaki Person yöntemi ilk, orta ve aile adını döndürür:
public void Deconstruct(out string fname, out string mname, out string lname)
Daha sonra, aşağıdaki kod gibi bir atamayla, p adlı Person sınıf örneğini parçalayabilirsiniz.
var (fName, mName, lName) = p;
Aşağıdaki örnek, bir Deconstruct nesnenin Person çeşitli özellik bileşimlerini döndürmek için yöntemini aşırı yükler. Bireysel aşırı yüklenimler döner.
- Bir ad ve soyadı.
- İlk isim, orta isim ve soyadı.
- Ad, aile adı, şehir adı ve eyalet adı.
using System;
public class Person
{
public string FirstName { get; set; }
public string MiddleName { get; set; }
public string LastName { get; set; }
public string City { get; set; }
public string State { get; set; }
public Person(string fname, string mname, string lname,
string cityName, string stateName)
{
FirstName = fname;
MiddleName = mname;
LastName = lname;
City = cityName;
State = stateName;
}
// Return the first and last name.
public void Deconstruct(out string fname, out string lname)
{
fname = FirstName;
lname = LastName;
}
public void Deconstruct(out string fname, out string mname, out string lname)
{
fname = FirstName;
mname = MiddleName;
lname = LastName;
}
public void Deconstruct(out string fname, out string lname,
out string city, out string state)
{
fname = FirstName;
lname = LastName;
city = City;
state = State;
}
}
public class ExampleClassDeconstruction
{
public static void Main()
{
var p = new Person("John", "Quincy", "Adams", "Boston", "MA");
// Deconstruct the person object.
var (fName, lName, city, state) = p;
Console.WriteLine($"Hello {fName} {lName} of {city}, {state}!");
}
}
// The example displays the following output:
// Hello John Adams of Boston, MA!
Aynı sayıda parametreye sahip birden çok Deconstruct yöntem belirsizdir. Farklı sayıda parametreye veya "arity"ye sahip Deconstruct yöntemleri tanımlarken dikkatli olmanız gerekir. Aynı sayıda parametreye sahip Deconstruct yöntemleri aşırı yükleme çözümlemesi sırasında ayırt edilemez.
Atmalarla kullanıcı tanımlı tür
Tanımlama listelerinde olduğu gibi, bir Deconstruct yöntem tarafından döndürülen seçili öğeleri yoksaymak için atmaları kullanabilirsiniz. "_" adlı değişken bir atma temsil eder. Tek bir yapısızlaştırma işlemi birden çok ihmal veya iptal içerebilir.
Aşağıdaki örnek, bir Person nesnesini dört dizeye (ad ve aile adları, şehir ve eyalet) ayırır, ancak aile adını ve durumu atar.
// Deconstruct the person object.
var (fName, _, city, _) = p;
Console.WriteLine($"Hello {fName} of {city}!");
// The example displays the following output:
// Hello John of Boston!
Yapısızlaştırma uzantısı yöntemleri
Bir sınıf, yapı veya arabirim yazmadıysanız, ilgilendiğiniz değerleri döndürmek için bir veya daha fazla Deconstructuzantı yöntemi uygulayarak bu türdeki nesnelerin yapısını yine de kaldırabilirsiniz.
Aşağıdaki örnek, System.Reflection.PropertyInfo sınıfı için iki Deconstruct uzantı yöntemini tanımlar. birincisi, özelliğin özelliklerini gösteren bir değer kümesi döndürür. İkincisi özelliğin erişilebilirliğine işaret eder. Boole değerleri özelliğin ayrı alma ve ayarlama erişimcilerine veya farklı erişilebilirlik özelliklerine sahip olup olmadığını gösterir. Yalnızca bir erişimci varsa veya hem get hem de küme erişimcisi aynı erişilebilirliği varsa, access değişken özelliğin erişilebilirliğini bir bütün olarak gösterir. Aksi takdirde, get ve set erişimcilerinin erişilebilirliği getAccess ve setAccess değişkenleri ile belirtilir.
using System;
using System.Collections.Generic;
using System.Reflection;
public static class ReflectionExtensions
{
extension(PropertyInfo propertyInfo)
{
public void Deconstruct(out bool isStatic,
out bool isReadOnly, out bool isIndexed,
out Type propertyType)
{
var getter = propertyInfo.GetMethod;
// Is the property read-only?
isReadOnly = ! propertyInfo.CanWrite;
// Is the property instance or static?
isStatic = getter.IsStatic;
// Is the property indexed?
isIndexed = propertyInfo.GetIndexParameters().Length > 0;
// Get the property type.
propertyType = propertyInfo.PropertyType;
}
public void Deconstruct(out bool hasGetAndSet,
out bool sameAccess, out string access,
out string getAccess, out string setAccess)
{
hasGetAndSet = sameAccess = false;
string getAccessTemp = null;
string setAccessTemp = null;
MethodInfo getter = null;
if (propertyInfo.CanRead)
getter = propertyInfo.GetMethod;
MethodInfo setter = null;
if (propertyInfo.CanWrite)
setter = propertyInfo.SetMethod;
if (setter != null && getter != null)
hasGetAndSet = true;
if (getter != null)
{
if (getter.IsPublic)
getAccessTemp = "public";
else if (getter.IsPrivate)
getAccessTemp = "private";
else if (getter.IsAssembly)
getAccessTemp = "internal";
else if (getter.IsFamily)
getAccessTemp = "protected";
else if (getter.IsFamilyOrAssembly)
getAccessTemp = "protected internal";
}
if (setter != null)
{
if (setter.IsPublic)
setAccessTemp = "public";
else if (setter.IsPrivate)
setAccessTemp = "private";
else if (setter.IsAssembly)
setAccessTemp = "internal";
else if (setter.IsFamily)
setAccessTemp = "protected";
else if (setter.IsFamilyOrAssembly)
setAccessTemp = "protected internal";
}
// Are the accessibility of the getter and setter the same?
if (setAccessTemp == getAccessTemp)
{
sameAccess = true;
access = getAccessTemp;
getAccess = setAccess = String.Empty;
}
else
{
access = null;
getAccess = getAccessTemp;
setAccess = setAccessTemp;
}
}
}
}
public class ExampleExtension
{
public static void Main()
{
Type dateType = typeof(DateTime);
PropertyInfo prop = dateType.GetProperty("Now");
var (isStatic, isRO, isIndexed, propType) = prop;
Console.WriteLine($"\nThe {dateType.FullName}.{prop.Name} property:");
Console.WriteLine($" PropertyType: {propType.Name}");
Console.WriteLine($" Static: {isStatic}");
Console.WriteLine($" Read-only: {isRO}");
Console.WriteLine($" Indexed: {isIndexed}");
Type listType = typeof(List<>);
prop = listType.GetProperty("Item",
BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Static);
var (hasGetAndSet, sameAccess, accessibility, getAccessibility, setAccessibility) = prop;
Console.Write($"\nAccessibility of the {listType.FullName}.{prop.Name} property: ");
if (!hasGetAndSet | sameAccess)
{
Console.WriteLine(accessibility);
}
else
{
Console.WriteLine($"\n The get accessor: {getAccessibility}");
Console.WriteLine($" The set accessor: {setAccessibility}");
}
}
}
// The example displays the following output:
// The System.DateTime.Now property:
// PropertyType: DateTime
// Static: True
// Read-only: True
// Indexed: False
//
// Accessibility of the System.Collections.Generic.List`1.Item property: public
Sistem türleri için uzantı yöntemi
Bazı sistem türleri kolaylık sağlamak için Deconstruct yöntemini sağlar. Örneğin, System.Collections.Generic.KeyValuePair<TKey,TValue> türü bu işlevi sağlar. bir System.Collections.Generic.Dictionary<TKey,TValue>üzerinde yineleme yaparken, her öğe bir KeyValuePair<TKey, TValue> ve yapısı kaldırılabilir. Aşağıdaki örneği inceleyin:
Dictionary<string, int> snapshotCommitMap = new(StringComparer.OrdinalIgnoreCase)
{
["https://github.com/dotnet/docs"] = 16_465,
["https://github.com/dotnet/runtime"] = 114_223,
["https://github.com/dotnet/installer"] = 22_436,
["https://github.com/dotnet/roslyn"] = 79_484,
["https://github.com/dotnet/aspnetcore"] = 48_386
};
foreach (var (repo, commitCount) in snapshotCommitMap)
{
Console.WriteLine(
$"The {repo} repository had {commitCount:N0} commits as of November 10th, 2021.");
}
record Tür
İki veya daha fazla konumsal parametre kullanarak bir kayıt türü bildirdiğinizde, derleyici bildirimdeki Deconstruct her konum parametresi için bir parametre içeren bir outrecord yöntem oluşturur. Daha fazla bilgi için bkz Özellik tanımı için konumsal söz dizimi ve Türetilmiş kayıtlarda yıkıcı davranışı.