Jump to content
Unity Insider Forum

Kann man ein Array-Element mit get/set belegen?


Kokujou

Recommended Posts

Yo! ich will erreichen dass eine Funktion aufgerufen wird wenn das hier passiert:

array = x;

 

Ich habe schon gelesen dass man dafür eine Klasse macht a la:

class X
{
  public int this[int i] { get; set};
}

Ich will dasselbe nur eben nicht für eine Klasse sondern für ein int-Array

 

PS: Es soll für ein Zweidimensionales Array sein...

Link zu diesem Kommentar
Auf anderen Seiten teilen

Du könntest der Klasse eine Get und Set Funktion spendieren und dann array.Set(255) oder array.Get()

 

X[] array = new X[10];

public class X
{
  int i = -1;
  public void Set(int i)
  {
  this.i = i;
  }
  public int Get()
  {
  return i;
  }
}

 

Edit: Also eigentlich ist das ja fast das selbe wie du es vorgeschlagen hast :rolleyes:

Link zu diesem Kommentar
Auf anderen Seiten teilen

Du könntest der Klasse eine Get und Set Funktion spendieren und dann array.Set(255) oder array.Get()

 

X[] array = new X[10];

public class X
{
  int i = -1;
  public void Set(int i)
  {
  this.i = i;
  }
  public int Get()
  {
  return i;
  }
}

 

Das problem ist... wie setze ich das für ein zweidimensionales Array um. Das ist sehr unübersichtlich und sehr frustrierend. ich versuche es nämlich gerade. gibt es das nicht in einfach? Am liebsten wäre mir sowas wie:

int[][] array {get{} set{}};

Link zu diesem Kommentar
Auf anderen Seiten teilen

X[][] array = new X[10,10]

array[0,5].Set(24);
array[4,8].Set(33);

Debug.Log(array[0,5].Get());

 

So klappt das doch :)

 

Mhmm also doch so hm?

Naja es ist so auf diese weise umss ich jetzt etwa 100 zeilen code umschreiben XD

hätte ich die interne Set-Funktion benutzt wäre sie automatisch aufgerufen worden ohne dass ich was umschreiben muss.

Link zu diesem Kommentar
Auf anderen Seiten teilen

Naja warum?

Ich meine ein Array ist ja auch nur eine Klasse. Man muss da also nur irgendwie den int-Elementen die get/set-Parametern hinzufügen.

Aber das geht wohl nicht. Und bevor ich jetzt ein 50 Zeilen Code schreibe um eine Klasse für ein 2Dimensionales int_Feld zu schreiben kann ich wohl auch gleich den Code umschreiben XD schade.

 

ich meine:

public int this[int i]{ get; set}

funktioniert doch auch. warum dann nicht sowas wie

public int this[int i][int j] { get; set }

?

Link zu diesem Kommentar
Auf anderen Seiten teilen

Nunja ich finde es ist ein ganz guter stil.

Ich hab mal versucht das ganze so zu machen dass ich eine Klasse anlege die ein 2D Array verkörpert darin eine Klasse für 1D Arrays und darin dann den [] Operator redefiniere um get/set Eigenschaften anzuhängen.

 

Aber ich denke wir sind uns alle Einig das das völliger Nonsens und ineffizient wäre.

 

Der Sinn dahinter war einfach... Ich habe in Visual Studio ein Projekt geschrieben weil es ohne grafik einfach schneller zu testen geht :) Den Grafik-Teil habe ich währenddessen in Unity fertig gemacht. Jetzt habe ich beide Teile zusammengeschmissen udn habe entdeckt dass mir ein Event fehlt. Und jetzt muss ich 1000 Codezeilen umschreiben um das was ich hier suche da reinzukriegen ^^ und das ist etwas mühselig darum dachte ich vielleicht gibts da ja was :)

Link zu diesem Kommentar
Auf anderen Seiten teilen

Ich habe den Thread jetzt erst gesehen und bin komplett verwirrt, was du da haben willst. Was haben Properties (get; set;) damit zu tun?

Wenn du eine Funktion haben willst die ein Feld eines Arrays beschreibt, dann schreib' doch genau das...?

void Foo(int x, int y, int value)
{
 array[x, y] = value;
}

Aber da dein Array sowieso public ist, wozu brauchst du überhaupt noch eine Funktion drumherum?

Link zu diesem Kommentar
Auf anderen Seiten teilen

Aber da dein Array sowieso public ist, wozu brauchst du überhaupt noch eine Funktion drumherum?

Yo! ich will erreichen dass eine Funktion aufgerufen wird wenn das hier passiert:

array = x;

Ich denke da soll eine andere Funktion als ein Setter aufgerufen werden, also in der Art "immer wenn ein Wert gesetzt/aktualisiert wurde, mache zusätzlich XY". Richtig? ^^

 

Naja es ist so auf diese weise umss ich jetzt etwa 100 zeilen code umschreiben XD

Lieber 5 Minuten vergeuden und 100 Zeilen umschreiben (ist ja whs ohnehin nur copy-paste?) als da mit so Gehacke anzufangen und den Code zu verwurschteln ^^

Link zu diesem Kommentar
Auf anderen Seiten teilen

Ich denke da soll eine andere Funktion als ein Setter aufgerufen werden, also in der Art "immer wenn ein Wert gesetzt/aktualisiert wurde, mache zusätzlich XY". Richtig? ^^

 

 

Lieber 5 Minuten vergeuden und 100 Zeilen umschreiben (ist ja whs ohnehin nur copy-paste?) als da mit so Gehacke anzufangen und den Code zu verwurschteln ^^

 

Ja genau so meinte ich das. so wie man bei Windows Forms ein Event aufruft wenn man irgendwo draufklickt oder sich der Wert einer Textbox verändert.

 

