myCSharp.de - DIE C# und .NET Community
Willkommen auf myCSharp.de! Anmelden | kostenlos registrieren
 
 | Suche | FAQ

» Hauptmenü
myCSharp.de
» Startseite
» Forum
» FAQ
» Artikel
» C#-Snippets
» Jobbörse
» Suche
   » Plugin für Firefox
   » Plugin für IE
   » Gadget für Windows
» Regeln
» Wie poste ich richtig?
» Datenschutzerklärung
» wbb-FAQ

Mitglieder
» Liste / Suche
» Stadt / Anleitung dazu
» Wer ist wo online?

Angebote
» ASP.NET Webspace
» Bücher
» Zeitschriften
   » dot.net magazin

Ressourcen
» guide to C#
» openbook: Visual C#
» openbook: OO
» MSDN Webcasts
» Search.Net

Team
» Kontakt
» Übersicht
» Wir über uns
» Impressum

» Unsere MiniCity
MiniCity
» myCSharp.de Diskussionsforum
Du befindest Dich hier: Community-Index » Diskussionsforum » Entwicklung » Basistechnologien und allgemeine .NET-Klassen » bei foreach auf referenz zugreifen
Letzter Beitrag | Erster ungelesener Beitrag Druckvorschau | Thema zu Favoriten hinzufügen

Antwort erstellen
Zum Ende der Seite springen  

bei foreach auf referenz zugreifen

 
Autor
Beitrag « Vorheriges Thema | Nächstes Thema »
Darrn
myCSharp.de-Mitglied

Dabei seit: 19.08.2006
Beiträge: 28


Darrn ist offline

bei foreach auf referenz zugreifen

Beitrag: beantworten | zitieren | editieren | melden/löschen       | Top

hi!

ich habe ein array von referenzen auf die klasse Objekt und möchte diese gerne mit einer foreach schleife auf andere referenzen umändern.

C#-Code:
Objekt[] nodes;

...Array füllen...

foreach ( Objekt node in nodes )
{
   node = new Objekt( this.getNext() );
}

der compiler sagt mir natürlich, dass ich auf eine foreach iteration variable nichts zuweisen darf. deshalb wollte ich fragen, wie man der foreach schleife angeben kann, dass sich die variable auf die referenz bezieht? in PHP geht das zB mit einem & vor dem variablennamen.

php-Code:
1:
2:
3:
4:
<?php foreach ( $array as &$value )
{
...
} php?>
21.08.2006 17:47 Beiträge des Benutzers | zu Buddylist hinzufügen
norman_timo norman_timo ist männlich
myCSharp.de-Poweruser/ Experte

images/avatars/avatar-1775.jpeg


Dabei seit: 13.07.2004
Beiträge: 4.506
Entwicklungsumgebung: .NET 2.0/3.5 und VS2005/VS2008
Herkunft: Wald-Michelbach (Odw)


norman_timo ist offline

Beitrag: beantworten | zitieren | editieren | melden/löschen       | Top

Hallo Darrn,

ich kann Dir nicht folgen. Was möchtest Du tun?

Wenn Du ein dynamisches Array möchtest (also erst zur Laufzeit festlegen, wie groß das Array werden soll), dann verwende statt Array eine ArrayList.

Wenn Du ein fixes Array haben möchtest, dann kannst Du es folgendermaßen anlegen:

C#-Code:
Objekt[] nodes = new Objekt[Anzahl];

Dann kannst Du allerdings nur Objekte vom Typ Objekt in das Array stecken. Falls Du verschiedene Typen in das Array geben möchtest, dann verwende lieber object, wobei ich davon abraten würde.

Foreach ist nämlich dafür da, durch eine bereits gefüllte Liste zu gehen, und die vorhandenen Instanzen abzugreifen. Eine erstmalige Befüllung sollte über den Index des Arrays erfolgen, und damit dann auch mittels einer "normalen" For-Schleife.

Gruß
Norman-Timo
21.08.2006 17:54 E-Mail | Beiträge des Benutzers | zu Buddylist hinzufügen
Darrn
myCSharp.de-Mitglied

Dabei seit: 19.08.2006
Beiträge: 28

Themenstarter Thema begonnen von Darrn

Darrn ist offline

Beitrag: beantworten | zitieren | editieren | melden/löschen       | Top

ich möchte folgenden code abschnitt im foreach stil schreiben:

C#-Code:
for ( int a = 0; a < nodes.Length; a++ )
{
   nodes[a] = new Object( getNext());
}
21.08.2006 18:20 Beiträge des Benutzers | zu Buddylist hinzufügen
ZiMD ZiMD ist männlich
Chefprogrammierer

images/avatars/avatar-1977.png


Dabei seit: 18.10.2005
Beiträge: 564
Entwicklungsumgebung: VS2008 Exp/Std


ZiMD ist offline

Beitrag: beantworten | zitieren | editieren | melden/löschen       | Top

Warum?
21.08.2006 18:26 Beiträge des Benutzers | zu Buddylist hinzufügen
polofreak polofreak ist männlich
myCSharp.de-Mitglied

