C# Anonymous Type Kullanımı
Bir sınıf tanımladığımızda bu sınıfı programımızın bir çok yerinden çağırılmasını bekleriz. Peki sadece belli bir scope içerisinde sadece 1 kere kullanacağımız bir model gerekiyorsa ne yaparız? Sadece 1 kere kullanacak olmamıza rağmen yeni sınıf oluşturmak ne kadar mantıklı? Tabi ki mantıklı değil bu tip durumlarda Anonymous Type kullanabiliriz.
Anonymous Type tanımı yapılırken var keyword'ü kullanılır. Çünkü bildiğiniz gibi var ile bir değişken tanımlandığında tipi runtime'da compiler tarafından belirlenir. Anonymous Type olarak tanıladığımız tiplerin belirli bir tipi olmadığı için var ile kullanılır.
Yukarıda gördüğünüz gibi Person sınıfı oluşturmak yerine Anonymous Type ile person nesnesi yarattık, ardından yarattığımız Anonymous Type nesnesinin property'lerine metod içerisinde ulaşabildik.
Çıktı:
Anonymous Type tanımlanırken dikkat edilmesi gereken bir konu, Anonymous Type propertyleri default construtor ile tanımlanır ve readonly'dirler sonradan değiştirilemezler.
Yarattığımız person nesnesinin Name alanını sonradan yukarıdaki gibi Ahmet'e çevirmek istersek readonly olduğu için aşağıdaki hatayı verecektir.
Çıktı:
Gördüğünüz gibi compiler arka tarafta System.Object sınıfından türeyen <>f__AnonymousType0 isminde bir sınıf yaratmış. Programımızı ildasm ile açarsanız bu sınıfın sealed bir sınıf olduğunu görürsünüz. Ayrıca belirttiğimiz tüm Property'lerin bu sınıf içerisinde readonly olarak yaratılmış olduğunu göreceksiniz. Bu yüzden construtor dışında bu property'leri değiştiremiyoruz.
<>f__AnonymousType0 siz kendi programınızda baktığınızda farklı olabilir. Çünkü compiler çalışma zamanında oluşturduğu bu sınıfa unique bir isim vermektedir.
Son olarak aşağıdaki gibi 2 Anonymous Type tanımladığımızı düşünelim:
Compiler bu iki nesne için oluşturduğu tek <>f__AnonymousType0 sınıfını kullanacaktır. Her nesne için ayrı sınıf oluşturmayacaktır. Property'leri aynı olan Anonymous Type nesneleri için tek bir sealed sınıf oluşturulup kullanılmaktadır.
Örnek Proje:
AnonymousTypeExample.rar
Anonymous Type tanımı yapılırken var keyword'ü kullanılır. Çünkü bildiğiniz gibi var ile bir değişken tanımlandığında tipi runtime'da compiler tarafından belirlenir. Anonymous Type olarak tanıladığımız tiplerin belirli bir tipi olmadığı için var ile kullanılır.
class Program { static void Main(string[] args) { BuildAnonymousType("Safak", "Unel", 26); Console.ReadLine(); } static void BuildAnonymousType(string name, string surname, int age) { // Build anon type using incoming args. // Anonymous Type tanimi yapiliyor // new'den sonra isim verilmeden property'ler tanimlaniyor var person = new { Name = name, Surname = surname, Age = age }; // Note you can now use this type to get the property data! Console.WriteLine("Fullname: {0} Age: {1}\n", person.Name + " " + person.Surname, person.Age); // Anon types have custom implementations of each virtual // method of System.Object. For example: Console.WriteLine("ToString() == {0}", person.ToString()); } }
Yukarıda gördüğünüz gibi Person sınıfı oluşturmak yerine Anonymous Type ile person nesnesi yarattık, ardından yarattığımız Anonymous Type nesnesinin property'lerine metod içerisinde ulaşabildik.
Çıktı:
Anonymous Type tanımlanırken dikkat edilmesi gereken bir konu, Anonymous Type propertyleri default construtor ile tanımlanır ve readonly'dirler sonradan değiştirilemezler.
person.Name = "Ahmet";
Yarattığımız person nesnesinin Name alanını sonradan yukarıdaki gibi Ahmet'e çevirmek istersek readonly olduğu için aşağıdaki hatayı verecektir.
Property or indexer 'AnonymousType#1.Name' cannot be assigned to -- it is read onlyPeki bu yarattığımız Anonymous Type nesnesini compiler nası yoruluyor hangi tipe çeviriyor? Bunu görmek için şu kod parçasını yazıp çalıştıralım:
static void ReflectOverAnonymousType(object obj) { Console.WriteLine("obj is an instance of: {0}", obj.GetType().Name); Console.WriteLine("Base class of {0} is {1}", obj.GetType().Name, obj.GetType().BaseType); Console.WriteLine("obj.ToString() == {0}", obj.ToString()); Console.WriteLine("obj.GetHashCode() == {0}", obj.GetHashCode()); Console.WriteLine(); }
Çıktı:
Gördüğünüz gibi compiler arka tarafta System.Object sınıfından türeyen <>f__AnonymousType0 isminde bir sınıf yaratmış. Programımızı ildasm ile açarsanız bu sınıfın sealed bir sınıf olduğunu görürsünüz. Ayrıca belirttiğimiz tüm Property'lerin bu sınıf içerisinde readonly olarak yaratılmış olduğunu göreceksiniz. Bu yüzden construtor dışında bu property'leri değiştiremiyoruz.
<>f__AnonymousType0 siz kendi programınızda baktığınızda farklı olabilir. Çünkü compiler çalışma zamanında oluşturduğu bu sınıfa unique bir isim vermektedir.
Son olarak aşağıdaki gibi 2 Anonymous Type tanımladığımızı düşünelim:
var p1 = new { Name = "Safak", Surname = "Unel", Age = 26 }; var p2 = new { Name = "Ahmet", Surname = "Mehmet", Age = 22 };
Compiler bu iki nesne için oluşturduğu tek <>f__AnonymousType0 sınıfını kullanacaktır. Her nesne için ayrı sınıf oluşturmayacaktır. Property'leri aynı olan Anonymous Type nesneleri için tek bir sealed sınıf oluşturulup kullanılmaktadır.
Örnek Proje:
AnonymousTypeExample.rar