C# 4 – Tìm hiểu về Lazy Initialization

lazy-cat‘Lazy Initialization’ là một thuật ngữ quen thuộc nói về phương pháp trì hoãn việc khởi tạo (hoặc nạp) dữ liệu cho đến khi chúng thực sự cần đến. Việc này rất hữu ích khi dữ liệu rất lớn và bạn không muốn người dùng tốn một tách café, ngồi chờ đợi những thứ chưa được sử dụng nhưng lại được nạp lên một cách … ‘xa xỉ’.

Theo cách thông thường, đây là một kĩ thuật rất đơn giản và áp dụng rất thường xuyên. Ví dụ như một property như sau hẳn là rất quen thuộc với đa số lập trình viên:

class Foo
{
    private object _lazyData = null;
    public object LazyData{
        get {
            if (_lazyData == null)
                _lazyData = LoadData();
            return _lazyData;
        }
    }
}

Trong C# 4, bạn không cần phải xử lý thủ công như trên để đạt được mục đích, hãy dành việc này cho .NET qua các class mà tôi giới thiệu qua hai ví dụ sau:

System.Lazy

Việc khởi tạo một đối tượng cần truyền vào một delegate Func để trả về dữ liệu (thay vì là dữ liệu trực tiếp). Khi đó dữ liệu vẫn chưa được nạp cho đến khi bạn lấy dữ liệu thông qua property lazyObj.Value.

static void Main(string[] args)
{
    var lazyObj = new Lazy<object>(() => { return LoadData(); });

    Console.WriteLine(lazyObj);         // (1)
    Console.WriteLine(lazyObj.Value);   // (2) (3)

    Console.ReadLine();
}

static string LoadData(){
    System.Console.WriteLine("Start loading data.");
    return "This is a 'HUGE data'.";
}
// Output:
// Value is not created. 	(1)
// Start loading data.		(2)
// This is the 'data'.		(3)

System.Threading.LazyInitializer

Nếu bạn không thích dữ liệu được wrap vào lớp Lazy, bạn có thể sử dụng một phương pháp trực tiếp hơn thông qua phương thức tĩnh EnsureInitialized() của lớp LazyInitializer. Phương thức này sẽ kiểm tra và nạp dữ liệu nếu biến (lazyObj) chưa có giá trị.

static void Main(string[] args)
{
    object lazyObj = null;
    Console.WriteLine("Data has not been loaded.");

    LazyInitializer.EnsureInitialized(ref lazyObj, () => { return LoadData(); });
    Console.WriteLine(lazyObj);

    Console.ReadLine();
}

static string LoadData(){
    System.Console.WriteLine("Start loading data.");
    return "This is a 'HUGE data'.";
}

// OUTPUT:
// Data has not been loaded yet.
// Start loading data.
// This is a 'HUGE data'.

Bạn cũng có thể sử dụng một cờ kiểu boolean để xác định việc dữ liệu đã được nạp hay chưa bằng cách dùng overload sau của EnsureInitialized():

object lazyObj = 1;
bool loaded = false;
object datalock = new object();

LazyInitializer.EnsureInitialized(ref lazyObj, ref loaded, ref datalock, () => { return LoadData(); });

YinYangIt’s Blog

Advertisements

7 thoughts on “C# 4 – Tìm hiểu về Lazy Initialization

  1. Mình thường đọc các bài viết của bạn trên blog, thấy nó rất có ích cho mình . Nhưng mình chưa hiểu khi không sử dụng lazy với khi sử dụng khác nhau như thế nào ? Bởi khi mình viết code thì khi nào cần mình mới khởi tạo

    [Code]
    class Foo
    {
    public string _lazy ;
    public object LazyData{

    return LoadData();

    }
    public string LoadData(){
    _lazy=”a”;
    }
    }
    // khi gọi
    Class Foo = new ClassFoo();
    Foo._lazy;
    [/Code]
    Không biết cách viết của mình có lỗi gì không ? Mong bạn sớm phản hồi

    Phản hồi

Trả lời

Mời bạn điền thông tin vào ô dưới đây hoặc kích vào một biểu tượng để đăng nhập:

WordPress.com Logo

Bạn đang bình luận bằng tài khoản WordPress.com Log Out / Thay đổi )

Twitter picture

Bạn đang bình luận bằng tài khoản Twitter Log Out / Thay đổi )

Facebook photo

Bạn đang bình luận bằng tài khoản Facebook Log Out / Thay đổi )

Google+ photo

Bạn đang bình luận bằng tài khoản Google+ Log Out / Thay đổi )

Connecting to %s