[VC++.NET] Arbeiten mit Generic::List / Array

the incredible Leitman

Erfahrenes Mitglied
Hallo Leute :D

Ich hab wieder mal ein Problem auf dessen Lösung ich nicht komme -.-
Haltet mich nicht für blöd...(oder zumindest für blöder als ich bin) aber ich checks einfach nicht...

Ich arbeite zurzeit mir Generic Lists in C++.NET... hab noch nicht soviel Erfahrung mit dieser Datenstruktur, hab bisher immer Arrays verwendet....
Doch diesmal muss ich die Liste aus einer Funktion verwenden...

Nun meine Frage:
Wie kann ich auf die einzelnen Elemente dieser Liste zugreifen?
In einem Array nehme ich einfach array[index] aber in einer Liste
Hab schon ein bisschen mit IndexOf probiert, aber das ist nicht das, was ich will...oder ich checks einfach nicht -.-

Also ich möchte einfach vom ersten Element bis zum 3. einen Strich zeichnen (ja, es sind Punkte drinnen), dann vom 2. zum 4. ... usw.
Bis jetzt hab ich die Liste mittels ToArray in ein Array umgewandelt und damit gearbeitet... das ist aber nicht nur zusätzlicher Aufwand, sondern auch noch nicht unbedingt sauber....

Kann ich das anders lösen?

Bitte Hilfe :)
 
Hi Micha!

Also das ist eigentlich sehr einfach zu verstehen,
sogar für einen wie mich der aktiv nicht mit dem 2.0er Framework zu tun hat. :p

Gut dann will ich dich mal aufklären die die Generics in .NET 2.0 gestrickt sind.
Es gibt 2 verschiedene sorten von Sammlungen Listen (List) und Hashtables (Dictionary).
Die generische definiton einer Liste oder einer Hashtable erspaart dir das Implementieren
einer typsicheren Sammlung so wie man es noch in .NET 1.1 machen musste.
Mit typsicher meine ich, dass man nur Objekte eines bestimmten Typs in die Sammlung hinein und auch wieder herraus bekommt.
Dafür musste man in .NET von der entsprechenden Sammlung ableiten und die entsprechende Methoden und Indexer überscheiben,
oder man verwendete einer der verfügbaren Basisklassen (CollectionBase, DictionaryBase).

Der große Vorteil ist nun das man durch die generische Definition einer Liste in .NET 2.0,
bereits während der definierung fest legen kann, mir welchen Typ eine Liste gefüllt werden soll (List<myType>)
oder welcher Typ bei einer Hashtable als Schlüssel (Key) und welcher Typ als Wert (Value) verwendet werden soll
(Dictionary<MyKeyType><MyValueType>).

Soweit klar denke ich. :)

Kommen wir jetzt zu der eigentlichen Defnition einer generisch definierten Liste.
C#:
List<MyType> myGenericList = new List<MyType>();
MyType myType = new MyType();

myGenericList.Add( myType );
myType = myGenericList[0];
Zum Schluss die Definition einer generisch definierten Hashtable.
C#:
Dictionary<string, MyType> myGenericHashTable = new Dictionary<string, MyType>();
myGenericHashTable[ "Key" ] = new MyType();
MyType myType = myGenericHashTable[ "Key" ];
In beiden Fällen ist sehr schön zu sehen, dass kein casting mehr notwendig ist.
 
Ohhh.... *Licht-aufgeh*

Danke, Cosmo für die flotte Erklärung :D

gut, ich habe sowieso nur ab .NET 2.0 zu tun, deshalb absolut keinen Plan, was sich geändert und dass man das alles noch selber typenüberprüfen musste -.-

Achso... dass ich auf die einzelnen Elemente einer Liste eh mittels Index zugreifen konnte wußte ich nicht... habs natürlich probiert, aber da hat irgendwas nicht gfunkt...
aber jetzt gehts, toll danke :)

was die Hashtables angeht... :confused: der Hund ..blablablabla... muss weg... blablabla :p
Das werd ich mir erst genauer ansehen, sobald ichs brauch... heute schon zu spät um meinen Kopf mit noch mehr Information zu füllen (hatte gerade 5 Stunden Projektbesprechung x_x ) XD

Nur der Interesse halber... was ist eigentlich der Unterschied zwischen Listen und herkömmlichen Arrays? Nur dass ich Listen sortieren und Sachen anhängen / löschen kann, ohne dafür extra Funktionen implementieren zu müssen?

Big THX again,
mfG

Leitman

PS: bitte nicht michael... und schon gar nicht Micha :p
 
Re: AW: [VC++.NET] Arbeiten mit Generic::List / Array

