PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : c#: Frage zu ArrayList


pajofego
2005-01-27, 16:09:24
Hallo Leute haben folgenden Beispielcode geschrieben:


public struct MeineStruct
{
public int i;
}

public class MeineStructs : System.Collections.ArrayList
{
public int Add(MeineStruct value)
{
return base.Add(value);
}

public new MeineStruct this[int index]
{
get { return (MeineStruct)base[index]; }
set { base[index] = value; }
}
}

class Program
{
static MeineStructs mstr = new MeineStructs();
static void Main(string[] args)
{
mstr.Add(new MeineStruct());
mstr[0].i = 1;
Console.WriteLine("Value: " + mstr[0].i.ToString() );
}
}


In der vorletzten Zeile (mstr[0].i = 1) möchte ich gerne meinem ersten Eintrag in meiner vererbten Klasse MeineStructs der dort enthaltenen "struct" (MeineStruct), der Variable "i" einen Wert zuweisen. Der Compiler meldet diesbgzl. folgenden Fehler:

Cannot modify the return value of 'ConsoleApplication1.MeineStructs.this[int]' because it is not a variable :eek:

Vielleicht habe ich Tomaten auf den Augen, aber irgendwie komme ich nicht dahinter, warum ich der Variable i keinen Wert zuweisen kann? Lesen geht!

Wäre euch dankbar, wenn Ihr mir einen Tipp geben könntet!

Danke,

Gruss Paulo

Nagilum
2005-01-27, 17:43:08
Ich bin nicht der C# Crack, aber was du versuchst, ergibt doch eigentlich keinen Sinn? Structs sind Wertetypen und das Auslesen aus der Property führt so zu einer Kopie von mstr[0]. Den Wert dieser Kopie zu ändern dürfte aber ziemlich sinnfrei sein, und deshalb haut dir wohl auch der Compiler auf die Flossen. :)

Probiers mal mit einer temporären Variablen, oder nimm eine Klasse.

class Program {
static MeineStructs mstr = new MeineStructs();
static void Main(string[] args) {
mstr.Add(new MeineStruct());

MeineStruct ms = mstr[0];
ms.i = 1;

Console.WriteLine("Value: " + ms.i.ToString() );
}
}

pajofego
2005-01-27, 20:14:47
Aaaaah! Ich hatte ehrlich gesagt eine ganz andere Vorstellung von structs! Dank, deines Hinweises habe ich mich nochmals hier etwas genauer umgesehen! msnd (http://msdn.microsoft.com/library/default.asp?url=/library/en-us/csref/html/vcwlkstructstutorial.asp)

Gruss,

pajofego

Demirug
2005-01-27, 20:16:41
structs sind bei C# eine der besten Möglichkeiten sich selbst ins Knie zu schiessen.

Ist mir gerade heute Mittag selbst passiert.

Jesus
2005-01-28, 20:12:46
Dir fehlt die get bzw set funktion in deinem Strukt ( bzw. eine init funktion mit selbem Namen wie das struct). So ungefähr


public MeineStruct{

public int x;

public MeineStruct(int x){

this.x=x;

}
}

oder eben mit get/set...

in C# solltest du allerdings auch lieber Klassen für Datenstrukturen nehmen. Die lassen sich wesentlich besser weiterverwenden, und werden auch als Data Objects bspw. von Datagrids ö.ä. akzeptiert, structs dagegen nicht.

Nagilum
2005-01-28, 20:25:54
Öhm. Was hat das mit dem urspünglichen Fehler zu tun?

Dir fehlt die get bzw set funktion in deinem Strukt
Get und Set sind nur syntaktischer Zucker. Ausserdem war die Membervariable bereits öffentlich.

( bzw. eine init funktion mit selbem Namen wie das struct). So ungefähr
Structs haben einen Default Constructor, der alle Member auf ihre Defaultwerte setzt.

Jesus
2005-01-28, 20:36:10
oh, sorry hab mir nicht alles angeschaut :rolleyes:

pajofego
2005-01-29, 01:18:38
Hab jetzt alles (structs) einfach in Klassen umgewandelt! Weg des geringsten Widerstandes! :rolleyes:

Gruss pajofego

][immy
2005-02-03, 13:15:56
bei deiner Struct darfst du kein new verwenden ;)

aber wieso nutzt du überhaupt ein struct?
ist zwar schneller da diese auf dem Stack liegt (nicht wie bei Objekten wo ein Pointer im Stack auf das Objekt zeigt) aber macht an dieser stelle nicht viel sinn

