it-swarm-vi.com

Sử dụng thực tế của các đại biểu C #

Tôi nghĩ rằng về mặt khái niệm tôi hiểu các đại biểu C #, tuy nhiên, tôi đang vật lộn để tìm một ví dụ trong thế giới thực nơi họ sẽ hữu ích. Bạn có thể cung cấp một số câu trả lời chi tiết về cách các đại biểu C # được sử dụng trong các ứng dụng thực không và những vấn đề họ cho phép bạn giải quyết.

16
AlexC

Mã GUI sử dụng các đại biểu để xử lý các sự kiện, chẳng hạn như nhấp vào nút, di chuyển cửa sổ. Sử dụng ủy nhiệm cho phép bạn có một hàm được gọi bất cứ khi nào sự kiện xảy ra. Một ví dụ sẽ liên kết một chức năng lưu dữ liệu vào nút "Lưu" trên giao diện. Khi nhấn vào nút, nó được thiết lập để thực hiện chức năng lưu dữ liệu. Nó hữu ích trong lập trình GUI vì toàn bộ chương trình của bạn có thể đang chờ người dùng làm gì đó và bạn không có cách nào biết họ sẽ làm gì trước tiên. Việc sử dụng các đại biểu cho phép chức năng của chương trình của bạn được kết nối với giao diện người dùng theo cách mà người dùng có thể thực hiện mọi việc theo bất kỳ cách nào họ muốn.

16

Linq sử dụng Func<T>Action<T> đại biểu khắp nơi làm tham số.

Điều này cho phép bạn sử dụng biểu thức lambda làm tham số và xác định hành động được thực hiện như một phần của danh sách tham số.

12
Oded

Hầu như mọi thứ sử dụng Mẫu quan sát sẽ có khả năng triển khai các đại biểu.

Đọc mô tả và bạn có thể sẽ tưởng tượng một số tình huống mà bạn sẽ sử dụng chúng. Xử lý sự kiện GUI là một ví dụ phổ biến.

12
whatsisname

Các đại biểu rất hữu ích trong lập trình không đồng bộ.

Bạn có một lớp làm công cụ không đồng bộ và có một cuộc gọi lại. Bạn có thể yêu cầu phương thức ủy nhiệm khi gọi lại - và việc triển khai lớp của bạn sẽ thực hiện logic được mô tả trong phương thức ủy nhiệm của bạn.

9
James Love

Các đại biểu đặc biệt hữu ích như một giải pháp cho lỗ ở mẫu giữa . Về cơ bản, có rất nhiều trường hợp bạn muốn bọc một bộ hướng dẫn duy nhất bên trong một loạt các hướng dẫn chung. Điều này đặc biệt khó khăn nếu các hướng dẫn trước và sau bit duy nhất cần chia sẻ trạng thái. Với các đại biểu, bạn chỉ có thể chuyển một đại biểu vào một chức năng. Hàm thực thi bit trước, thực thi ủy nhiệm, sau đó thực hiện bit sau.

9
Scott Whitlock

Trong "ngày xưa" của các ngôn ngữ không phải OOP như Fortran và C, thật hữu ích khi có thể có một chương trình con nhận được một đối số là con trỏ tới hàm. Ví dụ: hàm qsort hoạt động với chức năng so sánh do người dùng cung cấp. Có rất nhiều chương trình con để giải các phương trình vi phân thông thường hoặc để tối ưu hóa các hàm và tất cả chúng đều lấy các con trỏ hàm làm đối số.

Trong các hệ thống cửa sổ, tất cả các loại gọi lại theo cùng một mẫu.

Trong LISP, ngay cả trong những ngày đầu, có một thứ gọi là "đối số chức năng" hoặc FUNARG, không chỉ là một chức năng, mà nó còn chứa một bối cảnh lưu trữ nơi nó có thể nhớ và tương tác với một phần của thế giới bên ngoài.

Nhu cầu tương tự này tồn tại trong các ngôn ngữ OOP, ngoại trừ khi bạn chuyển địa chỉ của hàm, bạn cũng phải truyền địa chỉ của đối tượng, hàm đó là một phương thức. Đó là hai điều bạn phải vượt qua Vì vậy, một đại biểu chỉ là như vậy, và cho phép mô hình cũ tốt đó vẫn được sử dụng.