Gut, ich mach die Frage wieder auf, ich bin auf ein mir unverständliches Problem gestoßen :confused:

Ich habe nun eine Liste an Punkten, die ich übergeben bekommen,
anschließend weise ich meiner Member Liste diese Punkte zu und überprüfe die Positionen.
Da ich Strichdicken größer als eins verwende, würde ich beim Zeichnen nur immer die halbe Linie sehen, deswegen möchte ich den einzelnen Punkten in der Liste neue Werte zuweisen...
Seltsamerweise werden die neuen Punkte nicht gespeichert...

kann mir vielleicht jemand erklären warum?

C++:
// wenn ich wie folgt versuche, die Punkte direkt in meiner member Liste 
// zu verändern, werden die neuen Werte nich übernommen:
for(int idx = 0; idx < this->m_pointList->Count; ++idx)
{
	if(this->m_pointList[idx].X == 0)
	{
		this->m_pointList[idx].X = this->m_pointList[idx].X + 1;
	}
	if(this->m_pointList[idx].X == this->Width)
	{
		this->m_pointList[idx].X = this->m_pointList[idx].X -1;
	}
	if(this->m_pointList[idx].Y == 0)
	{
		this->m_pointList[idx].Y = this->m_pointList[idx].Y + 1;
	}
	if(this->m_pointList[idx].Y == this->Height)
	{
		this->m_pointList[idx].Y = this->m_pointList[idx].Y -1;
	}
}

// auch nicht wenn ich for each verwende:
for each(Point pt in this->m_pointList
{
	if(pt.X == 0)
	{
		pt.X = pt.X + 1;
	}
	if(pt.X == this->Width)
	{
		pt.X = pt.X -1;
	}
	if(pt.Y == 0)
	{
		pt.Y = pt.Y + 1;
	}
	if(pt.Y == this->Height)
	{
		pt.Y = pt.Y -1;
	}
}
// kann mir jemand sagen warum? Liegt das am Scope oder was?

Wenn ich hingegen die Liste in ein Array umwandle und dann die Werte ändere funktioniert es problemlos:
C++:
// so gehts
array<Point> ^arr = gcnew array<Point>(this->m_pointList->Count);
arr = this->m_pointList->ToArray();

for(int idx = 0; idx < arr->Length; ++idx)
{
	if(arr[idx].X == 0)
	{
		arr[idx].X = arr[idx].X + 1;
	}
	if(arr[idx].X == this->Width)
	{
		arr[idx].X = arr[idx].X -1;
	}
	if(arr[idx].Y == 0)
	{
		arr[idx].Y = arr[idx].Y + 1;
	}
	if(arr[idx].Y == this->Height)
	{
		arr[idx].Y = arr[idx].Y -1;
	}
}

Ich machs halt jetzt in der Array Art, (muss ich sowieso, da ich nur ein PointArray und keine PointListe zeichnen kann) trotzdem würde ich gerne wissen, warum ich nicht auf die Werte meiner Liste zugreifen und diese verändern kann?

mfG und Danke im Vorraus
Leitman

PS: @Macan:
Ich habe eine Benachrichtigung von dir bekommen, dass du auf dieses Thema geantwortet hat, jedoch sehe ich keinen Beitrag von dir? Was ist da passiert :confused:
 
Zuletzt bearbeitet:
Re: AW: [VC++.NET] Arbeiten mit Generic::List / Array

Nur der Interesse halber... was ist eigentlich der Unterschied zwischen Listen und herkömmlichen Arrays? Nur dass ich Listen sortieren und Sachen anhängen / löschen kann, ohne dafür extra Funktionen implementieren zu müssen?
Du machst mir angst, Michael ähh leitman. *fg* :D
Du hackst schon seit einem halben jahr auf c++.net rum und kennst noch nicht mal
die elementaren Elemente des Frameworks.
Ist aber nicht schlimm, das war bei mir anfangs auch so als ich mit c# angfangen hab. :D
Daran erkennt man die enthusiastischen coder, die auch ohne Lehrmeister ihren weg gehen.
Man muss nur irgend wann mal raffen das man sich mal von selbst mit den Basics auseinander setzt.
Sonst übersieht man noch Möglichkeiten bestimmte Sachen die man mithilfe von bereits fertigen Dingen,
die vom Framework bereit gestellt werden, viel schneller und vor allen noch viel sauberer fertig stellen kann.

Ein Array (System.Collections.Array - MyType[]) ist einer einfach verkettete Liste die in ihrer Große statisch ist.
Will man sie vergrößern oder verkleinern, hat man einen relativ nervigen Kopieraufwand
der den Code zudem sehr hässlich aussehen lässt.
Arrays können aber auch mehrere Dimensionen haben.
MyType[,] myFourDimArray = new MyType[2,4] würde einem 2 Dimensionalem Array Entsprechen.
Verinnerliche Dir das als eine Art Tabelle. ;)
MyType[1,1] währe dann der Index des 2. Elements in der 2. Spalte.
0,0
0,X
0,0
0,0

