AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Thema durchsuchen
Ansicht
Themen-Optionen

[C#] Dies ist keine Variable?

Ein Thema von Medium · begonnen am 7. Aug 2009 · letzter Beitrag vom 8. Aug 2009
Antwort Antwort
Seite 1 von 2  1 2      
Medium

Registriert seit: 23. Jan 2008
3.686 Beiträge
 
Delphi 2007 Enterprise
 
#1

[C#] Dies ist keine Variable?

  Alt 7. Aug 2009, 22:55
Ich fummel gerade mit C# rum, und da kam mir etwas seltsames über den Weg:

Ich habe folgenden Struct:
Code:
   public struct MarkedPoint
   {
      public int X;
      public int Y;
      public bool Marked;
      public MarkedPoint(int posX, int posY, bool marked)
      {
         X = posX;
         Y = posY;
         Marked = marked;
      }
      public MarkedPoint(int posX, int posY)
      {
         X = posX;
         Y = posY;
         Marked = false;
      }
   }
Und von diesem eine Liste "List<MarkedPoint>" in meiner Klasse als privates Feld. Innerhalb dieser Klasse gibt's so eine Methode:

Code:
      private void DoSomething(ref List<MarkedPoint> e)
      {
         if (e.Count>2)
         {
            int i = 1;
            do
            {
               if (eineBedingung) e[i].Marked = true;
               i++;
            } while (i<e.Count-1);
         }
      }
(Das ist natürlich ein auf die für die Frage essentiellen Teile herunter gebrochenes Codebröckchen )

Diese rufe ich dann aus einer anderen Methode heraus auf, die den Parameter aus einer übergeordneten Liste "List<List<MarkedPoint>> MainList" via "DoSomething(ref MainList[k])" in einer Schleife über k übergibt.

Das Problem:
Bei der Zuweisung [i]"if (eineBedingung) e.Marked = true;" meldet #Develop:
"Cannot modify the return value of 'System.Collections.Generic.List<Class1.MarkedPoin t>.this[int]' because it is not a variable (CS1612)"

Warum zum Henker?? Ändern des Parameters in "out" statt "ref" bringt das selbe Ergebnis. Ich komm nicht dahinter, und zudem brauch ich da sowas wie ne Lösung für
"When one person suffers from a delusion, it is called insanity. When a million people suffer from a delusion, it is called religion." (Richard Dawkins)
  Mit Zitat antworten Zitat
Dust Signs

Registriert seit: 28. Dez 2004
Ort: Salzburg
379 Beiträge
 
#2

Re: [C#] Dies ist keine Variable?

  Alt 7. Aug 2009, 23:05
Ganz einfach: der linken Seite kann nichts zugewiesen werden bzw. anders gesagt: ihr könnte zwar theoretisch etwas zugewiesen werden, da dieser Wert aber temporär wäre macht es keinen Sinn ihm etwas zuzuweisen. Mit anderen Worten: e[i] liefert dir eine lokale Kopie des Structs an der i-ten Stelle von e. Wenn du diese Kopie änderst ändert das aber natürlich nichts am entsprechenden Struct in der Liste. Mit der Liste ist das etwas umständlich zu lösen (altes Item lokal kopieren, aus der Liste löschen, Marked setzen und dann wieder an der richtigen Stelle einfügen). Besser wäre hier allerdings ein Array - auf das könntest du direkt zugreifen und die Werte ändern.
//EDIT: Wieso übergibst du eigentlich die Liste mit ref? Da es sich um ein Objekt handelt wird ohnehin nur ein "Zeiger" übergeben - das ref kannst du dir also sparen.

Dust Signs
(aka AXMD in der EE)
Die Nummer, die Sie gewählt haben, ist imaginär. Bitte drehen Sie Ihr Telefon um 90° und versuchen Sie es erneut.
  Mit Zitat antworten Zitat
Medium

Registriert seit: 23. Jan 2008
3.686 Beiträge
 
Delphi 2007 Enterprise
 
#3

Re: [C#] Dies ist keine Variable?

  Alt 8. Aug 2009, 00:02
Das ref ist drin, weil ich sowas wie du für das einzelne Feld beschrieben hast, für die ganze Liste befürchtet habe Ich tu mich noch etwas schwer damit, wann und wo genau C# jetzt mit kopien und wo mit Verweisen arbeitet. Somit ist wenigstens klar, dass die Methode diesen Parameter verändert.

Das mit der lokalen Kopie ist ärgerlich. Arrays will ich ungern benutzen, da ich die in List implementierten anderen Methoden ausgiebig nutze. Ich hab mir jetzt so beholfen:
Code:
e[i] = new MarkedPoint(e[i].X, e[i].Y, true);
Die Zuweisung einer ganzen neuen Instanz klappt nämlich. Leidet zwar ein wenig die Geschwindigkeit (und der GC) drunter, aber ich bin noch lange nicht in der Optimierungsphase. Da nehm ich die paar ms noch in Kauf.

Danke für die Erläuterung! (Auch wenn ich meine, dass mir die Liste da ja mal ruhig ne ordentliche Referenz ausspucken dürfte... grml)
"When one person suffers from a delusion, it is called insanity. When a million people suffer from a delusion, it is called religion." (Richard Dawkins)
  Mit Zitat antworten Zitat
Dax
(Gast)

n/a Beiträge
 
#4

Re: [C#] Dies ist keine Variable?

  Alt 8. Aug 2009, 00:25
Zitat von Medium:
(Auch wenn ich meine, dass mir die Liste da ja mal ruhig ne ordentliche Referenz ausspucken dürfte... grml)
Die Runtime gibt das durchaus her, aber in C# wird das nicht benutzt. Mir scheint auch, als wäre für deine Zwecke eine Klasse für die Punkte besser geeignet - damit entfällt das umkopieren des Structs, wenn du sowieso nur ein Feld änderst. Wenn du willst, dass alle Aufrufe in die Klasse statisch gebunden werden, kannst du sie auch als sealed markieren, danach kann der JIT alle Methodenaufrufe dieser Klasse statisch übersetzen (auch die virtuellen).
  Mit Zitat antworten Zitat
Medium

Registriert seit: 23. Jan 2008
3.686 Beiträge
 
Delphi 2007 Enterprise
 
#5

Re: [C#] Dies ist keine Variable?

  Alt 8. Aug 2009, 01:16
Ich hatte zu allererst mit Klassen gearbeitet, da ich aber pervers oft irgendwo Punkte neu erzeuge und wieder lösche, und teils hunderte Elemente lange Teil-Listen auf den Kopf stelle und aneinander pappe und noch andere wilde Digne damit anstelle, hab ich mit vertretbarem Aufwand (=ich will da in der jetzigen Phase möglichst kaum Hirnschmalz reintun) keine akzeptablen Laufzeiten hinbekommen. Sobald ich aus dieser "Proof-of-Concept" Phase raus bin, muss ich aber eh noch einiges optimieren und neu schreiben - ich muss halt aber erst noch raus finden, ob sich die Arbeit in ein ordentliches Programm wirklich nachher lohnt. Solang ich im Moment effizient testen kann bin ich erstmal glücklich.

Aber ich werd zu gegebener Zeit schauen ob sich da ein gutes Klassen-Konzept zu finden lässt! Guter Einwand. Spart vermutlich auch hier und da noch Dinge die jetzt by-Value passieren, ohne dass ich davon weiss . (Das mit dem sealed war übrigens ein 1a Tipp. Diese Auswirkung war mir nicht bewusst.)


PS: Allein der Gedanke daran, für einen Pixel je eine eigene Klasseninstanz... wuahhhh! Aber wir ham's ja =)
"When one person suffers from a delusion, it is called insanity. When a million people suffer from a delusion, it is called religion." (Richard Dawkins)
  Mit Zitat antworten Zitat
Dax
(Gast)

n/a Beiträge
 
#6

Re: [C#] Dies ist keine Variable?

  Alt 8. Aug 2009, 01:33
Man mag es nicht glauben, aber in der CLR (und der Java-VM und anderen GC-Umgebungen) sind Allokationen in der Regel spottbillig. Gerade wenn du viele kleine Instanzen hast, ist jede Allokation im Prinzip nichts mehr als ein Registerinkrement. Wenn du effizient Listen umdrehen willst, kannst du dir auch einen Listenwrapper schreiben, der einfach die Zugriffe verkehrt herum auf die Basisliste abbildet. Da gibt's einiges an Möglichkeiten
  Mit Zitat antworten Zitat
Medium

Registriert seit: 23. Jan 2008
3.686 Beiträge
 
Delphi 2007 Enterprise
 
#7

Re: [C#] Dies ist keine Variable?

  Alt 8. Aug 2009, 02:19
Du machst mich ganz schwindelig =) Ich knobel hier noch an elementarstem funktionalem Design, und du kommst mir mit Wrappern! Nein im Ernst: Jede Info die mir nachher das Leben leichter machen könnte ist ganz herzlich willkommen. Merci!
"When one person suffers from a delusion, it is called insanity. When a million people suffer from a delusion, it is called religion." (Richard Dawkins)
  Mit Zitat antworten Zitat
Benutzerbild von Khabarakh
Khabarakh

Registriert seit: 18. Aug 2004
Ort: Brackenheim VS08 Pro
2.876 Beiträge
 
#8

Re: [C#] Dies ist keine Variable?

  Alt 8. Aug 2009, 14:15
Wegen solcher Probleme gibt es eine grundlegende Übereinkunft unter .Net-Programmierern: mutable value types are evil. Wenn man Mutable Structs einfach ganz aus dem Gedächtnis streicht, dann verschwindet fast jeder Unterschied zwischen Structs und Klassen und all die damit verbundenen Probleme. Ja, dann kann man Structs überhaupt erst einmal ausblenden und sollte sich wirklich erst bei der Performance-Messung fragen, ob eine Immutable Class als Value Type nicht doch noch ein paar ms rausholen könnte.

Aber solange die Allokationen nicht stören (messen, messen, messen !), ist eine ganz normale Mutable Class natürlich auch eine Lösung .
Sebastian
Moderator in der EE
  Mit Zitat antworten Zitat
Medium

Registriert seit: 23. Jan 2008
3.686 Beiträge
 
Delphi 2007 Enterprise
 
#9

Re: [C#] Dies ist keine Variable?

  Alt 8. Aug 2009, 15:11
Das trifft die Sache ganz prima . Da werd ich dann doch wohl als nächstes mal meine diversen Structs wegfegen, da mir das wie ich bemerkt habe noch an anderen Stellen ganz erheblich was erleichtern könnte.

Nur zur Rückversicherung: Wenn ich eine Liste mit einem Klassentyp statt eines Structs typisiere, dann liefert mir der Zugriff darauf tatsächlich immer Referenzen, keine Kopien?
"When one person suffers from a delusion, it is called insanity. When a million people suffer from a delusion, it is called religion." (Richard Dawkins)
  Mit Zitat antworten Zitat
Benutzerbild von Khabarakh
Khabarakh

Registriert seit: 18. Aug 2004
Ort: Brackenheim VS08 Pro
2.876 Beiträge
 
#10

Re: [C#] Dies ist keine Variable?

  Alt 8. Aug 2009, 17:29
Jupp, die Identität einer Instanz, das wichtigste Merkmal von Klassen, bleibt immer bewahrt. Brechen könntest du sie höchstens von Innen heraus durch Object.MemberwiseClone (protected) oder natürlich durch Reflection.
Sebastian
Moderator in der EE
  Mit Zitat antworten Zitat
Antwort Antwort
Seite 1 von 2  1 2      


Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 09:57 Uhr.
Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz