2012-11-23 8 views
5

Ich habe die folgende Klasse und den Delegaten im Code definiert (viele andere Zeilen wurden aus Platzgründen abgekürzt).Kein Fehler, wenn die Delegiertensignatur nicht übereinstimmt

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 

Wenn ich eine neue Instanz der Timer mit dem folgenden Code erstellen, ich habe nicht einen Compiler-Fehler, obwohl die Signatur der anonymen Funktion nicht die Unterschrift des Delegierten überein (es fehlt das " als boolescher "param" abgebrochen.

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

erwarte ich einen Compiler-Fehler zu erhalten, wenn der Timer auf diese Weise instanziiert wird, kann mir jemand erklären, warum es ohne Fehler kompiliert? Gibt es irgendwelche Optionen, die ich einstellen kann, damit es einen Kompilierungsfehler erzeugt? Ich habe Option explizit aktiviert, Option strict on und Option abl in den Projekteigenschaften. So wie es ist, ist es viel zu einfach, das abgebrochene Argument zu vergessen.

Antwort

4

Ja. Das ist in Ordnung - der Compiler kann eine anonyme Methode erstellen, die die Signatur benötigt, die benötigt wird, und einfach nicht die Parameter verwenden, die es gegeben wird. Also die Compiler-generierte Methode wird haben den Parameter - es wird es einfach nicht verwenden. Sie können das gleiche in C# mit delegate { ... } tun.

+1

Ist es nicht wichtig, das Argument für TimerCallback stark einzugeben, um sicherzustellen, dass die Methodensignatur übereinstimmt? Ich könnte dieses Verhalten möglicherweise sehen, wenn Option Infer auf On gesetzt wäre. Aber wenn ich Option Iner Off einstelle, würde ich erwarten, dass der Compiler nichts ableitet und die Signatur durchsetzt. Gibt es Lösungen für den zweiten Teil meiner Frage, ob der Compiler in dieser Situation einen Fehler oder zumindest eine Warnung generieren soll? –

3

Dieses Phänomen wird Relaxed Delegate Conversion genannt und hat ein etwas anderes Verhalten, wenn Option Strict on und off ist. Bitte folgen Sie dem Link für weitere Details.

Es ist ein Merkmal von VB ist, die für kompakte Code ermöglicht, wie dies:

Private Sub Form1_Load() Handles MyBase.Load 

Wenn Sie nicht eines der Argumente verwenden, warum erklären sie alle? Ich persönlich sehe es als einen Vorteil von VB und nicht als ein Problem. Wenn Sie das gleiche in C# zu tun versuchen, erhalten Sie einen Compiler-Fehler wie folgt aus:

Keine Überlastung für ‚Form1_Load‘ Streichhölzer Delegierten System.EventHandler '.

+0

Das Argument wird nicht in/this/verwendet, aber es kann an anderen Stellen verwendet werden. Mein Timer-Code ist Teil einer Bibliothek, die andere Personen in ihren Projekten verwenden können. Wenn diese Benutzer die Signatur für den TimerCallback nicht kennen, können sie es unterlassen, sie einzuschließen, oder sogar über die Möglichkeit verfügen, Timer zu stornieren. –

+1

@BradleyUffner: VB gibt Ihnen Flexibilität, es mit Parameter nur dort zu deklarieren, wo es den Parameter benötigt. Sie können auf diese Weise auch mehrere Ereignisse mit unterschiedlichen Signaturen unter einem Sub behandeln, z. B. für Protokollierungszwecke oder zum Debuggen. Benutzer sollten die Dokumentation lesen, bevor Sie Ihr Produkt verwenden. Danach haben sie die Wahl, ob sie die vollständige Signatur immer angeben oder bei Bedarf kürzen möchten. Siehe meine Bearbeitung für weitere Informationen. – Neolisk

+0

Vielen Dank für die zusätzlichen Informationen und den tatsächlichen formalen Namen dieses Features. –

Verwandte Themen