Tuple'ın .Net 4.0'da kullanılabileceği pratik bir örnek?


97

Net 4'te tanıtılan Tuple'ı gördüm, ancak nerede kullanılabileceğini hayal edemiyorum. Her zaman bir Özel sınıf veya Struct yapabiliriz.


13
Belki burası bu konunun çok eski olduğunu belirtmek için iyi bir yerdir. C # 7'de ne olduğuna bakın !
maf-soft

Yanıtlar:


83

Daha uygundur - Bu mesele değil özel bir sınıf yapmak veya her zaman yapısına bir. Bu, Actionya da Func... gibi bir gelişmedir , bu türleri kendiniz yapabilirsiniz, ancak çerçevede var olmaları uygundur.


5
Muhtemelen MSDN'den işaret etmeye değer : "Bu türdeki herhangi bir genel statik üye iş parçacığı güvenlidir. Herhangi bir örnek üyesinin iş parçacığı güvenli olduğu garanti edilmez. "
Matt Borja

Peki, belki de dil tasarımcıları anında özel türler oluşturmayı kolaylaştırmalıydı, o zaman? Yani, başka bir sözdizimi eklemek yerine aynı sözdizimini koruyabilir miyiz?
Thomas Eyde

@ThomasEyde tam da son 15 yıldır yaptıkları şey. İfade gövdeli üyeler bu şekilde eklendi ve şimdi demetlere değer. Kayıt tarzı sınıflar, C # 7'nin bu sürümü için Ağustos'ta (bu yorumdan 9 ay önce) kesintiyi çok az ıskaladı ve muhtemelen C # 8'de çıkacak. Ayrıca, eski sınıfların yapmadığı yerlerde değer demetlerinin değer eşitliği sunduğunu unutmayın . Tüm bunları 2002'de tekrar tanıtmak için önsezi gerekir
Panagiotis Kanavos

Ne demek istiyorsunuz convenient not to make a custom class. Kullanarak özel sınıf örneği oluşturmayı mı kastediyorsunuz =new..()?
Alex

75

Tuple'lar ile iki boyutlu bir sözlüğü (veya bu konuda n-boyutlu) kolayca uygulayabilirsiniz. Örneğin, bir döviz kuru eşlemesi uygulamak için böyle bir sözlüğü kullanabilirsiniz:

var forex = new Dictionary<Tuple<string, string>, decimal>();
forex.Add(Tuple.Create("USD", "EUR"), 0.74850m); // 1 USD = 0.74850 EUR
forex.Add(Tuple.Create("USD", "GBP"), 0.64128m);
forex.Add(Tuple.Create("EUR", "USD"), 1.33635m);
forex.Add(Tuple.Create("EUR", "GBP"), 0.85677m);
forex.Add(Tuple.Create("GBP", "USD"), 1.55938m);
forex.Add(Tuple.Create("GBP", "EUR"), 1.16717m);
forex.Add(Tuple.Create("USD", "USD"), 1.00000m);
forex.Add(Tuple.Create("EUR", "EUR"), 1.00000m);
forex.Add(Tuple.Create("GBP", "GBP"), 1.00000m);

decimal result;
result = 35.0m * forex[Tuple.Create("USD", "EUR")]; // USD 35.00 = EUR 26.20
result = 35.0m * forex[Tuple.Create("EUR", "GBP")]; // EUR 35.00 = GBP 29.99
result = 35.0m * forex[Tuple.Create("GBP", "USD")]; // GBP 35.00 = USD 54.58

Ülke kısaltmaları için bir Enum kullanmayı tercih ederim. Mümkün mü?
Zack,

1
Elbette, numaralandırmalar değer türü olduğundan sorunsuz çalışması gerekir.
MarioVW

@MarioVW Çok boyutlu dizi kullanılarak da gerçekleştirilebilir. Tuple nasıl bir fark yaratır?
Alex

26

Harika bir makale varMSDN dergisinde, BCL'ye Tuple eklemeye giden karın ağrısı ve tasarım hususlarından bahseden . Bir değer türü ile bir referans türü arasında seçim yapmak özellikle ilginçtir.

Makalede açıkça görüldüğü gibi, Tuple'ın arkasındaki itici güç, Microsoft'un içindeki birçok grubun bunu kullanmasıydı, F # ekibi önde. Bahsedilmemesine rağmen, C # (ve VB.NET) 'deki yeni "dinamik" anahtar kelimenin de bununla bir ilgisi olduğunu düşünüyorum, tuplelar dinamik dillerde çok yaygındır.

