2012-11-23 44 views
5

我有以下代碼中定義的類和委託(爲了簡潔起見剪切了許多其他行)。當代理簽名不匹配時沒有錯誤

Public Delegate Sub TimerCallback(canceled As Boolean) 

Public Class Timer 
    Implements TimerManager.ITimer 

    Public Sub New(delay As Integer, callback As TimerCallback) 
     mState = TimerState.Setup 
     mCallback = callback 
     CType(TimerManager.Instance, TimerManager.ITimerManager).RegisterTimer(Me, delay) 
    End Sub 
End Class 

當我創建了下面的代碼計時器的新實例,我沒有得到一個編譯錯誤,即使匿名函數的簽名不匹配委託的簽名(它缺少「取消布爾「參數)。

Dim timer As New Timer(Me.CookTime, Sub() 
             Dim cooked As FoodBase = CType(Activator.CreateInstance(SuccessfulResult), FoodBase) 
             player.GetBackpack.AddItem(cooked) 
            End Sub) 

我希望得到一個編譯錯誤實例化計時器時這種方式,任何人都可以解釋爲什麼它沒有差錯編譯?有沒有我能設置的選項會導致它產生編譯錯誤?我有選項明確的,選項嚴格,並在項目屬性選項推斷。事實上,忘記包含取消的論點太容易了。

回答

4

是的。這很好 - 編譯器可以生成一個匿名方法知道需要的簽名,而不是使用它給出的參數。所以編譯器生成的方法會有這個參數 - 它就是不會用它。您可以使用delegate { ... }在C#中執行相同的操作。

+1

是不是強制鍵入參數到TimerCallback以確保方法簽名匹配?如果Option Infer設置爲On,我可能會看到這種行爲。但通過設置Option Infer Off,我希望編譯器不會推斷任何內容並強制簽名。對於我的問題的第二部分,是否有任何解決方案來強制編譯生成錯誤或至少在這種情況下發出警告? –

3

這種現象被稱爲Relaxed Delegate Conversion,並且在Option Strict爲onoff時具有稍微不同的行爲。請點擊鏈接瞭解更多詳情。

這是VB的一項功能,它允許緊湊的代碼,比如這個:

Private Sub Form1_Load() Handles MyBase.Load 

如果不使用任何參數,爲什麼聲明它們?我個人認爲它是VB的好處,而不是問題。如果您嘗試在C#中執行相同的操作,則會出現如下編譯錯誤:

'Form1_Load'沒有與委託'System.EventHandler'相匹配的重載。

+0

該參數未在/ this/example中使用,但可用於其他地方。我的計時器代碼是其他人可能在其項目中使用的庫的一部分。如果這些用戶不知道TimerCallback的簽名,他們可能會忽略包含它,甚至不知道取消定時器的能力。 –

+1

@BradleyUffner:VB爲您提供了靈活性,只需要參數就可以用參數聲明它。您也可以使用這種方式處理具有不同簽名的多個事件,例如,用於記錄目的或調試。用戶在使用產品前應閱讀文檔。之後,他們可以選擇是否始終指定完整簽名或在需要時將其縮短。查看我的編輯瞭解更多信息。 – Neolisk

+0

感謝您提供此功能的附加信息和實際正式名稱。 –

相關問題