ERLEDIGT
NEIN
NEIN
ANTWORTEN
21
21
ZUGRIFFE
1547
1547
EMPFEHLEN
-
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:
... was eben in bla nur objekte geliefert hätte, deren Eigenschaft blubb den Wert "bli" enthält.Code :1
foreach(bla in xxx where blubb=="bli")
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
-
20.12.04 16:14 #2
- 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
ist ja nicht soviel Aufwand.Code :1 2
if (!bla.Blubb.Equals("blu")) continue;
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,
AlexWith 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
-
20.12.04 16:25 #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!
-
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
-
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
-
24.12.04 00:42 #6
- 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.netWith 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
-
@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
-
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.
-
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
-
Dann hätte dies aber nicht das foreach betreffen müssen, sondern ein neues Konstrukt einführen.
-
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.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.Code :1
For Each entry As String In myArrayList Where CStr(entry).Length > 2
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
-
05.01.05 21:56 #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üsseErst 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!
-
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
-
06.01.05 00:50 #14
- Registriert seit
- Mar 2001
- Ort
- München
- Beiträge
- 4.785
Ist .net 2.0 nicht noch beta?
Zitat von Sunray
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!
-
Kommt aber heuer raus und überrundet damit Java
Ähnliche Themen
-
Eine Art foreach für objekte gesucht
Von andrutz im Forum Javascript & AjaxAntworten: 2Letzter Beitrag: 07.04.09, 21:27 -
In der ForEach-Schleife eine Ausgabe
Von Papenburger im Forum PHPAntworten: 2Letzter Beitrag: 30.05.07, 16:30 -
foreach()
Von Arndtinho im Forum PHPAntworten: 5Letzter Beitrag: 27.07.04, 15:02 -
Foreach
Von Maximus im Forum PHPAntworten: 3Letzter Beitrag: 29.05.02, 10:40





Zitieren

Login