Aksi takdirde, kendi poco'nuzu yaratmaktan özellikle üstün değildir, en azından üyelere daha iyi bir isim verebilirsiniz.


GÜNCELLEME: C # sürüm 7'deki büyük bir revizyon nedeniyle, şimdi çok daha fazla sözdizimi sevgisi alıyoruz. Bu blog gönderisinde ön duyuru .


23

İşte küçük bir örnek - bir kullanıcı kimliği verildiğinde, bir kullanıcının tutamaçını ve e-posta adresini aramaya ihtiyaç duyan bir yönteminiz olduğunu varsayalım. Her zaman bu verileri içeren özel bir sınıf oluşturabilir veya bu veriler için bir ref / out parametresi kullanabilirsiniz veya yeni bir POCO oluşturmak zorunda kalmadan sadece bir Tuple döndürebilir ve güzel bir yöntem imzasına sahip olabilirsiniz.

public static void Main(string[] args)
{
    int userId = 0;
    Tuple<string, string> userData = GetUserData(userId);
}

public static Tuple<string, string> GetUserData(int userId)
{
    return new Tuple<string, string>("Hello", "World");
}

10
Ancak bu iyi bir örnek, Tuple kullanımını haklı çıkarmaz.
Amitabh

7
Bir demet, farklı değerler döndürdüğünüz için burada uygun bir uyumdur; ancak bir demet, farklı türlerde birden çok değer döndürdüğünüzde daha fazla parlar .
Mark Rushakoff

21
Çıktı parametresini ortadan kaldırıp bunun yerine bir Tuple kullanabileceğiniz için başka bir iyi örnek int. TryParse olacaktır. Böylece Tuple<bool, T> TryParse<T>(string input)bir çıktı parametresine sahip olabilirsiniz ve bunun yerine, her iki değeri de bir demet içinde geri alırsınız.
Tejs

3
aslında, F # 'dan herhangi bir TryParse yöntemini çağırdığınızda olan tam olarak budur.
Joel Mueller

23

Project Euler'in 11. Problemini çözmek için bir demet kullandım :

class Grid
{
    public static int[,] Cells = { { 08, 02, 22, // whole grid omitted

    public static IEnumerable<Tuple<int, int, int, int>> ToList()
    {
        // code converts grid to enumeration every possible set of 4 per rules
        // code omitted
    }
}

Şimdi tüm sorunu şu şekilde çözebilirim:

class Program
{
    static void Main(string[] args)
    {
        int product = Grid.ToList().Max(t => t.Item1 * t.Item2 * t.Item3 * t.Item4);
        Console.WriteLine("Maximum product is {0}", product);
    }
}

Ben olabilir bunun için özel bir türü kullanmış, ancak baktım olurdu aynen kayıt düzeni gibi .


16

C # 'ın tuple sözdizimi gülünç derecede hantaldır, bu yüzden tupleları bildirmek zahmetlidir. Ve desen eşleştirmesi olmadığı için kullanımı da zahmetlidir.

Ancak bazen, bunun için bir sınıf oluşturmadan nesnelerin anlık olarak gruplandırılmasını istersiniz. Örneğin, bir listeyi toplamak istediğimi, ancak bir yerine iki değer istediğimi varsayalım:

// sum and sum of squares at the same time
var x =
    Enumerable.Range(1, 100)
    .Aggregate((acc, x) => Tuple.Create(acc.Item1 + x, acc.Item2 + x * x));

Bir değerler koleksiyonunu tek bir sonuçta birleştirmek yerine, tek bir sonucu bir değerler koleksiyonuna genişletelim. Bu işlevi yazmanın en kolay yolu şudur:

static IEnumerable<T> Unfold<T, State>(State seed, Func<State, Tuple<T, State>> f)
{
    Tuple<T, State> res;
    while ((res = f(seed)) != null)
    {
        yield return res.Item1;
        seed = res.Item2;
    }
}

fbazı durumu bir demete dönüştürür. İlk değeri tuple'dan döndürüyoruz ve yeni durumumuzu ikinci değere ayarlıyoruz. Bu, hesaplama boyunca durumu korumamıza izin verir.

Bunu şu şekilde kullanırsınız:

// return 0, 2, 3, 6, 8
var evens =
    Unfold(0, state => state < 10 ? Tuple.Create(state, state + 2) : null)
    .ToList();

// returns 0, 1, 1, 2, 3, 5, 8, 13, 21, 34
var fibs =
    Unfold(Tuple.Create(0, 1), state => Tuple.Create(state.Item1, Tuple.Create(state.Item2, state.Item1 + state.Item2)))
    .Take(10).ToList();

evensoldukça basit, ancak fibsbiraz daha akıllı. Onun stateaslında (n-1), sırasıyla fib (n-2) ve fib tutan bir demet olup.


4
+1 Tuple.Create için kullanışlı bir kısaltmanew Tuple<Guid,string,...>
AaronLS

@Juliet State anahtar kelimesinin kullanımı nedir
irfandar

7

Kendini açıklamayan kod ürettikleri için kötüye kullanılmalarını sevmiyorum, ancak IStructuralEquatable ve IStructuralComparable'ı uyguladıkları için anında bileşik anahtarları uygulamak harikadır (hem arama hem de sipariş için kullanmak için amaçlar).

Ve tüm öğelerinin hashcode'larını dahili olarak birleştirirler; örneğin, işte Tuple'ın GetHashCode'u (ILSpy'dan alınmıştır):