eine speicherreservierung durch new ist nicht nötig (bzw auch nicht möglich) da ein struct mehr oder weniger ein einfacher selbstdefinierter Datentyp ist bzw sein sollte (bzw sollte es nur aus einfachen datentypen bestehen). objekte sollte man innerhalb eines structs auch nicht nutzen, da der geschwindigkeitsvorteil dann auch wieder dahin ist, da ein objekt nur wieder im hauptspeicher liegt, d.h. für das objekt liegt auch wieder nur ein pointer im stack der auf den speicherbereich zeigt wo sich das objekt wirklich befindet

in dem Beispiel auf msdn haben die ein struct als Klasse missbraucht (was wie oben beschrieben unsinnig ist), daher brauchten die auch wieder ein new ;)

Nagilum
2005-02-03, 13:33:01
[immy']bei deiner Struct darfst du kein new verwenden ;)
Dann würd mich mal interessieren, wie du ohne new-Operator z.B. die privaten Member eines Structs initialisiert bekommst?

'new' bewirkt bei Structs nicht das das Ablegen auf dem Heap, sondern ein Aufruf des Konstruktors, der defaultmässig alle Membervariablen initialisiert.

][immy
2005-02-03, 14:30:59
Dann würd mich mal interessieren, wie du ohne new-Operator z.B. die privaten Member eines Structs initialisiert bekommst?

'new' bewirkt bei Structs nicht das das Ablegen auf dem Heap, sondern ein Aufruf des Konstruktors, der defaultmässig alle Membervariablen initialisiert.

ich habe doch geschrieben das man eine struct natürlich auch als klasse missbrauchen kann, ist aber für ein struct unsinnig.

das "new" bewirkt immer nur das speicher reserviert wird. nebenbei rufst du bei der verwendung von 'new' natürlich auch einen constructor auf, aber nur um bei der initialisierung schon etwas auszuführen zu können oder direkt etwas zu übergeben, was später für die benutzung des objekts wichtig ist.

für einen primitiven datentyp (int, char, double,...) muss nicht extra durch einen befehl speicher reserviert werden, diese typen liegen (wie schon erwähnt) direkt im stack und haben immer eine feste größe. ein struct sollte ansich nur aus eben solchen primitiven datentypen bestehen, daher sollte auch kein new verwendet werden müssen

ist in einer klasse kein constructor vorhanden wird durch das new ein standartconstructor aufgerufen welcher so gesehen nichts macht

Nagilum
2005-02-03, 14:35:36
Du schreibst:

bei deiner Struct darfst du kein new verwenden
Und das ist schlicht und einfach falsch.

Ich lass mich aber gerne vom Gegenteil überzeugen, wenn du meine Frage beantwortest. :)


Zudem würd mich mal interessieren, warum man "new" mit einem Struct nicht verwenden sollte? Welche bösen Nebenwirkungen hat es denn?

][immy
2005-02-03, 14:41:15
Du schreibst:


Und das ist schlicht und einfach falsch.

Ich lass mich aber gerne vom Gegenteil überzeugen, wenn du meine Frage beantwortest. :)

les nochmal genau
Zitat:
"bei deiner struct darfst du kein new verwenden"

das war nur auf den code bezogen der oben steht, da steht nur
public struct MeineStruct
{
public int i;
}

keine methode, kein komplexer datentyp ergo kein new ;)

edit:
wenn du um ein struct zu erzeugen ein new verwenden musst, ist das struct eine klasse und es handelt sich um einen komplexen datentyp
"struct" wurde aber dafür "erfunden" schnelle kleine datenspeicher zu haben. nutzt du ein struct wie eine klasse hast du keinen einzigen vorteil mehr den dir ein struct bietet, sondern wirst sogar noch von jedem programmierer schelte bekommen weil man sowas halt nicht macht.

man kann ja auch in c# & co nicht objekt orientiert programmieren, aber man macht es halt nicht (es sei denn es geht an einigen stellen nicht anders), weil man sich auch an gewissen konventionen hält. nebenbei kann man dann auch die vorteile die einem die OOP bietet vergessen. möglichst ist es, aber deshalb muss man es noch lange nicht machen.
alles was komplex ist gehört in eine klasse, benötigt man einen schnellen datenspeicher für primitive datentypen bietet sich ein struct an

