簡體   English   中英

我是代表們的新手,並想知道如何分解以下代碼

[英]I am new to delegates and wonder how to break down the following code

我有以下代碼,我想知道如何分解它? 它工作得很好,但是是由一位大師寫的並且超出了我的想象。 預先感謝您的任何幫助。

該代碼基本上將發送和接收的設備信息寫入GUI。 看起來它有基於設備創建的事件,並且還調用GUI內容。

  1. 你為什么需要調用?
  2. 我想我想知道這是否過於復雜或合適? 什么是完成相同任務的更好方法?
  3. 我也想知道“代表{};” 呢?

公共事件EventHandler CommunicationPerformed = delegate {};

    SerialPort _port;
    readonly int _delay = 100;


    private string ReadAndUpdateStatus()
    {
        string read = _port.ReadExisting();
        CommunicationPerformed?.Invoke(this, new LoaderReadWriteEventArgs(read, LoaderCommunicationDirection.Read));
        return read;
    }

    private void WriteAndUpdateStatus(string data)
    {
        if (!data.StartsWith("//")) //ignore "Comment" lines but show them on the GUI to read
            _port.Write(data);
        CommunicationPerformed?.Invoke(this, new LoaderReadWriteEventArgs(data, LoaderCommunicationDirection.Write));
    }



public class LoaderReadWriteEventArgs : EventArgs
{
    public LoaderCommunicationDirection Direction { get; }

    public string Value { get; }

    public LoaderReadWriteEventArgs(string value, LoaderCommunicationDirection direction)
    {
        Value = value;
        Direction = direction;
    }
}

public enum LoaderCommunicationDirection
{
    Read,
    Write
}

你問了三個問題,和往常一樣,只有一個問題得到了回答。 試着在你的問題中只問一個問題。

我也想知道delegate { }是什么?

  public event EventHandler CommunicationPerformed = delegate { }; 

正如另一個答案所指出的,默認情況下C#中的事件為空。 此技術使事件處理程序不執行任何操作 ,但不為null

遺憾的是,C#中的匿名函數有許多語法。 delegate {}表示“給我一個無用的函數,匹配任何返回無效的非ref-out形式參數列表”。 這就是人們delegate{}的原因,因為它幾乎可以在需要事件處理程序的上下文中工作。

我想你需要查看這個https://docs.microsoft.com/en-us/dotnet/standard/events/

你為什么需要調用?

向廣播事件處理程序廣播(注冊此事件的任何一方都會收到通知)

我想我想知道這是否過於復雜或合適?

*完成相同任務可能是更好的方法嗎?

這並不復雜。 這非常簡單。*

我也想知道“代表{};” 呢?

我的兩分錢。 我不知道您引用的是哪個代碼行,但委托是一種包含對方法的引用的類型。 委托聲明帶有簽名,該簽名顯示它引用的方法的返回類型和參數,並且只能保存對與其簽名匹配的方法的引用。 因此委托等同於類型安全函數指針或回調。 委托聲明足以定義委托類。

我要嘗試回答#1和#2(已經覆蓋了3個)。

#1 - 在某些時候,某人決定該程序的其他部分可以訂閱一個事件,告訴他們何時進行了通信。 一旦做出決定,這就是一種“合同”。 您執行通信 - >觸發事件,通知訂閱者已執行通信。 那些訂閱者正在做些什么,或者為什么他們需要知道......如果這個課程是你的重點,那么你真的不關心。 從理論上講,至少。 而且通常情況確實如此。 如果你的班級正在做自己的工作,那么聽你們關注這些事件並不是你真正關心的問題。

#2 - 想聲明的事件和事件處理程序在你的代碼的方法過於復雜。 很多人(以及微軟的官方最佳實踐 )都不同意我的意見。 你可以谷歌“為什么我的事件處理程序應該使用eventargs”並閱讀有關該主題的大量內容。 或者看這里 另一種方法如下:

public event Action<string, LoaderCommunicationDirection> CommunicationPerformed;
void PerformWrite()
{
  string myComm = "String I'm sending";
  //Line of code that performs communication that writes string here
  CommunicationPerformed?.Invoke(myComm, LoaderCommunicationDirection.Write);
}

這比從EventArgs派生的整個類簡潔得多。 但是,它有一個非常明顯的缺點,如果你是一個事件訂閱者...你不知道什么是string 當然,因為它在你的代碼中被命名為value ...這沒有多大幫助。 事件聲明上方的評論幾乎同樣有用。

orhtej2很好地回答了你的第一個問題。 使用顯式的Invoke方法允許您利用null條件運算符,這會減少代碼以將事件觸發到一行。

至於這是否過於復雜:不,這基本上是事件的完成方式。

我有時看到的(尤其是與MVVM模式中的INotifyPropertyChanged接口結合使用)是輔助方法,它封裝了更長但更明顯的前C#6代碼,讓您以更少的管道激活事件。

private void FireCommPerformed(string value, LoaderCommunicationDirection direction) 
{ 
    EventHandler handler = CommunicationPerformed;
    if (handler != null)
    {
        handler(this, new LoaderReadWriteEventArgs(value, direction)));
    }
}

然后你可以像這樣使用它:

private string ReadAndUpdateStatus()
{
    string read = _port.ReadExisting();
    FireCommPerformed(read, LoaderCommunicationDirection.Read);
    return read;
}

Delegate {}只是一個空委托,就像事件的null一樣。 除非代碼中的某些其他方法在運行時期間訂閱此類的CommunicationPerformed事件,否則在觸發事件時不會發生任何事情。

讓我們專注於這里發生的事情。 這應該可以幫助你弄清楚其他一切。

CommunicationPerformed?.Invoke(this, new LoaderReadWriteEventArgs(read, LoaderCommunicationDirection.Read));

這是檢查委托(事件處理程序是委托)(CommunicationPerformed)是否為空。

代表是指針(但具有額外的功能)。

如果委托(指針)為空,則表示沒有為其分配任何內容。

指針存儲內存位置。 在這種情況下,它會對函數'this'進行內存引用。 'this'是對ReadAndUpdateStatus()的引用。

所以這一行基本上說:“因為指針為空,所以讓這個指針引用ReadAndUpdateStatus()函數”。

但事件args怎么樣? 嗯......這是代表們與指針不同的地方。

代表們不僅可以安全地保存和存儲內存位置。 它們也可以保存參數。

您使用從EventArgs擴展的類作為傳遞參數列表的方式。

從這里開始,事件處理程序(事件處理程序是委托)CommunicationPerformed將協調將參數列表發送到任何需要它的函數。

每當調用CommunicationPerformed時(例如告訴運行),都會調用這些函數。 這通常表示為:

+=CommunicationPerformed(foo,bar) 

現在 - 為什么要使用事件處理程序(或任何委托 - 就此而言)?

他們閱讀比較繁瑣煩人(比編寫一個簡單的bool和觸發器功能更多的工作),它們看起來不像其他功能,而且它們很坦白 - 對吧?

除了他們真的有用。 這是如何做:

1.)他們的工作很像任務。 您可以在並行,循環,任何地方調用它們。 他們保持一致的狀態。 它們不會“流血”並導致錯誤。

2.)他們是指針。 保證傳遞參考。 除此之外,它們是神奇的,如果你停止使用代表,它們就不會留在記憶中。

3.)它們允許您控制循環中的狀態。 有時,如果你處於一個非常緊湊的循環中,bool觸發器將無法正常工作。 你開了一個活動? 保證您的觸發器只會被觸發一次的行為。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM