Aracılığıyla paylaş


Temsilciler ve lambda ifadeleri

Temsilci, belirli bir parametre listesine ve dönüş türüne sahip yöntemlere başvuruları temsil eden bir tür tanımlar. Parametre listesi ve dönüş türü eşleşmesi bu türdeki bir değişkene atanabilen, ardından doğrudan (uygun bağımsız değişkenlerle) çağrılabilen veya bağımsız değişken olarak başka bir yönteme geçirilip çağrılabilen bir yöntem (statik veya örnek). Aşağıdaki örnekte temsilci kullanımı gösterilmektedir.

using System;
using System.Linq;

public class Program
{
    public delegate string Reverse(string s);

    static string ReverseString(string s)
    {
        return new string(s.Reverse().ToArray());
    }

    static void Main(string[] args)
    {
        Reverse rev = ReverseString;

        Console.WriteLine(rev("a string"));
    }
}
  • Satır, public delegate string Reverse(string s); dize parametresini alan ve ardından bir dize parametresi döndüren bir yöntemin temsilci türünü oluşturur.
  • static string ReverseString(string s) Tanımlanan temsilci türüyle tam olarak aynı parametre listesine ve dönüş türüne sahip olan yöntemi, temsilciyi uygular.
  • Satır, Reverse rev = ReverseString; ilgili temsilci türündeki bir değişkene yöntem atayabileceğinizi gösterir.
  • Satır, Console.WriteLine(rev("a string")); temsilciyi çağırmak için temsilci türünde bir değişkenin nasıl kullanılacağını gösterir.

Geliştirme sürecini kolaylaştırmak için .NET, programcıların yeniden kullanabileceği ve yeni türler oluşturması gerekmeyen bir temsilci türleri kümesi içerir. Bu türler , Action<> ve Predicate<>'tir Func<>ve yeni temsilci türleri tanımlamak zorunda kalmadan kullanılabilir. Kullanılması amaçlanan şekilde yapılması gereken üç tür arasında bazı farklılıklar vardır:

  • Action<> , temsilcinin bağımsız değişkenlerini kullanarak bir eylem gerçekleştirmeye ihtiyaç duyulduğunda kullanılır. Kapsüllediği yöntem bir değer döndürmez.
  • Func<> genellikle elinizde bir dönüşüm olduğunda kullanılır, yani temsilcinin bağımsız değişkenlerini farklı bir sonuca dönüştürmeniz gerekir. Projeksiyonlar iyi bir örnektir. Kapsülledüğü yöntem, belirtilen bir değeri döndürür.
  • Predicate<> , bağımsız değişkenin temsilcinin koşuluna uygun olup olmadığını belirlemeniz gerektiğinde kullanılır. Yöntemin boole değeri döndürdüğü anlamına gelen olarak Func<T, bool>da yazılabilir.

Artık yukarıdaki örneğimizi alıp özel bir tür yerine temsilciyi Func<> kullanarak yeniden yazabiliriz. Program tam olarak aynı şekilde çalışmaya devam edecektir.

using System;
using System.Linq;

public class Program
{
    static string ReverseString(string s)
    {
        return new string(s.Reverse().ToArray());
    }

    static void Main(string[] args)
    {
        Func<string, string> rev = ReverseString;

        Console.WriteLine(rev("a string"));
    }
}

Bu basit örnekte, yöntemin dışında tanımlanmış bir yöntemin Main olması biraz gereksiz görünüyor. .NET Framework 2.0, herhangi bir ek tür veya yöntem belirtmek zorunda kalmadan "satır içi" temsilciler oluşturmanıza olanak tanıyan anonim temsilciler kavramını ortaya atmıştı.

Aşağıdaki örnekte anonim bir temsilci listeyi yalnızca çift sayılara göre filtreler ve ardından konsola yazdırır.

using System;
using System.Collections.Generic;

public class Program
{
    public static void Main(string[] args)
    {
        List<int> list = new List<int>();

        for (int i = 1; i <= 100; i++)
        {
            list.Add(i);
        }

        List<int> result = list.FindAll(
          delegate (int no)
          {
              return (no % 2 == 0);
          }
        );

        foreach (var item in result)
        {
            Console.WriteLine(item);
        }
    }
}

Gördüğünüz gibi, temsilcinin gövdesi diğer temsilciler gibi yalnızca bir ifade kümesidir. Ancak bunun ayrı bir tanım olması yerine yöntemine yaptığımız çağrıda geçici olarak kullanıma sundukList<T>.FindAll.

Ancak, bu yaklaşımda bile atabileceğiniz çok fazla kod vardır. Lambda ifadeleri burada devreye girer. Lambda ifadeleri veya kısaca "lambdalar", C# 3.0'da Dil Tümleşik Sorgu'nun (LINQ) temel yapı taşlarından biri olarak tanıtıldı. Bunlar yalnızca temsilcileri kullanmak için daha kullanışlı bir söz dizimidir. Bir parametre listesi ve yöntem gövdesi bildirir, ancak temsilciye atanmadıkları sürece kendi resmi kimliklerine sahip olmazlar. Temsilcilerden farklı olarak, bunlar doğrudan olay kaydının sağ tarafı olarak veya çeşitli LINQ yan tümcelerinde ve yöntemlerinde atanabilir.

Lambda ifadesi temsilci belirtmenin başka bir yolu olduğundan, anonim temsilci yerine lambda ifadesi kullanmak için yukarıdaki örneği yeniden yazabilmeliyiz.

using System;
using System.Collections.Generic;

public class Program
{
    public static void Main(string[] args)
    {
        List<int> list = new List<int>();

        for (int i = 1; i <= 100; i++)
        {
            list.Add(i);
        }

        List<int> result = list.FindAll(i => i % 2 == 0);

        foreach (var item in result)
        {
            Console.WriteLine(item);
        }
    }
}

Yukarıdaki örnekte kullanılan lambda ifadesi şeklindedir i => i % 2 == 0. Yine bu, temsilcileri kullanmak için kullanışlı bir söz dizimidir. Kapakların altında gerçekleşenler, anonim temsilciyle yapılana benzer.

Lambda'lar da yalnızca temsilcilerdir ve bu da aşağıdaki kod parçacığında gösterildiği gibi sorunsuz bir olay işleyicisi olarak kullanılabildikleri anlamına gelir.

public MainWindow()
{
    InitializeComponent();

    Loaded += (o, e) =>
    {
        this.Title = "Loaded";
    };
}

+= Bu bağlamda işleç bir olaya abone olmak için kullanılır. Daha fazla bilgi için bkz . Olaylara abone olma ve abonelikten çıkma.

Daha fazla okuma ve kaynak