delegate int del(int i); static void Main(string[] args) { del myDelegate = x => x * x; int j = myDelegate(5); //j = 25 }
Bir ifade ağacı türü oluşturmak için:
using System.Linq.Expressions; namespace ConsoleApplication1 { class Program { static void Main(string[] args) { Expression<del> myET = x => x * x; } } }
=> işleci atamayla aynı önceliğe sahiptir (=) ve sağa ilişkilendirilmiştir.
Lambda ifadeleri yöntem tabanlı LINQ sorgularında standart sorgu işleci yöntemlerinin bağımsız değişkenleri olarak kullanılır, örneğin Where.
Where yöntemini Enumerable sınıfının içinde çağırmak için yöntem tabanlı sözdizimi kullandığınızda (Nesneler için LINQ ve LINQ to XML durumlarında olduğu gibi) parametre, temsilci türüdür System.Func<T, TResult>. Lambda ifadesi, bu temsilciyi oluşturmak için en kullanışlı yoldur. Aynı yöntemi örneğin System.Linq.Queryable sınıfında çağırırsanız (LINQ to SQL içinde yaptığınız gibi) parametre türü, en fazla on altı giriş parametresi bildiren bir System.Linq.Expressions.Expression<Func> olur. Yine, Lambda ifadesi bu ifade ağacını oluşturmanın yalnızca çok kısa bir yoludur. Aslında lambdadan oluşturulan nesnenin türü farklı olsa da, lambdalar Where çağrılarının benzer görünmesine izin verir.
Önceki örnekte, temsilci imzasında örtük olarak yazılmış ve int türünde bir giriş parametresi olduğuna ve bir int döndürdüğüne dikkat edin. Lambda ifadesi bu türden bir temsilciye dönüştürülebilir çünkü ayrıca bir giriş parametresi (x) ve derleyicinin dolaylı olarak int türüne çevirebildiği bir dönüş değerine sahiptir. (Tür çıkarımı, ilerleyen bölümlerde daha ayrıntılı bir şekilde tartışılmıştır.) Temsilci, giriş parametresi 5 kullanılarak çağrıldığında 25 sonucunu döndürür.
Anonim yöntemler için uygulanan tüm kısıtlamalar lambda ifadeleri için de geçerlidir. Daha fazla bilgi için bkz. Anonim Yöntemler (C# Programlama Kılavuzu).
Lambda İfadeleri
(input parameters) => expression
Parantezler yalnızca lambdanın bir çıktı parametresi varsa isteğe bağlıdır; aksi takdirde bunlar gereklidir. İki veya daha fazla giriş parametresi, ayraç içinde virgülle ayrılır:
(x, y) => x == y
Bazen derleyicinin giriş türlerini çıkarması zor veya imkansız olabilir. Bu durumda türleri aşağıdaki örnekte olduğu gibi açıkça belirtebilirsiniz:
(int x, string s) => s.Length > x
Boş ayraçlarla sıfır giriş parametrelerini belirtin:
() => SomeMethod()
Önceki örnekte bir lambda ifadesi gövdesinin yöntem çağrısından oluşabileceğini unutmayın. Ancak SQL Server gibi başka bir etki alanında kullanılmak üzere ifade ağaçları oluşturuyorsanız lambda ifadelerinde çağıran yöntemi kullanmanız gerekir. Yöntemler .NET ortak dil çalışma zamanı bağlamının dışında anlamlı olmayacaktır.
Deyim Lambda
Ayraçlar arasındaki deyimler hariç statement lambda, expression lambda'ya benzer:
(input parameters) => {statement;}
Bir lambda deyiminin gövdesi herhangi bir sayıda deyimden oluşabilir; ancak, uygulamada genellikle iki veya üçten fazla değildir.
delegate void TestDelegate(string s); … TestDelegate myDel = n => { string s = n + " " + "World"; Console.WriteLine(s); }; myDel("Hello");
Anonim yöntemler gibi deyim lambdaları da ifade ağacı oluşturmak için kullanılamaz.
Zaman Uyumsuz Lambda
public partial class Form1 : Form { public Form1() { InitializeComponent(); } private async void button1_Click(object sender, EventArgs e) { // ExampleMethodAsync returns a Task. await ExampleMethodAsync(); textBox1.Text += "\r\nControl returned to Click event handler.\r\n"; } async Task ExampleMethodAsync() { // The following line simulates a task-returning asynchronous process. await Task.Delay(1000); } }
Zaman uyumsuz lambda kullanarak aynı olay işleyicisini ekleyebilirsiniz. Bu işleyiciyi eklemek için aşağıdaki örnekte göründüğü gibi lambda parametre listesinden önce birasync değiştirici ekleyin.
public partial class Form1 : Form { public Form1() { InitializeComponent(); button1.Click += async (sender, e) => { // ExampleMethodAsync returns a Task. await ExampleMethodAsync(); textBox1.Text += "\r\nControl returned to Click event handler.\r\n"; }; } async Task ExampleMethodAsync() { // The following line simulates a task-returning asynchronous process. await Task.Delay(1000); } }
Zaman uyumsuz yöntemlerin nasıl oluşturulacağı ve kullanılacağı hakkında daha fazla bilgi için bkz. Async ve Await ile Zaman Uyumsuz Programlama (C# ve Visual Basic).
Standart Sorgu İşlevleriyle Lambda İfadeleri
public delegate TResult Func<TArg0, TResult>(TArg0 arg0)
Temsilci; int değerinin giriş parametresi, bool değerinin dönüş değeri olduğu yerde Func<int,bool> myFunc olarak oluşturulabilir. Dönüş değeri her zaman son tür parametresinde belirtilir. Func<int, string, bool> bir temsilci ile int ve string olmak üzere iki giriş parametresi ve bool dönüş türü tanımlar. Aşağıdaki Func temsilcisi çağrıldığında, giriş parametresinin 5'e eşit olup olmadığını belirtmek için true ya da false döndürür:
Func<int, bool> myFunc = x => x == 5; bool result = myFunc(4); // returns false of course
Bağımsız değişken türü Expression<Func> olduğunda, örneğin standart sorgu işleçlerinde tanımlı System.Linq.Queryable gibi, lambda ifadesi sağlayabilirsiniz.Expression<Func> bağımsız değişken belirlediğinizde lambda ifade ağacında derlenecek.
Standart sorgu işleci olan Count yöntemi burada gösterilmektedir:
int[] numbers = { 5, 4, 1, 3, 9, 8, 6, 7, 2, 0 }; int oddNumbers = numbers.Count(n => n % 2 == 1);
Derleyici giriş parametresinin türünü çıkarabilir veya bunu açıkça belirtebilirsiniz. Bu belirli lambda ifadesi, ikiye bölündüğünde 1 kalan veren tamsayıları (n) sayar.
Aşağıdaki yöntem, numbers dizisinde 9'un sol tarafındaki tüm öğeleri içeren bir sıra oluşturur çünkü bu sayı sıradaki şu koşulu yerine getirmeyen ilk sayıdır:
var firstNumbersLessThan6 = numbers.TakeWhile(n => n < 6);
Bu örnek birden fazla giriş parametrelerini paranteze alarak belirtmeyi gösterir. Yöntem, değeri konumundan daha az olan bir sayı ile karşılaşana dek sayı dizisindeki tüm öğeleri döndürür. Lambda işlecini (=>) büyük veya eşittir işleciyle (>=) karıştırmayın.
var firstSmallNumbers = numbers.TakeWhile((n, index) => n >= index);
Lambda İçinde Tür Çıkarımı
customers.Where(c => c.City == "London");
Lambdalar için genel kurallar şunlardır:
- Lambda temsilci türüyle aynı sayıda parametre içermelidir.
- Lambdadaki her giriş parametresi, denk gelen temsilci parametresine dolaylı olarak dönüştürülebilir olmalıdır.
- Lambdanın (varsa) dönüş değeri örtük olarak temsilcinin dönüş türüne dönüştürülebilir olmalıdır.
Ortak tür sisteminin "lambda ifadesi" için iç kavramı olmadığından kendi içlerindeki lambda ifadelerinin türü olmadığını unutmayın. Ancak bazen bir lambda ifadesinin "türünden" resmi olmayan bir şekilde bahsetmek daha kolaydır. Bu gibi durumlarda, tür lambda ifadesinin dönüştürüldüğü temsilci türüne veya Expression türüne başvurur.
Lambda İfadelerinde Değişken Kapsamı
delegate bool D(); delegate bool D2(int i); class Test { D del; D2 del2; public void TestMethod(int input) { int j = 0; // Initialize the delegates with lambda expressions. // Note access to 2 outer variables. // del will be invoked within this method. del = () => { j = 10; return j > input; }; // del2 will be invoked after TestMethod goes out of scope. del2 = (x) => {return x == j; }; // Demonstrate value of j: // Output: j = 0 // The delegate has not been invoked yet. Console.WriteLine("j = {0}", j); // Invoke the delegate. bool boolResult = del(); // Output: j = 10 b = True Console.WriteLine("j = {0}. b = {1}", j, boolResult); } static void Main() { Test test = new Test(); test.TestMethod(5); // Prove that del2 still has a copy of // local variable j from TestMethod. bool result = test.del2(10); // Output: True Console.WriteLine(result); Console.ReadKey(); } }
Lambda ifadelerindeki değişken kapsam için aşağıdaki kurallar geçerlidir:
- Yakalanan bir değer, buna başvuran temsilci kapsamın dışına çıkıncaya kadar çöpte toplanamaz.
- Bir lambda ifadesi içinde tanıtılan değişkenler, dış yöntemde görünmez.
- Lambda ifadesi, kapsayan bir yöntemden alınan ref veya out parametresini doğrudan yakalayamaz.
- Lambda ifadesindeki bir dönüş ifadesi, kapsayan yöntemin döndürülmesine neden olmaz.
- Lambda ifadesi; hedefi, gövdenin dışında olan veya kapsanan anonim bir işlevin gövdesinde olan goto, break veya continue deyimini içeremez.
Hiç yorum yok:
Yorum Gönder