Und Prinzipiell hast du recht ich hatte nur gehofft das ist ne gelegenheit um gleich etwas Neues zu lernen und ganz ehrlich mit meiner Variante wäre der code 100mal schöner gewesen als wenn ich nach jedem Auslöser jedes mal

DoSomething();

einfüge.

Link zu diesem Kommentar
Auf anderen Seiten teilen

Ach, du willst Seiteneffekte!

Sag das doch! :D

 

Dafür sind Propertys natürlich keine ganz schlechte Idee. Ob man sie oder Methoden benutzt, ist semantische Geschmackssache.

Propertys gibt es in verschiedenen Ausführungen, je nach dem, was man da schreibt. Sie sind von der Stelligkeit mit Feldern und Methoden auf einer Ebene.

Die simpelste Form ist diese Form:

private int number{ get; set; }

Man beachte: Kein Semikolon nach der geschweiften Klammer, genau wie bei Methoden.

Dieser Code erzeugt implizit eine Variable, in die geschrieben und aus der gelesen wird. Er ist damit in den meisten Fällen äquivalent zu

private int number;

Ich habe schon Code gesehen, in denen alles voll war mit der obigen Form, anstatt einfach Variablen zu deklarieren.

Finde ich ein wenig bescheuert, auch wenn es die Konsistenz im Code wohl erhöht.

 

Diese Form kann man noch etwas ausweiten, und zwar mit Sichtbarkeitsmodifikatoren:

public int number { private set; get; }

Man kann number jetzt public auslesen, aber das Schreiben ist private. Dass diese Variante sehr praktisch sein kann, muss ich wohl nicht sagen ;)

 

Man kann get und set aber auch Rümpfe geben:

public int number
{
 get { return 0; }
 set { }
}

Wann immer lesend auf die Property zugegriffen wird, wird get ausgeführt. Der Code im get-Rumpf muss einen Wert vom Typ der Property (also int) zurück geben, der dann beim Lesen rauskommt.

Wird schreibend zugegriffen, wird set ausgeführt. In set gibt es das besondere Wort "value", das den Eingangswert enthält.

 

Dieser Code:

private int _number;
public int number
{
 get { return _number; }
 set { _number = value; }
}

Ist damit äquivalent zu

private int number{ get; set; }

und _number ersetzt das unsichtbare Feld, das der Compiler erzeugt.

Es gehen dann auch so feine Sachen wie

[serializeField]
private int _number;
public int number { get { return _number; } }

mit nur get oder set.

 

Man sieht bei der Benutzung, dass Propertys damit quasi faken, eine Variable zu sein, allerdings beim Zugriff der get- oder set-Code ausgeführt wird.

Warum diese ganze Erklärung? Damit klar wird, dass eine Property mit einem Array als Typ einfach nur faked, eine Array-Variable zu sein.

Der set-Code wird also ausgeführt bei

meinArray = new int[5,5];

aber nicht bei

meinArray[1, 2] = 42;

Stattdessen wird hier der get-Code ausgeführt, der das Array zurück gibt, und dann wird davon das Element rausgesucht.

 

Arrays sind halt besondere Objekte, daher ist das Vergleichbar mit einer Objekttyp-Property:

private Car _ownedCar;
public Car ownedCar
{
 get { return _ownedCar; }
 set
 {
_ownedCar= value;
_ownedCar.SetOwner(this); // Seiteneffekt!
 }
}

Wenn man dann folgendes tut:

someone.ownedCar.Drive();

Dann wird lesend auf ownedCar zugegriffen - es wird also get ausgeführt und auf dem Car, das dann zurück kommt, wird Drive aufgerufen.

Und ein Array-Zugriff ist wie ein Methodenaufruf. Erst wird das Array zurückgegeben, dann wird darauf zugegriffen.

 

Deshalb der Vorschlag mit der Klasse. Schreibend zugegriffen wird nämlich auf dem Wert, der dann in dem Array steckt.

Wie schon angedeutet (und jetzt verstehe ich auch endlich die Motivation hinter dem Vorschlag), kannst du z.B. eine Klasse bauen, die Getter und Setter hat. Ich würde stattdessen ein Struct empfehlen, da du hier ints faken willst, und mit einer Klasse holst du dir unnötigerweise Referenzsemantik ins Haus.

 

Würde dann so aussehen:

public struct SideEffectInt
{
private int _number;
public int number
{
	get { return _number; }
	set
	{
		_number = value;
		SideEffect();
	}
}
}

public SideEffectInt[] values;

void Awake()
{
values = new SideEffectInt[10];
}

public void DoAThing()
{
values[0].number = 10;
}

private void SideEffect()
{
Debug.Log("Ayyy Lmao");
}

 

Natürlich ist das nicht genau das, was du wolltest. Statt

values[0].number = 10;

wollen wir

values[0] = 10;

...und auch das ist möglich. Allerdings helfen dir dabei Propertys nicht; du brauchst implizite Casts.

 

Das funktioniert folgendermaßen:

public struct SideEffectInt
{
	private int _number;
	public static implicit operator int(SideEffectInt sei)
	{
		return sei._number;
	}
	public static implicit operator SideEffectInt(int i)
	{
		SideEffect();
		return new SideEffectInt { _number = i };
	}
}

Da die Dinger statisch sind, muss SideEffect() jetzt auch statisch sein.

Mit impliziten Casts kannst du jetzt sowas schreiben:

SideEffectInt number = 10; // Wird SideEffect() auslösen
int i = number;

oder eben, mit deinem Array

values[0] = 10;

Link zu diesem Kommentar
Auf anderen Seiten teilen

Archiviert

Dieses Thema ist jetzt archiviert und für weitere Antworten gesperrt.

×
×
  • Neu erstellen...