    int IStructuralEquatable.GetHashCode(IEqualityComparer comparer)
    {
        return Tuple.CombineHashCodes(comparer.GetHashCode(this.m_Item1), comparer.GetHashCode(this.m_Item2), comparer.GetHashCode(this.m_Item3));
    }

7

Tuple'lar, bir seferde birden çok eşzamansız GÇ işlemi yapmak ve tüm değerleri bir araya getirmek için harikadır. İşte bunu Tuple ile ve Tuple olmadan yapmanın örnekleri. Tuples aslında kodunuzu daha net hale getirebilir!

Olmadan (kötü iç içe geçme!):

Task.Factory.StartNew(() => data.RetrieveServerNames())
    .ContinueWith(antecedent1 =>
        {
            if (!antecedent1.IsFaulted)
            {
                ServerNames = KeepExistingFilter(ServerNames, antecedent1.Result);
                Task.Factory.StartNew(() => data.RetrieveLogNames())
                    .ContinueWith(antecedent2 =>
                        {
                            if (antecedent2.IsFaulted)
                            {
                                LogNames = KeepExistingFilter(LogNames, antecedent2.Result);
                                Task.Factory.StartNew(() => data.RetrieveEntryTypes())
                                    .ContinueWith(antecedent3 =>
                                        {
                                            if (!antecedent3.IsFaulted)
                                            {
                                                EntryTypes = KeepExistingFilter(EntryTypes, antecedent3.Result);
                                            }
                                        });
                            }
                        });
            }
        });

Tuple ile

Task.Factory.StartNew(() =>
    {
        List<string> serverNames = data.RetrieveServerNames();
        List<string> logNames = data.RetrieveLogNames();
        List<string> entryTypes = data.RetrieveEntryTypes();
        return Tuple.Create(serverNames, logNames, entryTypes);
    }).ContinueWith(antecedent =>
        {
            if (!antecedent.IsFaulted)
            {
                ServerNames = KeepExistingFilter(ServerNames, antecedent.Result.Item1);
                LogNames = KeepExistingFilter(LogNames, antecedent.Result.Item2);
                EntryTypes = KeepExistingFilter(EntryTypes, antecedent.Result.Item3);
            }
        });

Zaten örtülü bir türle anonim bir işlev kullanıyorsanız, Tuple'ı kullanarak kodu daha az net hale getirmiyorsunuz. Bir Tuple'ı bir yöntemden yeniden mi ayarlıyorsunuz? Benim düşünceme göre, kod netliği anahtar olduğunda idareli kullanın. C # 'da işlevsel programlamaya direnmenin zor olduğunu biliyorum, ancak tüm o eski hantal "nesne yönelimli" C # programcılarını da dikkate almalıyız.


5

Tuple'lar, onlarla daha fazla şey yapabilen işlevsel dillerde yoğun bir şekilde kullanılmaktadır, şimdi F #, C # ile birlikte çalışmak ve bunları iki dilde yazılmış kodlar arasında geçirmek isteyebileceğiniz bir 'resmi' .net dilidir.


Tuple'lar ayrıca Python ve Ruby gibi bazı popüler komut dosyası dilleri için türler halinde oluşturulmuştur (bunlar ayrıca birlikte çalışma için .Net uygulamalarına sahiptir ... IronPython / Ruby).
MutantNinjaCodeMonkey

5

TupleOkunabilirliği bozduğu için çoğu senaryodan kaçınma eğilimindeyim . Ancak, Tupleilgisiz verileri gruplamanız gerektiğinde kullanışlıdır.

Örneğin, arabaların ve bunların satın alındığı şehirlerin bir listesinin olduğunu varsayalım:

Mercedes, Seattle
Mustang, Denver
Mercedes, Seattle
Porsche, Seattle
Tesla, Seattle
Mercedes, Seattle

Şehir başına her arabanın sayılarını toplamak istiyorsunuz:

Mercedes, Seattle [3]
Mustang, Denver [1]
Porsche, Seattle [1]
Tesla, Seattle [1]

Bunu yapmak için bir Dictionary. Birkaç seçeneğiniz var:

