tutorials.de Buch-Aktion 05/2012
Seite 1 von 2 12 LetzteLetzte
ERLEDIGT
NEIN
ANTWORTEN
21
ZUGRIFFE
1547
EMPFEHLEN
  • An Twitter übertragen
  • An Facebook übertragen
AUF DIESES THEMA
ANTWORTEN
  1. #1
    Registriert seit
    Apr 2003
    Ort
    Scheeßel
    Beiträge
    359
    Hallo Leute,

    ich stolpere immer wieder darüber, daß man mit foreach keine selektive Auswahl in einer Collection treffen kann. Für mich ist foreach mangelhaft umgesetzt. Es wäre doch die einmalige Gelegenheit gewesen, den C# Entwicklern ein Konstrukt zu geben, welches über eine Collection eine Art SQL-, also Datenbank-Funktionalität abbildet. Worauf ich hinaus will, das ist folgendes:

    ein normales foreach-Konsturkt sieht ja so aus:
    Code :
    1
    2
    3
    4
    
    foreach(Object bla in xxx)
    {
    ...
    }

    in SQL sähe das ja so aus:
    Code :
    1
    
    bla = sqlquery("select * from xxx");

    jetzt wäre es schön gewesen, wenn man in foreach noch hätte selektieren können, welche Objekte aus xxx man benötigt, also wie in SQL:
    Code :
    1
    
    select * from xxx WHERE blubb='bli';

    was mit foreach so ähnlich hätte realisiert werden können:
    Code :
    1
    
    foreach(bla in xxx where blubb=="bli")
    ... was eben in bla nur objekte geliefert hätte, deren Eigenschaft blubb den Wert "bli" enthält.

    In der tatsächlichen Syntax der foreach muss man in jedem Schleifendurchlauf erstmal abfragen, ob blubb wirklich den Wert "bli" enthält:

    Code :
    1
    2
    3
    4
    
    foreach(bla in xxx)
    {
      if(bla.blubb != "bli") continue;
    }

    Ich find's schade, daß es sowas nicht gibt... hätte mir schon 'ne Menge zusätzlicher Arbeit erspart.

    Das ganze hätte man bestimmt auch noch weiter spinnen können, in Richtung SQL-Funktionalität. LIMITs und so... logische Verknüpfungen (WHERE blubb='bli' AND bloek='muh' oder so)...

    Das ist meine Meinung! Was meint ihr dazu?
     
    aka SeveQ

  2. #2
    Avatar von Alexander Schuc
    Alexander Schuc Alexander Schuc ist offline admin | crazy-weasel
    tutorials.de Administrator
    Registriert seit
    Aug 2001
    Ort
    Österreich, Stmk, Graz
    Beiträge
    2.783
    Hi.

    foreach mit einer Select-Anweisung aus SQL zu vergleichen passt, finde ich zumindest, nicht so ganz.
    Mit dem SQL-Select holt man sich Datensätze gewisse Datensätze die gewisse Kriterien erfüllen.
    Das foreach iteriert einfach durch eine Collection durch und du kannst dann mit jedem Objekt darin etwas machen. Eine Abfrage kannst dann im Anweisungsblock noch immer machen und ein
    Code :
    1
    2
    
    if (!bla.Blubb.Equals("blu"))
      continue;
    ist ja nicht soviel Aufwand.

    Machbar wäre aber ein von dir gewünschtes Konstrukt sicher. Wenn du es oft brauchst kannst es dir im Prinzip auch selbst schreiben. Nur schauts dann halt ein bisserl anders aus.
    Es wird dann ein Funktionsaufruf sein dem du verschiedene Parameter übergibst, unter anderem auch einen Delegate zu einer Funktion die dann mit den gefundenen Objekten ausgeführt werden soll.

    So könnte das aussehen:

    Code :
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    
    /*
     *
     * A simple example how to extend the foreach-construct
     *
     * (c) 2004 Alexander Schuc
     * free for use and distribution
     *
     */
     
    using System;
    using System.Reflection;
     
    namespace furred.Testing
    {
      public class TestObject
      {
        public string Name;
        public int Number;
        
        public TestObject(string name, int number)
        {
          this.Name = name;
          this.Number = number;
        }
      }
     
      public delegate void mydelegate(TestObject obj);
      
      public class advancedForeachTesting
      {
        public static void Main(string[] args)
        {
          new  advancedForeachTesting();
        }
     
        private mydelegate executeStatement;
        
        public advancedForeachTesting()
        {
          TestObject[] to = new TestObject[20];
          for (int i = 0; i < 20; i++)
          {
            string name = i % 2 == 0 ? "Blaa" : "Blubb";
            to[i] = new TestObject(name, i);
          }
     
          object[] objs = new object[20];
          for (int i = 0; i < 20; i++)
          {
            int mod = i % 3;
            switch (mod)
            {
              case 0: objs[i] = (i+20); break;
              case 1: string name = i % 2 == 0 ? "Muh" : "Kuh";
                      objs[i] = new TestObject(name, i+20); break;
              case 2: objs[i] = "Blaa"; break;
            }
          }
     
          executeStatement  = new mydelegate(printInfos);
          Console.WriteLine("Testing with TestObject-Array:");
          aForEach("furred.Testing.TestObject", to, "Name", "Blaa", executeStatement);
     
          Console.WriteLine("Testing with object-Array:");
          aForEach("furred.Testing.TestObject", objs, "Name", "Kuh", executeStatement);
        }
     
        private void printInfos(TestObject obj)
        {
          Console.WriteLine("#{0:00} - {1}", obj.Number, obj.Name);
        }
     
        private void aForEach(string type_name, object[] collection, string prop, string equal, mydelegate fun)
        {     
          Type type = Type.GetType(type_name);
          
          foreach (object o in collection)
          {      
            if (o.GetType() == type)
            {
              string p = (string) type.InvokeMember(prop,BindingFlags.GetField, null, o, null);
              if (p == equal)
                fun((TestObject)o);
            }
          }
        }
      }
    }

    MfG,
    Alex
    Angehängte Dateien Angehängte Dateien
     
    With the first link the chain is forged. The first speech censored, the first thought forbidden, the first freedom denied, chains us all irrevocably.
    Aaron Satie

    Legends... are the spice of the universe, Mr. Data, because they have a way of sometimes coming true.
    Captain Jean-Luc Picard, Stardate ~41294.5

    Tutorials.de chattet. Hier gibts auch .net Support ^^
    Klickt auf chattet und nutzt den Webchat, oder verbindet euch zu irc.tutorials.de - Channel #Tutorials.de

    (moo)blog furred.net // SiteInfo für WP7 // Pastebin für WP7 // BlogEngine.net Extensions

  3. #3
    Registriert seit
    Mar 2001
    Ort
    München
    Beiträge
    4.785
    foreach iteriert durch eine Collection nicht mehr und nicht weniger.

    Was du haben willst ist demnach ein eigener Algorythmus Objecte anhand
    eines Filters zu "finden".

    Hier den Filter ein die Iteration einzubauen ist nicht wünscheswert. Denn
    letztendlich müsste er in alle Klassen die eine Collection darstellen und
    per foreach durchlaufen werden wollen unnötige Methoden bereitstellen.

    Wenn du Collections haben willst die du aufgrund bestimmter Keys
    bekommen willst dann ist es das richtige diese Collections in eine
    Hashtable mit dem gewünschten Key zu packen.
     
    Erst wenn der letzte Programmierer eingesperrt...
    ...und die letzte Idee patentiert ist, werdet ihr merken, dass Anwälte nicht programmieren können.
    -------------------
    chris: hey Tom hast du eigentlich ne Freundin
    jdar: ich bin tutorials.de Mod!

  4. #4
    XChris XChris ist offline Mitglied Brokat
    Registriert seit
    Sep 2003
    Ort
    Weimar
    Beiträge
    373
    Meine Meinung:

    Ne foreach ist zum DURCHLAUFEN von Container da. Den Selectiven Zugriff mit EINER Zugriffsmethode effizient erschlagen zu wollen ist unmöglich.

    Du musst selbst entscheiden, was Du für einen Conatiner willst und brauchst. Das was Du Dir wünschst, nehmlich den Zugriff auf ein Element via Eigenschaft gibt es, Schau Dir mal - wie Christian Fein schon sagte, den Namespace Collection mal an. Wenn Du mal selbst eine verkettet Liste oder gewichteten Baum programmiert hast, weisst Du was ich meine.

    Chris
     

  5. #5
    Avatar von Sunray
    Sunray Sunray ist offline Mitglied Gold
    Registriert seit
    Sep 2003
    Ort
    Schweiz
    Beiträge
    190
    Eine gute Idee wäre, selber eine Collection oder Dictionary (wegen den Primary Keys) Klasse zu schreiben, die über Reflection dann gewisse Ausdrücke auswerten kann.
    VB.NET:
    Code :
    1
    2
    3
    4
    
    For Each resObj as Object in IntelligentCollection.Limit( _ 
       "param1 < 1900 and param2 = 'weihnachten' limit 3 sort by param1 asc")
        '//Code
    Next

    Im .NET Framework 2.0 könnte man das ganze sogar mit Generics machen...
    Wirklich interessante Idee...
     
    Zu jedem Problem gibt es mindestens eine Lösung.
    Zu jeder Lösung gibt es mindestens eine bessere Lösung

  6. #6
    Avatar von Alexander Schuc
    Alexander Schuc Alexander Schuc ist offline admin | crazy-weasel
    tutorials.de Administrator
    Registriert seit
    Aug 2001
    Ort
    Österreich, Stmk, Graz
    Beiträge
    2.783
    Ich hab vor ein paar Tagen mal an meinem Vorschlag weitergearbeitet,
    wenns jemanden interessiert, hab eine Seite bei mir dafür eingerichtet.
    Selektives ForEach - furred.net
     
    With the first link the chain is forged. The first speech censored, the first thought forbidden, the first freedom denied, chains us all irrevocably.
    Aaron Satie

    Legends... are the spice of the universe, Mr. Data, because they have a way of sometimes coming true.
    Captain Jean-Luc Picard, Stardate ~41294.5

    Tutorials.de chattet. Hier gibts auch .net Support ^^
    Klickt auf chattet und nutzt den Webchat, oder verbindet euch zu irc.tutorials.de - Channel #Tutorials.de

    (moo)blog furred.net // SiteInfo für WP7 // Pastebin für WP7 // BlogEngine.net Extensions

  7. #7
    Registriert seit
    Apr 2003
    Ort
    Scheeßel
    Beiträge
    359
    @Schuc: Check deine Seite mal! Irgendwie scheint das ZIP-File defekt zu sein. Winzip sagt mir immer was von "Bad Offset". Und die Seite hinter [mehr] geht auch nicht.

    Das mit der Collection, die eine Limit-Funktion liefert, welche SQL versteht, ist schonmal gar keine schlechte Idee. Trotzdem hätte ich es schön gefunden, wenn foreach das von Haus aus angeboten hätte.
     
    aka SeveQ

  8. #8
    Avatar von Norbert Eder
    Norbert Eder Norbert Eder ist offline Mitglied Diamant
    Registriert seit
    Feb 2004
    Ort
    Österreich / Graz
    Beiträge
    5.137
    Blog-Einträge
    51
    Es macht keinen Sinn das foreach für etwas zu missbrauchen, wofür es nicht gedacht war. Warum auch? Damit sollen Collections durchiteriert werden und sonst nichts. Überprüfungen können innerhalb durchgeführt werden.

    Also warum hätte man foreach aufblasen sollen? Ich sehe hier wirklich keinen Grund dafür. Da macht es doch mehr Sinn, eine entsprechende Datenstruktur zu basteln oder was auch immer die das für mich übernimmt.
     

  9. #9
    Registriert seit
    Apr 2003
    Ort
    Scheeßel
    Beiträge
    359
    Darum geht es mir ja. Um die Ursache dessen: darum, daß foreach für etwas anderes hätte vorgesehen werden können. Ums Prinzip. Man hätte ihm optional noch die Möglichkeit der Einschränkung geben können und so 'ne Menge Programmieraufwand einsparen können. Das ist es, was ich mit meiner Meinung aussagen wollte.
     
    aka SeveQ

  10. #10
    Avatar von Norbert Eder
    Norbert Eder Norbert Eder ist offline Mitglied Diamant
    Registriert seit
    Feb 2004
    Ort
    Österreich / Graz
    Beiträge
    5.137
    Blog-Einträge
    51
    Dann hätte dies aber nicht das foreach betreffen müssen, sondern ein neues Konstrukt einführen.
     

  11. #11
    Avatar von Sunray
    Sunray Sunray ist offline Mitglied Gold
    Registriert seit
    Sep 2003
    Ort
    Schweiz
    Beiträge
    190
    For Each muss wirklich nicht zwangsläufig aufs "normale" Iterieren beschränkt sein.
    In VB.NET könnte man das selektive For-Each ruhig ungefähr so implementieren.
    Code :
    1
    
    For Each entry As String In myArrayList Where CStr(entry).Length > 2
    Für C# müsste man sich dann halt was ausdenken. Aber es ist auf jeden Fall sinnvoller diese Funktion an das bestehende Foreach anzuhängen, weil der grossteil der "Arbeit" ja immer noch das iterieren ist. Ansonsten hättest du 2 Konstrukte, die fast das selbe machen.

    Ja, Foreach ist fürs iterieren gedacht. Aber wieso sollte man da nicht mit einem einzigen, simplen Ausdruck die Menge der übergebenen Elemente reduzieren können.
    Ich denke, dass auf Seiten des Frameworks (Interfaces, Collection Klassen) nichts geändert werden müsste.
     
    Zu jedem Problem gibt es mindestens eine Lösung.
    Zu jeder Lösung gibt es mindestens eine bessere Lösung

  12. #12
    Registriert seit
    Mar 2001
    Ort
    München
    Beiträge
    4.785
    Hab da ein "Selectiven Iterator" eben in Java mit Hilfe von Generics geschrieben.

    Sprich ein Typsicherer selektiver Iterator.
    Hauptanwendung ist die übergabe eines Objectes das ISelector<T> implementiert.
    Dieser sagt ob jenes object selectiert wird oder nicht.

    Der Code (erst das Interface, dann der Iterator, danach die main Methode und Anwendung):

    Code :
    1
    2
    3
    4
    5
    
    package de.jorona.test;
     
    public interface ISelectort<T> {
        public boolean select(T object);
    }

    Implementationen dieses Interface entscheiden ob ein Object in der Iteration berücksichtigt wird oder nicht

    Code :
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    
    package de.jorona.test;
     
    import java.util.ArrayList;
    import java.util.Iterator;
     
    public class SelectIterator<T> implements Iterator {
        
        private ArrayList<T> items = new ArrayList<T>();
        private ArrayList<T> okitems = new ArrayList<T>();
        private ISelectort<T> selectable;
        private int index = 0;
        private Iterator<T> iter;
        
        public SelectIterator(ArrayList<T> items,ISelectort<T> selectable) {
            this.selectable = selectable;
            this.items = items;
            Iterator<T> iterator = items.iterator();
            while(iterator.hasNext()) {
                T item = iterator.next();
                if(selectable.select(item))
                    okitems.add(item);
            }
            iter = okitems.iterator();
        }
        
        public boolean hasNext() {  return iter.hasNext(); }
        
        public T next() { return iter.next();   }
        
        public void remove() {  iter.remove();  }           
    }

    Generische Iterator. Checked anhand übergebener ISelector<T> Implementierung ob
    das Object Typs T berücksichtigt wird oder nicht. Wenn ja packt der das ganze in ein neues Array.

    Die Anwendung, hier wird nur über Strings iteriert die mit "e" anfangen. Mann kann diese ganze Geschichte natürlich allein durch die übergabe einer anderen ISelector<T> Implementierung ändern
    Code :
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    
    /*
     * Created on 05.01.2005
      */
    package de.jorona.test;
     
    import java.util.ArrayList; 
    public class ForEachTest {
        
        public static void main(String[] args) {
            ArrayList<String> items = new ArrayList<String>();
            items.add("eins");
            items.add("zwei");
            items.add("esel");
            items.add("efeu");
            SelectIterator<String> selectIterator = new SelectIterator<String>(items,
                    new ISelectort<String>() {
                        public boolean select(String arg0) {                        
                            return arg0.startsWith("e");
                        }           
                    }
            );
            while(selectIterator.hasNext()) {
                System.out.println(selectIterator.next());
            }
        }
    }

    In C# würde ich ähnlich machen, ausser natürlich das noch keine Generics existieren, wird Zeit das dies umgesetzt wird.

    grüsse
     
    Erst wenn der letzte Programmierer eingesperrt...
    ...und die letzte Idee patentiert ist, werdet ihr merken, dass Anwälte nicht programmieren können.
    -------------------
    chris: hey Tom hast du eigentlich ne Freundin
    jdar: ich bin tutorials.de Mod!

  13. #13
    Avatar von Sunray
    Sunray Sunray ist offline Mitglied Gold
    Registriert seit
    Sep 2003
    Ort
    Schweiz
    Beiträge
    190
    Wurde bereits umgesetzt. In .NET 2.0.
    Visual C# Express 2005 Beta: Schau dir Punkt 14 an.

    Aber Vorsicht: Generics sind NICHT CLS compliant d.h. solltest du sie in Bibliotheken nur private oder friend benutzen.
     
    Zu jedem Problem gibt es mindestens eine Lösung.
    Zu jeder Lösung gibt es mindestens eine bessere Lösung

  14. #14
    Registriert seit
    Mar 2001
    Ort
    München
    Beiträge
    4.785
    Zitat Zitat von Sunray
    Wurde bereits umgesetzt. In .NET 2.0.
    Visual C# Express 2005 Beta: Schau dir Punkt 14 an.

    Aber Vorsicht: Generics sind NICHT CLS compliant d.h. solltest du sie in Bibliotheken nur private oder friend benutzen.
    Ist .net 2.0 nicht noch beta?
     
    Erst wenn der letzte Programmierer eingesperrt...
    ...und die letzte Idee patentiert ist, werdet ihr merken, dass Anwälte nicht programmieren können.
    -------------------
    chris: hey Tom hast du eigentlich ne Freundin
    jdar: ich bin tutorials.de Mod!

  15. #15
    Avatar von Norbert Eder
    Norbert Eder Norbert Eder ist offline Mitglied Diamant
    Registriert seit
    Feb 2004
    Ort
    Österreich / Graz
    Beiträge
    5.137
    Blog-Einträge
    51
    Kommt aber heuer raus und überrundet damit Java
     

Ähnliche Themen

  1. Eine Art foreach für objekte gesucht
    Von andrutz im Forum Javascript & Ajax
    Antworten: 2
    Letzter Beitrag: 07.04.09, 21:27
  2. In der ForEach-Schleife eine Ausgabe
    Von Papenburger im Forum PHP
    Antworten: 2
    Letzter Beitrag: 30.05.07, 16:30
  3. foreach()
    Von Arndtinho im Forum PHP
    Antworten: 5
    Letzter Beitrag: 27.07.04, 15:02
  4. Foreach
    Von Maximus im Forum PHP
    Antworten: 3
    Letzter Beitrag: 29.05.02, 10:40