Bagikan melalui


Delegasi dan lambda

Delegasi menentukan jenis yang mewakili referensi ke metode yang memiliki daftar parameter tertentu dan jenis pengembalian. Metode (statis atau instans) yang daftar parameternya dan jenis pengembaliannya cocok dapat ditetapkan ke variabel jenis tersebut, lalu dipanggil secara langsung (dengan argumen yang sesuai) atau diteruskan sebagai argumen itu sendiri ke metode lain lalu dipanggil. Contoh berikut menunjukkan penggunaan delegate dalam pemrograman.

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"));
    }
}
  • public delegate string Reverse(string s); Baris ini membuat tipe delegasi dari metode yang menerima parameter berupa string dan kemudian mengembalikan string.
  • Metode static string ReverseString(string s), yang memiliki daftar parameter dan jenis pengembalian yang sama persis dengan tipe delegasi yang telah ditentukan, mengimplementasikan tipe delegasi.
  • Baris Reverse rev = ReverseString; menunjukkan bahwa Anda dapat menetapkan metode ke variabel jenis delegasi yang sesuai.
  • Baris Console.WriteLine(rev("a string")); menunjukkan cara menggunakan variabel jenis delegasi untuk memanggil delegasi.

Untuk menyederhanakan proses pengembangan, .NET menyertakan sekumpulan jenis delegasi yang dapat digunakan kembali oleh programmer dan tidak perlu membuat jenis baru. Jenis-jenis ini adalah Func<>, Action<> dan Predicate<>, dan dapat digunakan tanpa harus menentukan jenis delegasi baru. Ada beberapa perbedaan antara tiga jenis yang ada hubungannya dengan cara yang dimaksudkan untuk digunakan:

  • Action<> digunakan ketika ada kebutuhan untuk melakukan tindakan menggunakan argumen delegasi. Metode yang dienkapsulasinya tidak mengembalikan nilai.
  • Func<> biasanya digunakan ketika Anda memiliki transformasi di tangan, yaitu, Anda perlu mengubah argumen delegasi menjadi hasil yang berbeda. Proyeksi adalah contoh yang baik. Metode yang dienkapsulasinya mengembalikan nilai tertentu.
  • Predicate<> digunakan saat Anda perlu menentukan apakah argumen memenuhi kondisi delegasi. Ini juga dapat ditulis sebagai Func<T, bool>, yang berarti metode mengembalikan nilai boolean.

Sekarang kita dapat mengambil contoh di atas dan menulis ulang menggunakan fungsi delegasi Func<> alih-alih tipe khusus. Program akan terus berjalan persis sama.

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"));
    }
}

Untuk contoh sederhana ini, mempunyai metode yang didefinisikan di luar metode Main tampaknya agak berlebihan. .NET Framework 2.0 memperkenalkan konsep delegasi anonim, yang memungkinkan Anda membuat delegasi "sebaris" tanpa harus menentukan jenis atau metode tambahan apa pun.

Dalam contoh berikut, delegasi anonim memfilter daftar hanya ke angka genap lalu mencetaknya ke konsol.

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);
        }
    }
}

Seperti yang Anda lihat, bagian utama dari delegasi hanyalah sekumpulan ekspresi, seperti halnya delegasi yang lain. Tetapi alih-alih itu menjadi definisi terpisah, kami telah memperkenalkannya ad hoc dalam panggilan kami ke metode List<T>.FindAll.

Namun, bahkan dengan pendekatan ini, masih ada banyak kode yang dapat kita buang. Di sinilah ekspresi lambda mulai bermain. Singkatnya, ekspresi Lambda, atau hanya "lambda", diperkenalkan dalam C# 3.0 sebagai salah satu blok penyusun inti Language Integrated Query (LINQ). Mereka hanya sintaksis yang lebih nyaman untuk menggunakan delegasi. Mereka mendeklarasikan daftar parameter dan isi metode, tetapi tidak memiliki identitas formal mereka sendiri, kecuali jika ditetapkan ke delegasi. Tidak seperti delegasi, mereka dapat langsung ditetapkan sebagai bagian sebelah kanan dari pendaftaran event atau dalam berbagai klausa dan metode LINQ.

Karena ekspresi lambda hanyalah cara lain untuk menentukan delegasi, kita harus dapat menulis ulang sampel di atas untuk menggunakan ekspresi lambda alih-alih delegasi anonim.

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);
        }
    }
}

Dalam contoh sebelumnya, ekspresi lambda yang digunakan adalah i => i % 2 == 0. Sekali lagi, ini hanya sintaks yang praktis untuk menggunakan delegate. Apa yang terjadi di bawah sampul mirip dengan apa yang terjadi dengan delegasi anonim.

Sekali lagi, lambda hanya delegasi, yang berarti bahwa mereka dapat digunakan sebagai penanganan aktivitas tanpa masalah, seperti yang diilustrasikan cuplikan kode berikut.

public MainWindow()
{
    InitializeComponent();

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

Operator += dalam konteks ini digunakan untuk berlangganan peristiwa. Untuk informasi selengkapnya, lihat Cara berlangganan dan berhenti berlangganan dari acara.

Bacaan dan sumber daya lebih lanjut