Nagilum
2005-02-03, 14:51:06
[immy']keine methode, kein komplexer datentyp ergo kein new ;)

Das ist auch wieder gnadenlos pauschalisiert. Denn probier mal folgendes:


public struct MyStruct
{
public int i;
}

void Methode()
{
// Dein Code
MyStruct s1;
Console.WriteLine(s1.i);

// Mein Code
MyStruct s2 = new MyStruct();
Console.WriteLine(s2.i);
}


Ich hab im Moment keinen C# Compiler zur Hand, ich bin mir aber ziemlich, dass er bei deinem Code mindestens eine Warning, wenn nicht sogar einen Error wegen fehlender Initialisierung ausspuckt.

Ist es eine gute Angewohnheit uninitiliasierte Variablen mit sich herumzuschleppen?

][immy
2005-02-03, 15:02:31
Das ist auch wieder gnadenlos pauschalisiert. Denn probier mal folgendes:


public struct MyStruct
{
public int i;
}

void Methode()
{
// Dein Code
MyStruct s1;
Console.WriteLine(s1.i);

// Mein Code
MyStruct s2 = new MyStruct();
Console.WriteLine(s2.i);
}


Ich hab im Moment keinen C# Compiler zur Hand, ich bin mir aber ziemlich, dass er bei deinem Code mindestens eine Warning, wenn nicht sogar einen Error wegen fehlender Initialisierung ausspuckt.

Ist es eine gute Angewohnheit uninitiliasierte Variablen mit sich herumzuschleppen?

uninitialisierte komplexe Variablen (Objekte) verbrauchen auch kein speicher ;)
primitive datentypen verbrauchen speicher ab ihrer deklaration

und zu deiner frage mit dem kompelieren, nein der meldet einen fehler (da du vergessen hast meinem i was zu übergeben ;) )

..
und nochmal weil es so schön war, primitive datentypen müssen nicht manuel initialisiert werden. das geschieht quasi automatisch, der speicher ist im stack direkt mit deklaration "reserviert"
und nochmal die zwote:
ein struct sollte nur für die zusammenstellung primitiver datentypen verwendet werden

edit:
... ok.. nun.. muss mich wohl eben vertan haben, da hatte es ansich ohne das new kompeliert, mit aber nicht

grakaman
2005-02-03, 15:08:47
edit:
wenn du um ein struct zu erzeugen ein new verwenden musst, ist das struct eine klasse und es handelt sich um einen komplexen datentyp
"struct" wurde aber dafür "erfunden" schnelle kleine datenspeicher zu haben. nutzt du ein struct wie eine klasse hast du keinen einzigen vorteil mehr den dir ein struct bietet, sondern wirst sogar noch von jedem programmierer schelte bekommen weil man sowas halt nicht macht.


Wenn du bei Microsoft.NET eine Struktur mit new verwendest, wird hier nur der Standardkonstruktor aufgerufen. Das new bewirkt bei einer Struktur keinefalls, dass sie auf dem Heap landet. Dass eine Struktur immer auf dem Stack landet, liegt daran, dass sie von System.ValueType erbt. Und der Heap ist bei .NET fast so schnell wie der Stack. Das hat aber nichts mit dem Speicher an sich zu tun, sondern mit der Verwaltung. Der Vorteil einer Struktur ist viel eher die, dass sich in bestimmten Szenarien (z.B. int Array) Objektinstanzierungen sparen kann. Falsch eingesetzt, kann es aber das Gegenteil bewirken, da ja z.B. immer Kopien erstellt werden, wenn du die Struktur z.B. einer Methode übergibst.

grakaman
2005-02-03, 15:13:16
[immy']und zu deiner frage mit dem kompelieren, nein der meldet einen fehler (deswegen gibt es ja diesen thread ;) ) einen leeren contructor kann eine struct übrigends auch nicht enthalten (auch eben ausprobiert), dem constructor muss schon was übergeben werden sonst gehts nicht


Na klar geht das. Du darfst nur keinen Standardkonstruktor _definieren_, aber eine Struktur hat immer einen Standardkonstruktor. Das geht z.B. problemlos:

System.Int32 myint = new System.Int32();
myint = 3;
Console.WriteLine(myint);

Keine Warnung, kein Fehler, gar nichts :-)

][immy
2005-02-03, 15:18:36
Wenn du bei Microsoft.NET eine Struktur mit new verwendest, wird hier nur der Standardkonstruktor aufgerufen. Das new bewirkt bei einer Struktur keinefalls, dass sie auf dem Heap landet. Dass eine Struktur immer auf dem Stack landet, liegt daran, dass sie von System.ValueType erbt. Und der Heap ist bei .NET fast so schnell wie der Stack. Das hat aber nichts mit dem Speicher an sich zu tun, sondern mit der Verwaltung. Der Vorteil einer Struktur ist viel eher die, dass sich in bestimmten Szenarien (z.B. int Array) Objektinstanzierungen sparen kann. Falsch eingesetzt, kann es aber das Gegenteil bewirken, da ja z.B. immer Kopien erstellt werden, wenn du die Struktur z.B. einer Methode übergibst.

ich hatte geschrieben "wenn du um ein struct zu erzeugen ein new verwenden musst", denn dann hat man in der struktur methoden definiert, und es exestiert kaum ein unterschied mehr zu einer klasse, den ein struct sollte so etwas nicht beinhalten. beinhaltet ein struct so etwas musst du ein new verwenden, wenn nicht.. .dann nicht. beinhaltet dein struct einen komplexen datentyp landet dieser im heap und lediglich der pointer auf dem stack, wodurch der (immernoch vorhanden) geschwindigkeitsvorteil wieder weg ist

@grakaman... das andere hatte ich schon selbst gestrichen ;)