5
Mike Dunlavey

Dưới đây là một ví dụ đơn giản cho thấy các đại biểu hữu ích có thể tạo mã đơn giản theo nguyên tắc DRY. Nó cũng cho phép bạn giữ mã cực kỳ gần với nơi cần thiết.

Action<Button, Action<Button>> prepareButton = 
    (btn, nxt) => { 
        btn.Height = 32;
        btn.Width= 64;
        nxt(btn);
    };

prepareButton(myBtn1, btn => btn.Text = "A");
prepareButton(myBtn2, btn => btn.Text = "B");
prepareButton(myBtn3, btn => btn.Text = "C");

Dưới đây là một ví dụ thực tế về lợi thế mà các đại biểu cung cấp.

protected override void PageInitialize()
{
    const string selectCodeFormat = "javascript:selectCode('{0}', '{1}');";
    const string onClick = "return toggleElement(this);";

    Func<HtmlGenericControl> getElement = null;
    Action<HtmlGenericControl> setElement = null, addChild = null;
    HtmlGenericControl level1Element = null, level2Element = null, level3Element = null, level4Element = null;
    string className = null, code = null, description = null;           

    using (var records = Core.Database.ExecuteRecords("code.SocCodeTree"))
    {
        while (records.Read())
        {
            code = records.GetString("Code");
            description = records.GetString("Description"); 

            if (records.GetString("Level4") != "")
            {
                className = "Level4";
                setElement = e => level4Element = e;
                getElement = () => level4Element;
                addChild = e => level3Element.Controls.Add(e);
            }
            else if (records.GetString("Level3") != "")
            {
                className = "Level3";
                setElement = e => level3Element = e;
                getElement = () => level3Element;
                addChild = e => level2Element.Controls.Add(e);
            }
            else if (records.GetString("Level2") != "")
            {
                className = "Level2";
                setElement = e => level2Element = e;
                getElement = () => level2Element;
                addChild = e => level1Element.Controls.Add(e);
            }
            else
            {
                className = "Level1";
                setElement = e => level1Element = e;
                getElement = () => level1Element;
                addChild = e => Root.Controls.Add(e);
            }

            var child = new HtmlGenericControl("li");
            child.Attributes["class"] = className;
            var span = new HtmlGenericControl("span") { 
                InnerText = code + " - " + description + " - " 
            };
            span.Attributes["onclick"] = onClick;
            child.Controls.Add(span);
            var a = new HtmlAnchor() { 
                InnerText = "Select", 
                HRef = string.Format(selectCodeFormat, code, description) 
            };
            child.Controls.Add(a);
            setElement(new HtmlGenericControl("ul"));
            child.Controls.Add(getElement());
            addChild(child);    
        }
    }
}
3
ChaosPandion

Cuộc gặp gỡ đầu tiên của tôi với các đại biểu là kiểm tra cập nhật chương trình (windows form C # 3.5) bằng cách tải xuống một tệp từ trang web của tôi, nhưng để tránh việc cập nhật kiểm tra khóa toàn bộ chương trình, tôi đã sử dụng một đại biểu và một luồng để thực hiện không đồng bộ.

2
Ken

Tôi đã thấy các triển khai thú vị của mẫu Chiến lược sử dụng các đại biểu một cách hiệu quả. (tức là chiến lược là một đại biểu)

Cái tôi đang tìm kiếm là tìm đường dẫn trong đó thuật toán tìm đường dẫn là một đại biểu có thể được gán lại trong thời gian chạy để có thể sử dụng các thuật toán khác nhau (BFS vs A *, v.v.)

1
Steven Evers

Nhiều mẫu GoF cổ điển có thể được triển khai với các đại biểu: Ví dụ: Mẫu lệnh, Mẫu khách truy cập, Mẫu chiến lược, Mẫu nhà máy và Mẫu quan sát thường có thể được triển khai với một đại biểu đơn giản. Đôi khi, một lớp tốt hơn (ví dụ: khi một lệnh cần một tên hoặc một đối tượng chiến lược cần được tuần tự hóa) nhưng trong hầu hết các trường hợp, sử dụng Action<...> hoặc là Func<...> thanh lịch hơn nhiều so với việc tạo giao diện một phương thức chuyên dụng.

1
nikie