Allgemeine Frage zu Events

  • VB.NET

Es gibt 6 Antworten in diesem Thema. Der letzte Beitrag () ist von ~blaze~.

    Allgemeine Frage zu Events

    Hi,

    bei den meisten Klassen aus dem Framework mit Events haben die Events die beiden Parameter sender As Object und e As EventArgs (oder eine Klasse, die von EventArgs erbt), z. B. bei einem Button:

    VB.NET-Quellcode

    1. Public Event Click(sender As Object, e As EventArgs)


    Meine Frage ist, wieso man den sender immer also Object übergibt. Wäre es nicht sinnvoller, die Klasse zu nehmen, die das Event enthält? Damit würde man sich die umständliche Typenumwandlung sparen. Außerdem werden Parameter immer über die Klasse EventArgs übergeben. Hat das eine besondere Wichtigkeit?

    In meinen eigenen Klassen verwende ich meistens nicht diese Form, sondern z. B.:

    VB.NET-Quellcode

    1. Public Event DownloadProcessChanged(sender As YouTubeVideo, ProgressPercentage As Integer, Speed As Double, BytesDownloaded As Long, TotalDownloadSize As Long)


    Das hat für mich den Vorteil, dass ich mir eine Typenumwandlung sparen kann und dass ich es mir sparen kann, extra eine neue EventArgs-Klasse zu schreiben. Ist das schlechter, als das Schema des Frameworks zu verwenden?
    Das Click-Event - nur als ein Beispiel - kann auf viele Objekte, genauer gesagt Controls angewendet werden. Da auch mehrere Click-Events an eine Sub gekoppelt werden können, sollten die Signaturen schon übereinstimmen.
    (Sender as Button, und dann Sender as label... wäre nicht möglich, an EINE gemeinsame Prozedur zu koppeln.) Deshalb die übergeordnete Klasse "Object".

    In deinem Fall wäre eher eine Klasse angebracht, die diese Parameter zusammenfasst. Es könnte ja auch mal notwendig werden, einer anderen Prozedur mitzuteilen, um welche Datei es sich handelt, wieviel schon runtergeladen wurde usw...
    Hier müsstest du in deinem Fall dann sämtliche Parameter einzeln weitergeben, anstatt eines einzigen Objekts, welches alle notwendigen Infos enthält.

    Bleib beim Schema vom Framework. Das hat schon seinen Sinn. Manchmal ist der nicht leicht zu erkennen, aber er ist da.
    Hi
    außerdem verwendet man meistens den EventHandler-Delegaten bzw. den EventHandler(Of TEventArgs As EventArgs)- Delegaten. Object kann einfach alles umfassen, damit kann man auch Control.Click und MyClass.StateChanged in einem Handler zusammenfassen, ohne dass ein weiterer Methodenaufruf notwendig wäre. Das erkennt man übrigens afaik nur durch Option Strict On.

    Gruß
    ~blaze~
    Hier findest du mehr zum Standard von Events im .NET-Framework: msdn.microsoft.com/en-us/library/w369ty8x.aspx

    Der Grund ist, dass eine Methode verschiedenste Events von verschiedenen Typen abonnieren kann.
    Wenn du beispielsweise so was hast:

    VB.NET-Quellcode

    1. Module Program
    2. Sub Main()
    3. Dim _A = New A()
    4. AddHandler _A.AEvent, AddressOf Handler
    5. Dim _B = New B()
    6. AddHandler _B.BEvent, AddressOf Handler
    7. ' weiterer Code
    8. End Sub
    9. Sub Handler(ByVal sender As Object, ByVal e As EventArgs)
    10. If TypeOf sender Is A Then
    11. Dim Args As AEventArgs = DirectCast(e, AEventArgs)
    12. Console.WriteLine(Args.AProperty)
    13. Else
    14. Dim Args As BEventArgs = DirectCast(e, BEventArgs)
    15. Console.WriteLine(Args.BProperty)
    16. End If
    17. End Sub
    18. End Module
    19. Class A
    20. Public Event AEvent As EventHandler(Of AEventArgs)
    21. End Class
    22. Class B
    23. Public Event BEvent As EventHandler(Of BEventArgs)
    24. End Class
    25. Class AEventArgs
    26. Inherits EventArgs
    27. Public Property AProperty As String
    28. End Class
    29. Class BEventArgs
    30. Inherits EventArgs
    31. Public Property BProperty As String
    32. End Class
    Wie du siehst, sind die Events AEvent und BEvent mit unterschiedlichen Signaturen von derselben Methode abonniert (Program.Handler). Das heißt, es können beide Events darüber verarbeitet werden. Während mein Beispiel nicht viel Sinn macht, siehst du sicherlich, dass das praktisch sein kann. Deshalb würde ich immer die Signatur "Name(sender As Object, e As EventArgs)" nehmen.
    Danke für die Antworten. Ich denke ich weiß jetzt, wieso das Framework dieses Schema verwendet.

    VB.NET-Quellcode

    1. Das erkennt man übrigens afaik nur durch Option Strict On.

    Ich verwende immer Option Strict :).

    @haiyyu: Normalerweise verwende ich getrennte Funktionen (die dann logischerweise auch unterschiedliche Signaturen haben können), weil es meiner Meinung nach übersichtlicher ist als eine große Funktion für alle Events.
    Das die Frage aufgeworfen wird, findich gut. Ich bin nämlich auch nicht einverstanden, mit dieser Framework-Konvention.

    zb Click - Event:

    VB.NET-Quellcode

    1. blabla_Click(sender As Control, e As EventArgs)
    wäre doch kein Problem, weil sowohl Button als auch Label von Control erben

    Auch frage ich mich, wasses soll, dass jedes Event ein EventArgs transportier, auch wenns garkein Inhalt hat.

    Aber weil diese Konvention so durchgängig befolgt wird, isses vmtl nicht immer angeraten, da auszuscheren.

    VB.NET-Quellcode

    1. Public Event Click As EventHandler
    2. Protected Overridable Sub OnClick(ByVal e As EventArgs)
    3. RaiseEvent Click, e
    4. End Sub


    VB.NET-Quellcode

    1. Public Class CustomClickEventArgs
    2. Inherits EventArgs
    3. Private intComputedValue As Integer
    4. Public ReadOnly Property ComputedValue As Integer
    5. Get
    6. Return intComputedValue
    7. End Get
    8. End Property
    9. Public Sub New(computedValue As Integer)
    10. intComputedValue = computedValue
    11. End Sub
    12. End Class

    VB.NET-Quellcode

    1. OnClick(New CustomClickEventArgs(42))

    Auf gut deutsch: Von Control erbende Klassen können eigene EventArgs übergeben, die beim ausgelösten Ereignis übergeben werden. Control bietet zu (beinahe?) jedem Ereignis eine Methode, die das Ereignis mit entsprechenden EventArgs auslöst, an. Man kann zusätzlich zu z.B. Click noch weitere Informationen übergeben. Solche zusätzlichen Informationen könnten z.B. die Click-Quelle sein, also Tastatur, Maus, Code oder Unbekannt. Besonders sinnvoll ist das auch bei eigenen von EventArgs abgeleiteten Klassen, die überschreibbare Methoden bereitstellen.

    Gruß
    ~blaze~