Entwickler-Ecke

C# - Die Sprache - Gliederung von Properties/Feldern?


habichthugo - Fr 21.07.17 09:42
Titel: Gliederung von Properties/Feldern?
Hallo Zusammen,

ich habe immer wieder das Problem, in Klassen Properties/Felder zu gliedern/gruppieren. In C++ ging das ja ganz einfach z.B. so

C++-Quelltext
1:
2:
3:
4:
5:
class Motor {
  struct {
    ...
  } Parameter;
}

Pendant in C#?

C#-Quelltext
1:
2:
3:
4:
5:
6:
class Motor {
  class ParameterSet {
    ...
  };
  ParameterSet Parameter = new ParameterSet();
}

Daran stört mich alleine schon das (unnötige) Bezeichnungsproblem zwischen Klasse und einziger Instanz...


Th69 - Fr 21.07.17 09:59

Hallo und :welcome:

du kannst in C# den Klassennamen und die Instanz gleich benennen (in C++ ist der Strukturname in deinem Beispiel anonym):

C#-Quelltext
1:
2:
3:
4:
5:
6:
class Motor {
  class Parameter {
    ...
  };
  Parameter Parameter = new Parameter();
}


habichthugo - Fr 21.07.17 12:47

Nein, genau das geht leider nicht (Visual Studio 2015 bzw. .Net 4.7). Wenn, dann nur so

C#-Quelltext
1:
2:
3:
4:
5:
6:
class Parameter {
  ...
};
class Motor {
  Parameter Parameter = new Parameter();
}

aber dann ist nicht mehr klar, dass Parameter nur für Motor da ist (Parameter anderer Ausprägung bracht es in andere Klassen).

Moderiert von user profile iconTh69: Vollzitat entfernt.


Th69 - Fr 21.07.17 13:18

Ups, ja, du hast Recht:
Zitat:
error CS0102: The type `Motor' already contains a definition for `Parameter'

Wenn du wirklich so eine Unterklasse benötigst (was man in den meisten C#-Programmen eher selten einsetzt), dann mußt du diesen doch mit einem Prä- oder Postfix versehen ("_Parameter", "M_Parameter", "MotorParameter" oder eben dein verwendetes "ParameterSet"), damit du noch zusätzlich den Member "Parameter" benutzen kannst.

Die Kürze in C++ erkauft man sich aber auch durch den Nachteil, daß man z.B. keine Kopie davon anlegen kann, da man keine (lokale) Variable von dieser anonymen Struktur erstellen kann.
Selbst wenn man dann

C++-Quelltext
1:
2:
3:
4:
class Motor {
  struct Parameter {
  } Parameter;
};

schreiben würde, so müßte man beim Zugriff auf die Struktur explizit struct Motor::Parameter schreiben.
s.a. Ideone-Beispielcode [http://ideone.com/hS2Ra1].

Das wichtigste beim Code ist ja, daß er möglichst leserlich ist (und nicht, daß er möglichst kurz ist oder man überall dieselben Namen verwendet).


C# - Fr 21.07.17 13:31

user profile iconTh69 hat folgendes geschrieben Zum zitierten Posting springen:
daß man z.B. keine Kopie davon anlegen kann, da man keine (lokale) Variable von dieser anonymen Struktur erstellen kann.

http://ideone.com/HpQzRf


Th69 - Fr 21.07.17 14:46

OK, in C++98 geht dies (noch) nicht.


habichthugo - Fr 21.07.17 20:49

Ich brauche keine Kopie oder weitere Instanz. Es geht - wie gesagt - nur um eine vernünftige Gliederung der Properties, bei sehr großem Umfang selbiger. Aber ok, ist halt so.


C# - Fr 21.07.17 21:36

Naja ich würde es zwar nicht empfehlen aber theoretisch könntest du mit ValueTuple arbeiten.

C#-Quelltext
1:
2:
3:
4:
class Motor
{
    public (int Rpm, string Manufacturer, int andSoOn) Parameter {get; set;}
}


Christian S. - Fr 21.07.17 22:47

Ich halte ValueTuple in öffentlichen Membern für kein gutes Design. Nehmen wir an, ich will eine Adresse zurückgeben und mache das mit einer Klasse:


C#-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
public class Address {
    public string Street {get; set;}
    public string City {get; set;}
}
// ...
public class Person {
    public Address GetAddress() {
        /* ... */
    }
}


Alternativ per ValueTuple

C#-Quelltext
1:
2:
3:
4:
5:
public class Person {
    public (string Street, string City) GetAddress() {
        /* ... */
    }
}


Irgendwann später entscheide ich, dass die Adresse auch ein Land enthalten soll. In der ersten Variante erweitere ich die Address-Klasse um eine Property Country. Da ich nur erweitere, funktioniert Code, der meine GetAddress-Methode benutzt hat, problemlos weiter, ohne Ändeurngen.

Bei der ValueTuple-Variante sieht das anders aus. Will ich die erweitern, sieht das so aus:

C#-Quelltext
1:
2:
3:
4:
5:
public class Person {
    public (string Street, string City, string Country) GetAddress() {
        /* ... */
    }
}

Was hier passiert, ist, dass ich einen anderen Typ zurückgebe und damit funktioniert keiner der Codes mehr, der meine GetAddress-Methode benutzt.

Ich würde daher sehr stark empfehlen, ValueTuple ausschließlich für private Member zu benutzen.