delegate - prinzipielle Frage zum Verständnis
-
Hallo Forum,
ich bin gerade dabei einige Programme von mir zu erweitern. Dabei bin ich auf ein Problem gestossen, welches sich mit C# in einer einzigen Zeile lösen lässt. Leider programmier ich in C++ (VS 2008) und will nicht alles noch mal schreiben.
Es geht darum, den Inhalt einer DataColumn in ein String-Array zu kopieren. Im Moment rotiere ich die ganze Tabelle um 90° und lese dann die DataRows in Arrays aus. Relativ umständlich, wenn ich eine einzige Spalte auslesen und in ein Array kopieren möchte.
Jetzt habe ich für C# folgenden Code gefunden
String[] rowValuesForColumn = Array.ConvertAll<DataRow, String>( dataTable.Select(), delegate(DataRow row) { return (String) row[columnName]; } );
Inzwischen hab ich verstanden, was hier passiert. Die Array.ConvertAll-Funktion ist klar. Auch das "dataTable.Select()", welches ein Array aller Zeilen der Tabelle zurück gibt. Jetzt zu der delegate Zeile: Hier wird jetzt für jedes row-Objekt der Code in den {}-Klammern ausgeführt, wodurch mir der Inhalt der Zeile für die jeweilige Spalte als String zurückgegeben wird. Die ConvertAll-Funktion iteriert jetzt durch alle row-Objekte meiner Tabelle, was mir dann das gewünschte Ergebnis liefert.
Was hier noch recht verständlich ist, bekomm ich leider mit C++ überhaupt nicht hin. Irgendwie hab ich ein Verständnis-Problem bei der delegate-Thematik bei C++. Könnt ihr mir vielleicht obigen Code in C++ übersetzen und evtl. auch noch erklären wieso
Vielen, vielen Dank und guten Rutsch
physici
-
delegates sind grob gesagt verwaltete Funktionszeiger. Und dies ein anonyme Funktion (also eine - ohne sie sie explizit in der Klasse zu deklarieren).
delegate(DataRow row) { return (String) row[columnName]; }
Gibt einen delegate an, der auf die Funktionreturn (String) row[columnName];
zeigt. Und dies wird als Argument an die Methode Array.ConvertAll( übergeben. Etwa in der Art einer CallBack-Funktion nur direkt als Argument.Kann man soweit ich weiß nicht so einfach in C++/CLI machen ...
-
Anonymous delegates gibt es erst ab VS2010.
Für einen Work-Around siehe:
http://social.msdn.microsoft.com/Forums/en/csharplanguage/thread/cec57143-7f95-4953-9c70-945360b71266
-
Mit einer Hilfsklasse
public ref class ConvHelper { private: String^ colName; public: ConvHelper(String^ col) : colName(col) {} String^ conv(DataRow^ row) { return row[colName]->ToString(); } };
könnte man etwa
Array::ConvertAll( dataTable->Select(), gcnew Converter<DataRow^, String^>(gcnew ConvHelper(columnName), &ConvHelper::conv));
schreiben. (Ungetestet, aber so ähnlich sollte es gehen.)
-
Vielen Dank!! Auf euch ist wirklich Verlass
Ich hab es jetzt ähnlich nn hinbekommen. Aber mehr nach dem Prinzip Trial and Error.
Array::ConvertAll( dataTable->Select(), gcnew Converter<DataRow^, String^>(myClass::ConvertFunction));
wobei
static String^ ConvertFunction(DataRow^ row) { return row->default[_staticColumnIndex]->ToString(); }
außerhalb meiner Funktion, die ConvertAll aufruft, deklariert wird. "_staticColumnIndex" ist eine Variable die ich vor dem Aufruf der ConvertAll-Funktion noch setze und schon klappt es. Sicherlich nicht besonders elegant, aber bei mir als Laien-Coder zählt das Ergebnis etwas mehr. Dank euch, hab ich jetzt auch Verstanden, warum es so funktioniert...
Kommt gut ins neue Jahr.