grakaman
2005-02-03, 15:27:16
[immy']ich hatte geschrieben "wenn du um ein struct zu erzeugen ein new verwenden musst", denn dann hat man in der struktur methoden definiert, und es exestiert kaum ein unterschied mehr zu einer klasse, den ein struct sollte so etwas nicht beinhalten.


Natürlich nicht, denn fast jede Struktur enthält Methoden (z.B. ToString()).


beinhaltet ein struct so etwas musst du ein new verwenden, wenn nicht.. .dann nicht.
[QUOTE=']

Nein musst du nicht, es wird dann nur nicht der Standardkonstruktor aufgerufen. Aber ob new benutzt wird oder nicht, hat nichts mit Methoden zu tun.

[QUOTE=']
beinhaltet dein struct einen komplexen datentyp landet dieser im heap und lediglich der pointer auf dem stack, wodurch der (immernoch vorhanden) geschwindigkeitsvorteil wieder weg ist

Komplexe Datentypen und Primitives haben nichts mit Heap oder Stack zu tun. Einen Primitive nennt man einen Datentyp, den man per Wertezuweisung initialisieren kann. Ich kann auch komplexe Strukturen schreiben, das ist ja kein Problem.

Nagilum
2005-02-03, 15:30:08
Danke Graka.

Ich wollte schon das Ticket nach Peking buchen, in der Hoffnung, dass man mich dort besser versteht. :rolleyes:

MuLuNGuS
2005-02-17, 14:22:40
@pajofego

hi,
tatsächlich kann man das ganze per Boxing/Unboxing auch mit einer Struct(welche ja ein wertetyp ist und was auch der grund dafür war das du diese fehlermeldung erhalten hast:"Cannot modify the return value of 'ConsoleApplication1.MeineStructs.this[int]' because it is not a variable") hinbekommen..allerdings hinterher wieder nur mit einer hilfsvariable da man durchs Unboxing doch wieder nur einen wertetyp hat.

sicher, der speed geht in die knie..aber darum geht mir hier jetzt nicht, dafür kann mann jetzt jedes objekt an MeineStructs.Add() übergeben was ja auch nicht zu verachten ist ;)


using System;

namespace test
{
public struct MeineStruct
{
public int i;
}

public class MeineStructs : System.Collections.ArrayList
{
public new int Add(object value)
{
return base.Add(value);
}

public new object this[int index]
{
get {
return base[index];
}

set {
base[index] = value;
}
}
}

class Program
{
static MeineStructs mstr = new MeineStructs();
static void Main(string[] args)
{

MeineStruct ms;
ms.i = 333;

mstr.Add(ms);

Console.WriteLine("Value: " + ((MeineStruct)mstr[0]).i.ToString() );

MeineStruct ms2;
ms2.i = 666;

mstr[0] = ms2;

Console.WriteLine("Value: " + ((MeineStruct)mstr[0]).i.ToString() );

Console.Read();

}
}
}



ach ja, in C# ist eine Struct ein wertetyp...

ob so:
MeineStruct mein;

oder so:
MeineStruct mein = new MeineStruct();

pajofego
2005-02-17, 15:45:48
Cool,

das diesre Thread immer noch lebt! :biggrin: Danke an alle, die hier fleissig diskutiert haben und dazu beigetragen haben mir den Sinn und Zweck einer struct besser zu verstehen.

Bin aber jetzt mit einer Sache schwer im unklaren :confused:

Wann muss ich denn jetzt bei einer struct mit new initialisieren! Ich hab aus Gewohnheit immer new verwendet, bin mir jetzt aber duraus im klaren, dass es sich bei structs lediglich um einen Wertetypen handelt!

Gruss pajofego

MuLuNGuS
2005-02-17, 17:09:41
nun,

wenn deine struct einen constructor hat dem ein parameter übergeben werden muß dann gehts eh nur mit new...(btw: parameterlose konstruktoren sind in structs eh nicht erlaubt)


MeineStruct ms2 = new MeineStruct(666);
//ms2.i = 666;