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 Funktion return (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.


Anmelden zum Antworten