images/avatars/avatar-1895.jpg


Dabei seit: 11.04.2006
Beiträge: 181
Entwicklungsumgebung: VS 2005 Pro EN
Herkunft: D BW


polofreak ist offline

Beitrag: beantworten | zitieren | editieren | melden/löschen       | Top

foreach ( object node in nodes) kann so schon funktionieren, poste mal etwas mehr Code und deinen Fehler!
Denn geht nicht ist immer eine schlechte Beschreibung!!
22.08.2006 08:49 E-Mail | Beiträge des Benutzers | zu Buddylist hinzufügen
norman_timo norman_timo ist männlich
myCSharp.de-Poweruser/ Experte

images/avatars/avatar-1775.jpeg


Dabei seit: 13.07.2004
Beiträge: 4.506
Entwicklungsumgebung: .NET 2.0/3.5 und VS2005/VS2008
Herkunft: Wald-Michelbach (Odw)


norman_timo ist offline

Beitrag: beantworten | zitieren | editieren | melden/löschen       | Top

Hallo zusammen,

man kann definitiv die Referenzen, die temporär mit foreach erzeugt werden nicht innerhalb der foreach schleife verändern. Damit würde man die Reihenfolge und das abgreifen der nächsten Elemente durcheinander bringen.

Also ein

C#-Code:
foreach (Irgendwas tempInstanz in IrgendWasAnderes)
{
   tempInstanz = Neuer Wert;
}

Ist definitiv nicht möglich. Dazu muss man wissen, wie foreach implementiert ist. Das kann man z.B. dann nachvollziehen, wenn man für seine eigenen Klassen mal IEnumerator und IEnumerable implementiert hat.

Das foreach greift hier Element für Element mittels GetNext() (oder MoveNext?) ab. Dabei müssen die Elemente in einer festen Reihenfolge stehen. Sollte sich jetzt ein Wert eines Elementes ändern, so kann die Reihenfolge durcheinander geraten sein, und es ist nicht mehr sichergestellt, dass Foreach noch so funktioniert wie es sollte.

Bei einer For-Schleife wird immer über einen Index zugegriffen, und daher ist diese Problematik hier nicht gegeben. Man könnte hier innerhalb der For-Schleife auch zwei Reihenfolgen vertauschen, jedoch würde der Zugriff auf den Index immer noch funktionieren. Die For-Schleife ist auch nicht dafür vorgesehen ALLE Elemente nur EINMAL zu durchlaufen, sondern ist allgemeingültig. Eine Foreach-Schleife ist definitiv so gedacht ALLE Elemente nur EINMAL zu durchlaufen, und da müssen solche Restriktionen gegeben sein.

Sorry, dass ich Dir hier nix anderes sagen kann...

Gruß
Norman-Timo
22.08.2006 10:58 E-Mail | Beiträge des Benutzers | zu Buddylist hinzufügen
Darrn
myCSharp.de-Mitglied

Dabei seit: 19.08.2006
Beiträge: 28

Themenstarter Thema begonnen von Darrn

Darrn ist offline

Beitrag: beantworten | zitieren | editieren | melden/löschen       | Top

das sehe ich nicht so. die native implementation von foreach für arrays wird den aktuellen index irgendwo speichern und pro durchlauf erhöhen, wie in einer normalen for-schleife. ob sich das verweisziel eines element im array ändert ist für die reihenfolge unerheblich. bei collection kann das natürlich anders sein, die sind aber auch nicht nativ implementiert. und in PHP gehts auch... Augenzwinkern

Dieser Beitrag wurde 3 mal editiert, zum letzten Mal von Darrn am 23.08.2006 17:09.

23.08.2006 17:06 Beiträge des Benutzers | zu Buddylist hinzufügen
Borg
myCSharp.de-Poweruser/ Experte

Dabei seit: 23.08.2006
Beiträge: 1.529
Entwicklungsumgebung: VS2005
Herkunft: Berlin, Germany


Borg ist offline

Beitrag: beantworten | zitieren | editieren | melden/löschen       | Top

Das ist aber nicht PHP sondern C#.
Und norman_timo hat die Funktionsweise von foreach genau richtig beschrieben. Auch wenn es theoretisch möglich wäre, in einem nicht dynamischen Array die Elemente während der Iteration zu ändern, würde das die Allgemeingültigkeit von foreach für alle Collections (IEnumerator) einschränken.

Sicherlich hast du Recht, wenn du schreibst, dass foreach für ein Arry die Indize inkrementiert und durchläuft. Das ist jedoch eine spezifische Implementation der IEnumerator Schnittstelle für ein Array. Und diese nicht zu kennen (müssen), ist eine der Grundlagen der OOP (Kapselung).

Ausserdem kann man bei

C#-Code:
node[] nodes = new node[ anzahl ];
for( int i=0; i < nodes.Length; i++ )
{  nodes[i] = getNext();  }

wohl wahrlich kaum von kompliziert sprechen.
Eher davon, dass dein Klassendesign wahrscheinlich der Verbesserung bedarf.

