DebuggerDisplay

Es ist ja eine schöne Sache, wie einfach man die Anzeige von Objekten im Debugger verbessern kann. Man muss nur wissen, dass der Debugger für diese Anzeige die ToString-Methoden der jeweiligen Objekte aufruft, und dann eben diese Methoden entsprechend programmieren.

Umso überraschter war ich deshalb, als dieses Vorgehen einfach nicht klappen wollte, als ich eine Ableitung der Klasse TextBox programmierte und mir im Debugger nicht den momentanen textuellen Inhalt des Controls wünschte, sondern seinen Namen, um besser verfolgen zu können, was wann mit welchem Control aus einer ganzen Gruppe von Controls passierte: Ein Überschreiben von ToString hatte keinerlei Effekt im Debugger.

Ich habe nicht herausgefunden, warum genau das so ist, aber jedenfalls kann man mit Hilfe des DebuggerDisplay-Attributs erreichen, dass auch bei einer TextBox der Debugger die Methode ToString verwendet:

[DebuggerDisplay("{ToString()}")]
public class MyTextBox : TextBox {
  ...
    public override string ToString() {
      return Name;
    }
}
Veröffentlicht in Keine Kategorie. Schlagwörter: , . Leave a Comment »

Flexible Delegates

In den meisten C#-Programmen dürften Delegates nur vorkommen, um sie einem Event anzuhängen. Es könnte deshalb der Eindruck entstehen, Delegates seien unwichtig und ausser im Zusammenhang mit Events für sich alleine nicht zu gebrauchen. Einige Tests, die ich kürzlich durchgeführt habe, zeigen aber ein anderes Bild.

Anlass war folgende Frage: Hängen an einem Event mehrere Handler, hat man so gut wie keine Kontrolle darüber, in welcher Reihenfolge diese aufgerufen werden. Was tut man, wenn das ein Problem darstellt, d.h. wenn man die Kontrolle über die Aufruf-Reihenfolge benötigt?

Eine mögliche Antwort ist die folgende: Man lässt Events links liegen und arbeitet direkt mit Delegates.

Delegates haben gegenüber anderen .NET-Objekten eine „magische“ Eigenschaft: Man kann sie aufrufen, d.h. man kann mit ihrer Hilfe Methoden bestimmter Objekte ausführen. Sie sind aber trotzdem ganz normale Objekte, und man kann mit ihnen alles machen, was man mit anderen Objekten auch machen kann, inklusive Verwendung für Template-basierte Klassen wie List<T>. Wie untenstehender Demo-Code zeigt, ist es deshalb kein Problem, eine Art Event in Form einer Liste selbst mit sehr wenig Aufwand nachzubauen, einer Liste, wo man dann eben selbst beliebig bestimmen kann, in welcher Reihenfolge welcher Delegate aufgerufen werden soll.

Delegates sind übrigens Objekte der Klasse Delegate. Objekte dieser Klasse haben eine öffentliche Eigenschaft Target – das Objekt, dessen Methode sie aufrufen. Wenn man will, kann man also sogar noch weiter gehen als einfach die Reihenfolge des Aufrufs kontrollieren und z.B. einen Aufruf nur durchführen, wenn sich das entsprechende Objekt in einem bestimmten Zustand befindet.

using System.Collections.Generic;

namespace DelegateDemo {
  delegate void Method(int firstArg, int secondArg);

  class TestClass {
    public void TestMethod(int x, int y) {
    }
  }

  class Program {
    static void Main(string[] args) {
      TestClass a = new TestClass();
      TestClass b = new TestClass();
      TestClass c = new TestClass();

      List<Method> methods=new List<Method>();
      methods.Add(a.TestMethod);
      methods.Add(b.TestMethod);
      methods.Add(c.TestMethod);

      methods[0](0, 1);
      methods[1](2, 3);
      methods[2](4, 5);
    }
  }
}
Veröffentlicht in Keine Kategorie. Schlagwörter: , , . Leave a Comment »

Forcierte Updates für den Forms-Designer

Es kann vorkommen, dass während der Arbeit im Windows-Forms-Designer an einem Control so etwas ändert, dass es der Designer nicht mitbekommt. Dies ist speziell dann der Fall, wenn man wie in einem früheren Blog-Eintrag hier beschrieben quasi „hinterrücks“ Eigenschaften eines Controls ändert, ohne dass der Designer direkt beteiligt ist, nämlich via Code beim Control selbst.

Konkret hatte ich das Problem, dass ich den Text eines Label-Controls änderte, aber die Markierung rund um das Control nicht an die neue visuelle Länge angepasst wurde.

Es hat sich zum Glück herausgestellt, dass es relativ einfach ist, an die Komponente des Designers heranzukommen, welche für Reaktionen auf solche Änderungen zuständig ist. Konkret in Code:

 protected override void OnMouseClick(MouseEventArgs e) {
   base.OnMouseClick(e);
   if (DesignMode) {
     // gewünschte DesignTime-Verarbeitung 
     IComponentChangeService changeService = (IComponentChangeService)Site.GetService(typeof(IComponentChangeService));
     if (changeService != null) {
       changeService.OnComponentChanged(this, null, "", "");
     }
   }
 }
Veröffentlicht in Keine Kategorie. Schlagwörter: , , . Leave a Comment »

Bestehende Klassen erweitern

Die meisten Programmierer haben sich wohl schon irgendeinmal gewünscht, im einem System eine bestehende Klasse auf einfache Weise um ein paar Methoden erweitern zu können, die ganz einfach fehlen zum vollkommenen Glück.

Die C#-Klasse string im .NET-Framework ist wohl so ein Kandidat: Im Standard-Angebot ist da nur 1 Methode Substring, aber viele praktische Methoden wie z.B. Right, die es in VB.NET gibt, fehlen.

Seit C# 3.0 gibt es mit Hilfe sogenannter Extension Methods tatsächlich die Möglichkeit, selbst eine Standard-Klasse wie string auf einfache und elegante Weise zu erweitern. Das sieht dann bei der erwähnten Right-Methode konkret so aus:

public static class Strings {
public static string Right(this string str, int len) {
if (str.Length <= len) { return str; } else { return str.Substring(str.Length - len); } } } [/sourcecode] Der wichtigste Punkt bei dieser Sache ist wohl der, von irgendwoher zu wissen, dass das geht, z.B. eben aus diesem Blog-Eintrag hier. Der Rest ist einfach und lässt sich in der Microsoft-Dokumentation nachlesen, z.B. hier.

Man kann sich natürlich fragen, ob es eine gute Idee ist, Standard-Klassen auf diese Weise zu erweitern, wie z.B. hier in einem Forum-Thread leidenschaftlich diskutiert wurde. Ich denke, es ist wie fast bei allen Dingen: Richtig angewendet, sind extension methods eine nützliche Sache, aber ja, man kann sie missbrauchen, aber nein, die Versuchung zum Missbrauch ist nicht so gross, dass man die Sache per se pauschal zum Teufel schicken müsste.

Veröffentlicht in Keine Kategorie. Schlagwörter: , . 1 Comment »