0Pricing
C# Academy · Pelajaran

Semantik Evaluasi Malas

Pahami eksekusi tertunda pada iterator.

Semantik Evaluasi Malas adalah pelajaran C# Academy gratis di CoddyKit. Ini adalah pelajaran 3 dari 4. Kamu bisa membaca pelajaran lengkapnya di bawah secara gratis — lalu praktikkan langsung di browser dengan editor kode bawaan dan tutor AI 24/7. Ini adalah bagian dari jalur belajar C# Academy, dan progresmu tersinkronisasi di web dan aplikasi CoddyKit. Kursus C# Academy mencakup 4 pelajaran total.

Eksekusi Tertunda

Iterator dan query LINQ menggunakan eksekusi tertunda: mendefinisikan query hampir tidak melakukan apa pun. Pekerjaan baru berlangsung saat Anda benar-benar melakukan enumerasi terhadap hasil, item demi item.

Tidak Ada yang Berjalan Sebelum Enumerasi

Memanggil metode iterator tidak menjalankan isi metodenya. Isi tersebut mulai dieksekusi hanya ketika sebuah foreach (atau konsumen lain) mengambil nilai pertama.

using System;
using System.Collections.Generic;

public class Program
{
    static IEnumerable<int> Numbers()
    {
        Console.WriteLine("-- iterator body started --");
        yield return 1;
        yield return 2;
    }

    public static void Main()
    {
        var seq = Numbers();
        Console.WriteLine("query created, body not run yet");
        foreach (var n in seq) Console.WriteLine(n);
    }
}

Nilai Dihasilkan Satu per Satu

Setiap iterasi hanya menjalankan bagian iterator yang cukup untuk menghasilkan nilai berikutnya. Model berbasis pengambilan ini menjaga penggunaan memori tetap rendah, bahkan untuk urutan yang sangat besar.

using System;
using System.Collections.Generic;

public class Program
{
    static IEnumerable<int> Trace()
    {
        for (int i = 1; i <= 3; i++)
        {
            Console.WriteLine("producing " + i);
            yield return i;
        }
    }

    public static void Main()
    {
        foreach (var n in Trace())
            Console.WriteLine("consumed " + n);
    }
}

Enumerasi Ulang Menjalankan Kembali

Urutan tertunda tidak memiliki hasil yang tersimpan. Melakukan enumerasi dua kali mengeksekusi iterator dua kali, yang penting jika source berubah atau pekerjaannya mahal.

using System;
using System.Collections.Generic;

public class Program
{
    static int _calls = 0;
    static IEnumerable<int> Counter()
    {
        _calls++;
        yield return _calls;
    }

    public static void Main()
    {
        var seq = Counter();
        foreach (var n in seq) Console.WriteLine(n);
        foreach (var n in seq) Console.WriteLine(n);
        Console.WriteLine("total runs: " + _calls);
    }
}

Menangkap Keadaan Terkini

Karena eksekusi tertunda, iterator membaca source saat enumerasi, bukan saat definisi. Perubahan yang dibuat setelah query didefinisikan akan terlihat.

using System;
using System.Collections.Generic;

public class Program
{
    public static void Main()
    {
        var list = new List<int> { 1, 2 };
        IEnumerable<int> doubled = Double(list);
        list.Add(3); // added before enumeration
        foreach (var n in doubled) Console.WriteLine(n);
    }

    static IEnumerable<int> Double(IEnumerable<int> nums)
    {
        foreach (var n in nums) yield return n * 2;
    }
}

Memaksa Eksekusi Seketika

Untuk mengambil cuplikan hasil, materialisasikan urutan dengan ToList() atau ToArray(). Ini menjalankan iterator sekali dan menyimpan nilainya, sehingga terlepas dari perubahan source berikutnya.

using System;
using System.Collections.Generic;
using System.Linq;

public class Program
{
    public static void Main()
    {
        var list = new List<int> { 1, 2 };
        List<int> snapshot = Double(list).ToList(); // executed now
        list.Add(99);
        Console.WriteLine(string.Join(",", snapshot));
    }

    static IEnumerable<int> Double(IEnumerable<int> nums)
    {
        foreach (var n in nums) yield return n * 2;
    }
}

Pemangkasan Lebih Awal Menghemat Pekerjaan

Karena konsumen mengambil nilai secara malas, operasi seperti first yang mencari kecocokan dapat berhenti lebih awal. Produsen tidak pernah menghitung nilai yang tidak pernah diminta.

using System;
using System.Collections.Generic;
using System.Linq;

public class Program
{
    static IEnumerable<int> Numbers()
    {
        for (int i = 1; ; i++)
        {
            Console.WriteLine("checking " + i);
            yield return i;
        }
    }

    public static void Main()
    {
        int firstBig = Numbers().First(n => n > 3);
        Console.WriteLine("found " + firstBig);
    }
}

Pengecualian yang Tertunda

Pengecualian di dalam iterator tidak dilempar saat metode dipanggil, melainkan saat enumerasi mencapai baris yang gagal. Hal ini dapat mengejutkan jika Anda mengharapkan validasi sejak awal.