Da Arrays nun eine fixe Größe haben, sind sie schlecht als zwischenspeicher für Werte geeignet,
deren Anzahl sich permanent ändert oder ändern kann. Eher als permenenter Ablageplatz
für Werte oder als statischer Zwischenspeicher, dessen Elementanzahl sich nicht ändert.
Aus der Notwendigkeit herraus sind nun die dynamischen Listen enstanden (ArrayList).
Neu in .NET 2.0 zusätzlich dazu die Generische Definition die schon erörtert habe (List<MyType>).

Da die Elemente dieser Sammlungen leider nur viá eines numerischen Indexers angesprochen werden können
und es auch Fälle gibt bei denen es notwendig ist Werten einen einen bestimmten Schlüssel zuzuordnen,
sind die Schlüssel-Wert-Sammlungen enstanden (System.Collections.Hashtable).
Der Zugriff auf ein Element der Sammlung geschieht nicht über einen Indexer,
sondern dem Wert ist ein Schlüssel sprich ein Objekt eines bestimmten Typs zugeordnet.
Diese Art von Sammlungen sind völlig dynamisch und können mit allen möglichen Typen verwendet werden.
 
Zuletzt bearbeitet:
Re: AW: [VC++.NET] Arbeiten mit Generic::List / Array

Du machst mir angst, Michael ähh leitman. *fg* :D
*lol* :D
Du hackst schon seit einem halben jahr auf c++.net rum und kennst noch nicht mal die elementaren Elemente des Frameworks...
Doch doch, ich weiß schon, was Arrays und Listen sind (naja, ok, mit Hashtables hatte ich bisher wirklich nichts zu tun -.-) nur das ich auf Listen auch mittels Indizes zugreifen kann, wusste ich nicht... und der Unterschied ist mir immer noch zu unwesentlich.

Dimensionen, alles klar, war mir bekannt,...

Arrays haben nur eine fixe Größe
C++:
// for Schleife
arr[idx] = c;
++idx;
if (idx == arr->Length)
{
	arr->Resize(arr, arr->Length + 8);
}
So habe ich kein Problem, die Größe des Arrays zu ändern, nur wie gesagt es ist halt zusätzlicher Aufwand, da eine Liste automatisch vergrößert wird, sobald man etwas hinzufügt... gescheige denn, falls man irgendwelche Sortieralgorythmen braucht -.-

Danke nochmals für die zusammenfassende Erklärung
mfG
Leitman
 
Re: AW: [VC++.NET] Arbeiten mit Generic::List / Array

Seltsamerweise werden die neuen Punkte nicht gespeichert...

kann mir vielleicht jemand erklären warum?
Junge Junge,
Du weisst aber schon was die Point-Klasse im eigentlichen Sinne ist oder?
Eine Struktur. Was sagt uns das? Richtig :D, alle Member einer Struktur können nur vom Konstruktor selber verändert werden,
sprich während der Instanzierung. Was schließen wir daraus? Wieder richtig :D,
Du musst also das Point-Objekt an dem entsprechenden Index in der Sammlung einfach neu instanzieren.
C++:
this->m_pointList[idx] = new Point(
	this->m_pointList[idx].X + 1,
	this->m_pointList[idx].Y + 1 )
 
Zuletzt bearbeitet:
Re: AW: [VC++.NET] Arbeiten mit Generic::List / Array

gescheige denn, falls man irgendwelche Sortieralgorythmen braucht -.-
Wer zur Hölle braucht heutzutage noch Sortieralgorithmen? :D
Schon mal was von IComparable gehört.
Damit kann jedes Objekt, das sich in einem Array befindet, selbert bestimmen wie es sortiert wird.
Da brauchst vonn aussen her gar nichts mehr sortieren...

[thread=232634]Array "Sortieren" - Thread[/thread]
[thread=251026]mehrdimensionales Array sortieren - Thread[/thread]
 
Re: AW: [VC++.NET] Arbeiten mit Generic::List / Array

Ja, doch schon, Struktur... hat mich nur gewundert, wieso das mit nem Array klappt und mir ner Liste nicht, obwohl eigentlich dieselbe Syntax / Vorgehensweise?
Das ist unlogisch. Du hast wohl eher das Point-Objekt vorher aus der Liste entfernt
oder wohl doch direkt überschrieben.
Der Typ einer Sammlung ändert doch nicht das Verhalten von Werttypen. ;)
 
Zurück