Dieser Beitrag wurde 1 mal editiert, zum letzten Mal von Borg am 23.08.2006 17:34.

23.08.2006 17:34 E-Mail | Beiträge des Benutzers | zu Buddylist hinzufügen
norman_timo norman_timo ist männlich
myCSharp.de-Poweruser/ Experte

images/avatars/avatar-1775.jpeg


Dabei seit: 13.07.2004
Beiträge: 4.506
Entwicklungsumgebung: .NET 2.0/3.5 und VS2005/VS2008
Herkunft: Wald-Michelbach (Odw)


norman_timo ist offline

Beitrag: beantworten | zitieren | editieren | melden/löschen       | Top

Hallo Darrn,

für alle Standard-Collections kann das durchaus sein, dass es über Index läuft. Aber Du hast die Möglichkeit doch eine eigene Implementierung von "GetNext() (oder MoveNext?)" vorzunehmen, und Foreach funktioniert trotzdem.

Da das dann der Fall ist, kann Foreach vorher nicht wissen, wie auf die Elemente zugegriffen wird, und daher kann sich die Reihenfolge auch ändern.

Wie gesagt, implementiere mal Spaßeshalber selbst IEnumerator und IEnumerable in Deiner eigenen Klasse mit z.B. einem Dictionary<string, string> Objekt als Datenspeicher, über den iteriert werden soll.

Dann wirst Du genau sehen, was ich meine...

Gruß
Norman-Timo
23.08.2006 17:36 E-Mail | Beiträge des Benutzers | zu Buddylist hinzufügen
talla talla ist männlich
myCSharp.de-Poweruser/ Experte

images/avatars/avatar-3214.jpg


Dabei seit: 20.07.2003
Beiträge: 6.862
Entwicklungsumgebung: VS 2010
Herkunft: Esslingen


talla ist offline

Beitrag: beantworten | zitieren | editieren | melden/löschen       | Top

PHP ist ja auch wohl kaum so streng typisiert wie C# smile

Foreachs werden in der Tat meistens zu for Schleifen optimiert, aber halt nicht immer, und genau deshalb kann man das bei foreach net erlauben die Referenz generell ändern zu lassen. Wie willst du denn Arrays von Collections bzw. von anderen Datenstrukturen die IEnumerable implementieren unterscheiden?
23.08.2006 17:40 E-Mail | Beiträge des Benutzers | zu Buddylist hinzufügen
Borg
myCSharp.de-Poweruser/ Experte

Dabei seit: 23.08.2006
Beiträge: 1.529
Entwicklungsumgebung: VS2005
Herkunft: Berlin, Germany


Borg ist offline

Beitrag: beantworten | zitieren | editieren | melden/löschen       | Top

Als kleiner semantischer Zusatz noch folgendes:

C#-Code:
typeX[] bla = ...;
foreach( typeX i in bla )
{
     DoSomethingUsefull( i );
}

Da in einer Collection beliebige Objekte gespeichert sein können, benötigt der Compiler Typinformationen. Daher muss man i innerhalb des foreach-Kopfes als typeX deklarieren.
Damit ist i aber eine lokale Variable innerhalb der foreach-Schleife.

Das Zuweisen von Werttypen (struct) an i würde also nur die lokale Variable für den aktuellen Schleifendurchlauf (beim nächsten erhält sie ja einen neuen Wert) verändern.

Das Zuweisen von Referenztypen (class) an i würde eine Referenz auf das eigentliche Objekt speichern. Wird dieses nicht anderweitig referenziert, wird es vom Garbage Collector am Ende des Gültigkeitsbereichs (scope) von i (also am Ende eines Schleifendurchlaufs) abgeräumt.

Daher KANN man gar nichts zuweisen, was über die Schleife hinaus Bestand haben soll.

Dieser Beitrag wurde 2 mal editiert, zum letzten Mal von Borg am 23.08.2006 17:49.

23.08.2006 17:46 E-Mail | Beiträge des Benutzers | zu Buddylist hinzufügen
svenson svenson ist männlich
myCSharp.de-Poweruser/ Experte

Dabei seit: 15.04.2005
Beiträge: 8.746
Entwicklungsumgebung: Visual Studio .NET 2003
Herkunft: Berlin


svenson ist offline

Beitrag: beantworten | zitieren | editieren | melden/löschen       | Top

Letztlich gehts hier um Performance. Will man einen Iterator schreiben, der das Verändern der Collection beim Iterieren erlaubt, dann kostet das Performance und/oder Speicherplatz.
23.08.2006 17:57 E-Mail | Beiträge des Benutzers | zu Buddylist hinzufügen
Baumstruktur | Brettstruktur       | Top 
myCSharp.de | Forum Der Startbeitrag ist älter als 12 Jahre.
Der letzte Beitrag ist älter als 12 Jahre.
Antwort erstellen


© Copyright 2003-2018 myCSharp.de-Team. Alle Rechte vorbehalten. 14.12.2018 22:22