none
Struktur durchgehen RRS feed

  • Frage

  • Hallo,

    kann man die Elemente einer Struktur "durchgehen"??

    So etwa

    public struct BspStruktur { public string strElement1; public string strElement2; public string strElement3;}
    ...

       BspStruktur bspStruktur = new BspStruktur();
       foreach (string zBezeichnung in bspStruktur)
       {
          MessageBox.Show("Struktur-Element: " + zBezeichnung);
       }

    Dienstag, 14. Dezember 2010 15:49

Antworten

Alle Antworten

  • Hallo p

    nicht mit C# alleine, aber zB Reflection, Pseudo-Code grob:

    using System.Reflection;
    // ...
    foreach (FieldInfo field in typeof(BspStruktur).GetFields())
      MessageBox.Show("Struktur-Element: " + field.Name + "=" + field.GetValue(bspStruktur));


    MSDN
    http://msdn.microsoft.com/de-de/library/ch9714z3.aspx
    http://msdn.microsoft.com/de-de/library/system.reflection.fieldinfo.getvalue.aspx

    Dienstag, 14. Dezember 2010 15:59
  • Nur per Reflection.
    Dienstag, 14. Dezember 2010 16:00
  • Hallo Thomas!

    wenn man den Typ von der Struktur (nicht vom Member) ermittelt, dann klappt es perfekt! 

    foreach (FieldInfo field in typeof(BspStruktur).GetFields())

    Vielen Dank!!!

    Fred.

     

    Dienstag, 14. Dezember 2010 16:29
  • wenn man den Typ von der Struktur (nicht vom Member) ermittelt, dann klappt es perfekt!
    foreach (FieldInfo field in typeof(BspStruktur).GetFields())
    Fred, auch eine Instanz würde gehen, dann wie:
      bspStruktur.GetType()
    Dienstag, 14. Dezember 2010 16:32
  • Hallo perlfred,

    Hier noch eine LINQ-Iteration als Inspirationsquelle:

    using System;
    using System.Linq;
    
    namespace ConsoleApplication1
    {
      class Program
      {
        static void Main(string[] args)
        {
          var query = from m in typeof(Person).GetFields() // auch GetMembers moegl. mit entspr. BindingFlags
                select m;
    
          foreach(var m in query)
            Console.WriteLine(m.Name);
    
          Console.ReadKey(true);
        }
      }
    
      struct Person
      {
        public string FirstName;
        public string LastName;
      }
    }
    
    

    Gruß
    Marcel

    Dienstag, 14. Dezember 2010 18:31
    Moderator
  • Hallo,

    und LINQ mit Ausgabe der Werte:

      public struct BspStruktur 
      { 
        public string Element1; 
        public string Element2; 
        public string Element3;
    
        public static void DisplayFieldValues()
        {
          var beispiel = new BspStruktur() { Element1 = "abc", Element2 = "def", Element3 = null };
    
          var values = from field in beispiel.GetType().GetFields()
                 // Oder auch KeyValuePair<K, V>
                 select new Tuple<string, object>(field.Name, field.GetValue(beispiel));
    
          foreach (var value in values)
            Console.WriteLine("{0} = {1}", value.Item1, value.Item2);
        }
    
    

    um das Thema abzurunden ;-)

    Gruß Elmar

    Dienstag, 14. Dezember 2010 18:47
    Beantworter
  • Hallo Elmar,

          > um das Thema abzurunden ;-)

    ein Thema kann man ja im ~Prinzip nie abrunden, weil es immer noch andere Möglichkeiten gibt ;-)
    Gut, Dein Beispiel benutzt ja das GetFields, was Thomas richtigerweise vorgeschlagen hatte. Aber Reflection (hier GetFields) ist ja oft vermeidbar, und sollte vermieden werden (wenns es etwas anders gibt), u.a., weil es imperformant ist. Gut wenn ihr einen Cache eingebaut hättet (insgesamt wird es dann ggf. nur einmal evaluiert), wäre es ggf. noch performanter, aber immer noch nicht wie in folgendem Beispiel. Man kann also zum Beispiel auch (ganz simpel) folgendes machen, mit dem Aufruf:

     foreach (var feld in BspStruktur.Felder) // hier sehr performant
     MessageBox.Show(feld);
    

    // ...................... 

     public struct BspStruktur
     {
     public string Element1;
     public string Element2;
     public string Element3;
    
     // diese Ziele ggf. über PreBuild automatisch erstellen lassen 
     static public string[] Felder = new string[] { "Element1", "Element2", "Element3" };
     }

    Man kann da auch viel weiter gehen (oder sogar den struct partial machen) und letztlich über T4 Vorlagen (oder T4 MsBuild Integration - als PreBuild-Step) noch verhindern, dass beim Zufügen eines Element4's die "Felder" Liste auch angepasst wird, es gibt sehr viele Möglichkeiten. So wird die Performanz auf Kompilieren verschoben und nicht während der Ausführung langsamer.

    Auch wäre das eine ideale Aufgabe für PostSharp:

    [PostSharp – Documentation]
    http://www.sharpcrafters.com/postsharp/documentation


    ciao Frank

     

    Dienstag, 14. Dezember 2010 21:01
  • Hallo Frank,

    Die Markierung als Antwort war ein Ausrutscher, sorry (wiewohl Du in dem einen oder anderen Punkte Recht hast).

    > Aber Reflection (hier GetFields) ist ja oft vermeidbar, und sollte vermieden werden (wenns es etwas anders gibt), u.a., weil es imperformant ist.

    Reflection wurde - wie Du sicherlich weißt - auf dem Hintergrund von late-binding Szenarios entworfen. Von daher steckt sehr viel Kraft dahinter, die ihrerseits natürlich Performanz konsumiert. Und vieles kann auch hier über Caching wieder gut gemacht werden. Es gibt aber auch andere Wege an die benötigte Metadaten-Information zu kommen: z.B. Mono.Cecil (eine ausgezeichnete Bibliothek, wird z.B. intern von NDepend verwendet). Und wer ganz low-level arbeiten möchte, der kann sich natürlich das Common Compiler Infrastructure von Microsoft Research auf CodePlex ansehen. Ein Wort der Warnung jedoch: Microsoft.CCI ist nichts für Leute mit schwachen Nerven.

    Gruß
    Marcel

    Mittwoch, 15. Dezember 2010 08:29
    Moderator
  • Hallo Marcel,

    ja, es gibt immer noch andere Möglichkeiten etwas umzusetzen, meine präferierten Tools sind momentan in diesem Bereich eher die in meinem ersten Posting angegebenen - trotzdem ist da kein Anspruch auf Vollständigkeit vorhanden, es gibt viele weitere gute, die noch nicht genannt wurden.


    ciao Frank
    Mittwoch, 15. Dezember 2010 09:58