  1. Bir Dictionary<string, Dictionary<string, int>>.
  2. Bir Dictionary<CarAndCity, int>.
  3. Bir Dictionary<Tuple<string, string>, int>.

İlk seçenekle okunabilirlik kaybolur. Çok daha fazla kod yazmanızı gerektirecek.

İkinci seçenek işe yarıyor ve özlü, ancak araba ve şehir gerçekten birbiriyle ilişkili değil ve muhtemelen bir sınıfa ait değil.

Üçüncü seçenek, özlü ve temizdir. İyi bir kullanım Tuple.


4

Aklıma gelen birkaç örnek:

  • Bir X ve Y konumu (ve isterseniz Z)
  • a Genişlik ve Yükseklik
  • Zamanla ölçülen her şey

Örneğin, bir web uygulamasına yalnızca Point / PointF ve Size / SizeF kullanmak için System.Drawing'i dahil etmek istemezsiniz.


2
Tuplekritik durumlarda, grafik işlemleri yaparken olduğu kadar kullanışlıdır Pointveya SomeVectoryararlı olabilir. Birbirine çok bağlı iki değeri vurgular. Kodu okurken genellikle StartTime ve EndTime adlı özellikler görüyorum, ancak bir tarih saatinden ve süreden daha iyi olan bir Tuple, iş mantığınızın bu alanında her çalıştığınızda sizi her iki değeri de dikkate almaya zorluyor. Ya da "hey, veriler değişti (bool), işte veriler (diğer tür)" şeklinde, yoğun bağlamalardan geçmek yerine yoğun şekilde işlendi.
Léon Pelletier

3

Kullanırken çok dikkatli olmalısın Tupleve muhtemelen bunu yapmadan önce iki kez düşünmelisin. Önceki deneyimlerime dayanarak, kullanmanın Tuplegelecekte kodu okumayı ve desteklemeyi çok zorlaştırdığını öğrendim . Bir süre önce, tuple'ların neredeyse her yerde kullanıldığı bazı kodları düzeltmek zorunda kaldım. Uygun nesne modellerini düşünmek yerine, sadece demetler kullandılar. Bu bir kabustu ... Bazen kodu yazan adamı öldürmek istedim ...

Kullanmaman gerektiğini Tupleve kötü ya da başka bir şey olduğunu söylemek istemiyorum ve Tuplekullanılabilecek en iyi adayın olduğu bazı görevler olduğundan yüzde yüz eminim , ama muhtemelen tekrar düşünmelisin, GERÇEKTEN ihtiyacın var mı ?


1

Bulduğum Tuple'lar için en iyi kullanım, bir yöntemden 1'den fazla nesne türü döndürmeye ihtiyaç duyduğunuzda, hangi nesne türlerinin ve sayılarının olacağını biliyorsunuz ve bu uzun bir liste değil.

Diğer basit alternatifler bir 'çıkış' parametresi kullanmak olabilir

private string MyMethod(out object)

veya bir Sözlük yapmak

Dictionary<objectType1, objectType2>

Ancak bir Tuple kullanmak, ya 'dışarı' nesnesini oluşturmaktan ya da sözlükteki girişi esasen aramak zorunda kalmaktan kurtarır;


1

Sorunlarımdan birinin çözümünü Tuple'da buldum. Bu, bir yöntem kapsamında bir sınıfı bildirmek gibidir, ancak alan adlarının tembel olarak bildirilmesiyle. Tuple koleksiyonları, tek örnekleriyle çalışırsınız ve ardından demetinize dayanarak gerekli alan adlarıyla anonim bir tür koleksiyonu oluşturursunuz. Bu, bu amaçla yeni sınıfı oluşturmanızı engeller.

Görev, herhangi bir ek sınıf olmadan LINQ'dan bir JSON yanıtı yazmaktır:

