Der Code erzeugt einen überflüssigen Button an einer Variablen.
Und weißt dann der Variablen ein Object zu das auf den Typ Button gecastet wird. Wenn das Object (sender) kein Button war wird der Code an dieser Stelle eine Exception werfen.
Simpelst Beispiel für explizit vs. implizit.
C#-Quelltext
1: 2: 3: 4: 5:
| int i = 1; long l;
l = i; l = (long)i; |
Implizit der Code macht die Umwandlung einfach weil klar ist wie die Umwandlung (hier von int nach long) stattzufinden hat.
Explizit man sagt dem welche Umwandlung zu vollzuziehen ist mit einem Hinweis via cast, der geklammert Typ. Die explizite Erwähnung der long Umwandlung im obigen Fall ist wie hoffentlich auffällt unnötig ohne gehts ja auch. Wenn wir aber das Ganze umdrehen
C#-Quelltext
1: 2: 3: 4: 5:
| int i; long l = 1;
i = l; i = (int)l; |
wird der Compiler meckern. Der implizite Fall ist nicht erlaubt da beim Umwandeln ein Datenverlust stattfinden könnte. Ein int passt immer in einen long aber nicht zwingend umgekehrt.
Da muß man das explizit machen was andeuten soll das der Programmierer weiß was er tut und den potentiellen Datenverlust in Kauf nimmt.
Bezogen auf deinen Beispiel. sender ist ein Object und button1 ein Button. Ich könnte also problemlos
sender = button1; ausführen. Da alles ein object ist und Button natürlich auch. Umgekehrt
button1 = sender; aber nicht zwingend. sender ist nur als object definiert kann also alles mögliche sein. Ein Button wäre nur eine Möglichkeit. Man ist also gezwungen da den cast auf Button explizit hinzuschreiben um den Compiler zu sagen "hey ich weiß was ich mach, da steht zwar object in der Methodensignatur aber ich weiß da wird immer nur ein Button rüber kommen". Du mußt halt im Zweifel damit leben das wenn deine Annahme nicht stimmt das da eine Exception erfolgt. Wenn es zum Beispiel ein Label war und gar kein Button wird es eine Exception geben weil es zwischen Label und Button keine Umwandlungs gibt (Klassen können Umwandlungsmethoden von und zu anderen Klassen haben und zwischen Button und Label gibt es keine).