using System;
using System.Collections.Generic;

public class Program
{
    static IEnumerable<int> Risky(int divisor)
    {
        yield return 10 / divisor; // throws only during enumeration
    }

    public static void Main()
    {
        var seq = Risky(0);
        Console.WriteLine("no error yet");
        try { foreach (var n in seq) Console.WriteLine(n); }
        catch (DivideByZeroException) { Console.WriteLine("caught during enumeration"); }
    }
}

Alur Malas Dapat Digabungkan Secara Efisien

Merangkai operator malas tidak menjalankannya berulang kali. Setiap nilai mengalir melalui seluruh alur pemrosesan satu kali, sesuai kebutuhan, sehingga penggunaan memori dan pekerjaan tetap efisien.

using System;
using System.Collections.Generic;
using System.Linq;

public class Program
{
    public static void Main()
    {
        var result = Enumerable.Range(1, 1000000)
            .Where(n => n % 2 == 0)
            .Select(n => n * n)
            .Take(3);
        foreach (var n in result) Console.WriteLine(n);
    }
}

Kapan Melakukan Materialisasi

Lakukan materialisasi jika Anda akan melakukan enumerasi beberapa kali, jika source mungkin berubah, atau jika Anda harus mengambil hasil sebelum melepaskan sumber daya. Jika tidak, tetap gunakan eksekusi malas untuk menghemat memori dan pekerjaan.

using System;
using System.Collections.Generic;
using System.Linq;

public class Program
{
    public static void Main()
    {
        var evens = Enumerable.Range(1, 10).Where(n => n % 2 == 0).ToList();
        // Safe to enumerate many times now
        Console.WriteLine("count: " + evens.Count);
        Console.WriteLine("sum: " + evens.Sum());
    }
}

Coba Sendiri

Amati eksekusi tertunda secara langsung: sebuah query didefinisikan, source berubah, dan perubahan itu baru muncul dalam hasil saat enumerasi dilakukan.

using System;
using System.Collections.Generic;
using System.Linq;

public class Program
{
    public static void Main()
    {
        var source = new List<int> { 1, 2, 3 };
        var query = source.Where(n => n > 1); // not executed yet
        source.Add(10);
        source.Remove(2);
        // Executes now, reflecting all changes
        Console.WriteLine(string.Join(", ", query));
    }
}

Pemeriksaan Singkat

Bernalarlah tentang eksekusi tertunda.

Ringkasan

Evaluasi malas (tertunda) hanya menjalankan urutan saat dienumerasi.

  • Mendefinisikan query tidak melakukan pekerjaan; mengonsumsinya yang melakukan pekerjaan.
  • Melakukan enumerasi ulang akan menjalankan kembali iterator.
  • Source dibaca saat enumerasi, sehingga perubahan berikutnya akan terlihat.
  • Pengecualian muncul selama enumerasi.
  • Gunakan ToList()/ToArray() untuk melakukan materialisasi jika diperlukan.

Pertanyaan yang Sering Diajukan

Apakah pelajaran “Semantik Evaluasi Malas” gratis?

Ya — teks lengkap “Semantik Evaluasi Malas” gratis dibaca di sini di web. Untuk praktiknya secara interaktif (editor kode bawaan dan tutor AI 24/7) dan buka sisa kursus C# Academy, upgrade ke CoddyKit PRO. Kursus C# Academy mencakup 4 pelajaran total.

Apa yang akan aku pelajari di “Semantik Evaluasi Malas”?

Pahami eksekusi tertunda pada iterator. Kamu berlatih C# Academy dengan kode praktik yang langsung kamu jalankan di browser, dan tutor AI 24/7 menjawab pertanyaanmu saat kamu mengerjakan pelajaran ini.

Apakah aku perlu pengalaman untuk memulai C# Academy?

Tidak diperlukan pengalaman sebelumnya. C# Academy di CoddyKit dirancang untuk pemula hingga pelajar tingkat lanjut, jadi kamu bisa memulai di sini atau dari awal dan belajar sesuai kecepatan kamu sendiri. Ini adalah pelajaran 3 dari 4.

Berapa lama pelajaran “Semantik Evaluasi Malas” memakan waktu?

Sebagian besar pelajaran CoddyKit memakan waktu sekitar 5–10 menit. Setiap pelajaran ringkas dan interaktif, jadi kamu membuat kemajuan stabil dan melanjutkan dari tempat kamu tinggalkan di web dan aplikasi.

Bisakah aku menulis dan menjalankan kode dalam pelajaran C# Academy ini?

Ya. Setiap pelajaran C# Academy menyertakan editor kode bawaan, jadi kamu menulis dan menjalankan kode nyata langsung di browser dan mendapatkan umpan balik AI instan — tidak diperlukan penyiapan lokal.

Semua pelajaran dalam kursus ini

  1. Metode Iterator dengan yield return
  2. yield break dan Penghentian Dini
  3. Semantik Evaluasi Malas
  4. Enumerable Kustom
← Kembali ke C# Academy