 //I select some roles from my ORM my with subrequest and save results to Tuple list
 var rolesWithUsers = (from role in roles
                       select new Tuple<string, int, int>(
                         role.RoleName, 
                         role.RoleId, 
                         usersInRoles.Where(ur => ur.RoleId == role.RoleId).Count()
                      ));

 //Then I add some new element required element to this collection
 var tempResult = rolesWithUsers.ToList();
 tempResult.Add(new Tuple<string, int, int>(
                        "Empty", 
                         -1,
                         emptyRoleUsers.Count()
                      ));

 //And create a new anonimous class collection, based on my Tuple list
 tempResult.Select(item => new
            {
                GroupName = item.Item1,
                GroupId = item.Item2,
                Count = item.Item3
            });


 //And return it in JSON
 return new JavaScriptSerializer().Serialize(rolesWithUsers);

Çünkü bunu gruplarım için yeni bir Sınıf ilan ederek yapabilirdik, ancak yeni sınıflar bildirmeden böyle anonim koleksiyonlar oluşturma fikri.


1

Benim durumumda, asenkron bir yöntemde parametre kullanamayacağımızı öğrendiğimde bir Tuple kullanmak zorunda kaldım. Buradan okuyun . Ayrıca farklı bir iade türüne ihtiyacım vardı. Bu yüzden dönüş türüm olarak bir Tuple kullandım ve yöntemi zaman uyumsuz olarak işaretledim.

Aşağıdaki örnek kod.

...
...
// calling code.
var userDetails = await GetUserDetails(userId);
Console.WriteLine("Username : {0}", userDetails.Item1);
Console.WriteLine("User Region Id : {0}", userDetails.Item2);
...
...

private async Tuple<string,int> GetUserDetails(int userId)
{
    return new Tuple<string,int>("Amogh",105);
    // Note that I can also use the existing helper method (Tuple.Create).
}

Tuple hakkında daha fazlasını buradan okuyun . Bu yardımcı olur umarım.


Anonim bir tür veya Dizi (veya dinamik içerik) döndürmek istemediğinizi varsayıyorum
ozzy432836

0

Nesnelerin şekillerini kablo üzerinden göndermeniz veya farklı uygulama katmanına geçmeniz gerektiğinde değiştirmek ve birden çok nesne tek bir nesnede birleştirilir:

Misal:

var customerDetails = new Tuple<Customer, List<Address>>(mainCustomer, new List<Address> {mainCustomerAddress}).ToCustomerDetails();

ExtensionMethod:

public static CustomerDetails ToCustomerDetails(this Tuple<Website.Customer, List<Website.Address>> customerAndAddress)
    {
        var mainAddress = customerAndAddress.Item2 != null ? customerAndAddress.Item2.SingleOrDefault(o => o.Type == "Main") : null;
        var customerDetails = new CustomerDetails
        {
            FirstName = customerAndAddress.Item1.Name,
            LastName = customerAndAddress.Item1.Surname,
            Title = customerAndAddress.Item1.Title,
            Dob = customerAndAddress.Item1.Dob,
            EmailAddress = customerAndAddress.Item1.Email,
            Gender = customerAndAddress.Item1.Gender,
            PrimaryPhoneNo = string.Format("{0}", customerAndAddress.Item1.Phone)
        };

        if (mainAddress != null)
        {
            customerDetails.AddressLine1 =
                !string.IsNullOrWhiteSpace(mainAddress.HouseName)
                    ? mainAddress.HouseName
                    : mainAddress.HouseNumber;
            customerDetails.AddressLine2 =
                !string.IsNullOrWhiteSpace(mainAddress.Street)
                    ? mainAddress.Street
                    : null;
            customerDetails.AddressLine3 =
                !string.IsNullOrWhiteSpace(mainAddress.Town) ? mainAddress.Town : null;
            customerDetails.AddressLine4 =
                !string.IsNullOrWhiteSpace(mainAddress.County)
                    ? mainAddress.County
                    : null;
            customerDetails.PostCode = mainAddress.PostCode;
        }
...
        return customerDetails;
    }

0

Bir çıkış parametresi, döndürülmesi gereken yalnızca birkaç değer olduğunda harikadır, ancak döndürülmesi gereken 4, 5, 6 veya daha fazla değerle karşılaşmaya başladığınızda, işiniz zorlaşabilir. Birden çok değer döndürmek için başka bir seçenek, kullanıcı tanımlı bir sınıf / yapı oluşturmak ve döndürmek veya bir yöntem tarafından döndürülmesi gereken tüm değerleri paketlemek için bir Tuple kullanmaktır.

Değerleri döndürmek için bir sınıf / yapı kullanan ilk seçenek basittir. Sadece türü oluşturun (bu örnekte bu bir yapıdır) aşağıdaki gibi:

public struct Dimensions
{
public int Height;
public int Width;
public int Depth;
}

Bir Tuple kullanan ikinci seçenek, kullanıcı tanımlı bir nesne kullanmaktan çok daha zarif bir çözümdür. Değişken türlerdeki herhangi bir sayıda değeri tutmak için bir Tuple oluşturulabilir. Ek olarak, Tuple'da sakladığınız veriler değişmezdir; Yapıcı veya statik Create yöntemi aracılığıyla verileri Tuple'a ekledikten sonra, bu veriler değiştirilemez. Tuples, sekiz ayrı değer dahil olmak üzere kabul edebilir. Sekizden fazla değer döndürmeniz gerekiyorsa, özel Tuple sınıfını kullanmanız gerekir: Tuple Sınıfı Sekizden fazla değere sahip bir Tuple oluştururken, statik Create yöntemini kullanamazsınız — bunun yerine sınıfın yapıcısını kullanmanız gerekir. Bu, 10 tam sayı değerinden oluşan bir Tuple'ı nasıl oluşturacağınızdır:

var values = new Tuple<int, int, int, int, int, int, int, Tuple<int, int, int>> (
1, 2, 3, 4, 5, 6, 7, new Tuple<int, int, int> (8, 9, 10));

Elbette, her gömülü Tuple'ın sonuna daha fazla Tuple eklemeye devam ederek ihtiyacınız olan herhangi bir boyutta Tuple oluşturabilirsiniz.


0

Sadece prototipleme için - Tuples anlamsızdır. Bunları kullanmak uygun ama bu sadece bir kısayol! Prototipler için - iyi. Bu kodu daha sonra sildiğinizden emin olun.

Yazması kolay, okuması zor. Sınıflara, iç sınıflara, anonim sınıflara vb. Göre görünür bir avantajı yoktur.


0

C # 7'de aynı sorunu çözmek için 3 yol denedim ve Tuples için bir kullanım durumu buldum.

Web projelerinde dinamik verilerle çalışmak, haritalama vb. İşlemler sırasında bazen sancılı olabilir.

Tuple'ın item1, item2, itemN ile otomatik olarak eşleştirilme şeklini seviyorum; bu bana, dizin dışı bir öğeye yakalanabileceğiniz dizi dizinlerini kullanmaktan veya bir özellik adını yanlış yazabileceğiniz anonim türü kullanmaktan daha sağlam görünüyor.

Bir DTO sadece bir Tuple kullanılarak ücretsiz olarak yaratılmış gibi geliyor ve bu amaç için ayrı bir DTO oluşturmak zorunda kalmadan daha çok statik yazım gibi hissettiren itemN kullanarak tüm özelliklere erişebiliyorum.

using System;

namespace Playground
{
    class Program
    {
        static void Main(string[] args)
        {
            var tuple = GetTuple();
            Console.WriteLine(tuple.Item1);
            Console.WriteLine(tuple.Item2);
            Console.WriteLine(tuple.Item3);
            Console.WriteLine(tuple);

            Console.WriteLine("---");

            var dyn = GetDynamic();
            Console.WriteLine(dyn.First);
            Console.WriteLine(dyn.Last);
            Console.WriteLine(dyn.Age);
            Console.WriteLine(dyn);

            Console.WriteLine("---");

            var arr = GetArray();
            Console.WriteLine(arr[0]);
            Console.WriteLine(arr[1]);
            Console.WriteLine(arr[2]);
            Console.WriteLine(arr);

            Console.Read();

            (string, string, int) GetTuple()
            {
                return ("John", "Connor", 1);
            }

            dynamic GetDynamic()
            {
                return new { First = "John", Last = "Connor", Age = 1 };
            }

            dynamic[] GetArray()
            {
                return new dynamic[] { "John", "Connor", 1 };
            }
        }
    }
}
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.