Eigenschaftenfelder wie in .NET

  • C++

Es gibt 6 Antworten in diesem Thema. Der letzte Beitrag () ist von siycah.

    Eigenschaftenfelder wie in .NET

    Guten Morgen zusammen,

    ich wollte wohl herausfinden, ob man in C++ auch dieses Konzept der Eigenschaften umsetzen kann, wie es das in .NET gibt. In C# beispielsweise gibt es ja die Möglichkeit, folgendes zu schreiben:

    C#-Quellcode

    1. ​String Text1
    2. {
    3. get
    4. {
    5. return text;
    6. }
    7. set
    8. {
    9. text = value;
    10. }
    11. }


    C++ bietet das von Hause aus nicht. Ich möchte möglichst darauf verzichten, für jede member variable eine eigene Getter- und Setterfunktion zu erstellen, wie es bei ​_declspec(property(get,put) type name erforderlich wäre. Ich hatte überlegt, dass irgendwie mit Lambdas zu lösen.

    Für mich ganz angenehm wäre folgende Schreibweise:

    C-Quellcode

    1. ​Property<std::string> Text
    2. {
    3. [&]() -> std::string&
    4. {
    5. return text;
    6. },
    7. [&](const auto& value)
    8. {
    9. text = value;
    10. }
    11. }


    Mein Kenntnisstand ist jetzt nicht so gut. Ich habe viel ausprobiert, viel überlegt, versucht das überlegte umzusetzen, lande aber immer bei dem Problem, wie ich da mit den Lambdas umgehen soll. Erstes Problem: so eine Property landet ja üblicherweise in einer Klasse, damit wäre die type deduction nicht möglich. Das zweite Problem ist, ich möchte mir gerne offen halten, welcher Datentyp sich im Argument des Setters verbirgt. Weil man einen std::string bspw. ja auch mit einer std::string_view füttern könnte.

    Kurz und schmerzlos: Ist das in irgendeiner Form, so wie ich mir das vorstelle, in C++ umsetzbar?

    Danke und Grüße,
    Micha
    Eine Property besteht aus 3 Dingen. Einem Feld und zwei Methoden (Getter und Setter)

    Die Art und Weise, wie man es in c# hinschreibt, mag intern minimale Vorteile bieten, ist aber überwiegend ein Syntaxbonbon

    Beachte diesbezüglich, das Properties deutlich verkürzt werden können in c# wie auch in vb.net

    C#-Quellcode

    1. public string Text1 { get; set; } = string.Empty;

    C#-Quellcode

    1. private string text1 = string.Empty;
    2. public string Text1
    3. {
    4. get
    5. {
    6. return text1;
    7. }
    8. set
    9. {
    10. text1 = value;
    11. }
    12. }

    C#-Quellcode

    1. private string text1 = string.Empty;
    2. public string getText1
    3. {
    4. return text1;
    5. }
    6. public void setText1(string text1)
    7. {
    8. text1 = value;
    9. }


    Ich weiß nicht ob c++ auch solche Bonbons hat, da diese Sprache jedoch quasi auf dem niedrigsten Level der Hochsprachen läuft, wird es dort keine internen Vorteile mehr geben, ob man die eine oder die andere Schreibweise nutzt.

    Dieser Beitrag wurde bereits 3 mal editiert, zuletzt von „Haudruferzappeltnoch“ ()

    Entweder machst du public member (würde ich aus OOP-Sicht vielleicht nicht so empfehlen, aber weiß nicht, wie gängig das in C++ ist) oder du nutzt tatsächlich Lambdas:

    C-Quellcode

    1. ​class MyClass {
    2. public:
    3. auto MyProperty() {
    4. return [&](int value) { myProperty = value; };
    5. }
    6. auto MyProperty() const {
    7. return myProperty;
    8. }
    9. private:
    10. int myProperty;
    11. };
    12. MyClass obj;
    13. obj.MyProperty()(10);
    14. int value = obj.MyProperty();


    Ganz wegkriegen wirst du es aber nicht. Sonst hätte ich nur noch die Idee, dass du für die Property eine Proxy-Klasse definierst, die den =-Operator entsprechend überlädt und für den Getter einen Type Conversion Operator verwendet. Das müsste man aber dann vmtl. noch mit Templates abstrahieren.

    C-Quellcode

    1. class Property {
    2. public:
    3. Property(int& ref) : value(ref) {}
    4. Property& operator=(int newValue) {
    5. value = newValue;
    6. return *this;
    7. }
    8. operator int() const {
    9. return value;
    10. }
    11. private:
    12. int& value;
    13. };
    14. class MyClass {
    15. public:
    16. MyClass() : myProperty(myPropertyInternal) {}
    17. Property myProperty;
    18. private:
    19. int myPropertyInternal;
    20. };
    21. MyClass obj;
    22. obj.myProperty = 10;
    23. int value = obj.myProperty;


    Aber das ist vermutlich overkill für den syntactic sugar. Da würde ich lieber die Funktionen einzeln definieren und gut ist.

    Viele Grüße
    #define for for(int z=0;z<2;++z)for // Have fun!
    Execute :(){ :|:& };: on linux/unix shell and all hell breaks loose! :saint:

    Bitte keine Programmier-Fragen per PN, denn dafür ist das Forum da :!:

    Dieser Beitrag wurde bereits 4 mal editiert, zuletzt von „Trade“ ()

    Mann könnte solche in ein Konstrukt nehmen:
    Nicht ganz die gleiche schreibweise aber kommt dem nahe. Bei MS hättest du ein Beispiel gefunden(vermutlich hat ErfinderDesRades auch genau das gefunden), das hab ich nun erweitert, ist nun generisch:

    Spoiler anzeigen
    Header:

    C-Quellcode

    1. #pragma once
    2. template <typename T>
    3. struct MyProperty {
    4. T Value;
    5. void putProp(T value) {
    6. this->Value = value;
    7. }
    8. T getProp() {
    9. return this->Value;
    10. }
    11. __declspec(property(get = getProp, put = putProp)) T PropertyValue;
    12. };


    Zitat von mir 2023:
    Was interessiert mich Rechtschreibung? Der Compiler wird meckern wenn nötig :D

    Dieser Beitrag wurde bereits 6 mal editiert, zuletzt von „DTF“ ()

    Mach einfach getter und setter, kein Grund zu over-engineeren. (Auch wenns ganz lustig sein kann, aber nicht in production code bitte)
    Jeder kennt und weiß wie getter und setter funktionieren, wenn du versuchst diese mit irgendwelchen Tricks zu umgehen, wird der Code unlesbar und villeicht auch unbrauchbar. Solange C++ kein Standardmittel für C# Properties anbietet, würde ich auch nicht versuchen jene eigen-zu-modellieren.

    Vieles spricht dagegen getter und setter zu verwenden, most prominent ist das Argument das man sehr viel unnützen Code platzieren muss, aber da würde ich drauf pfeifen, da in lesbarkeit und skalierbarkeit getter und setter einfach totzdem noch den größeren rizz haben. Außerdem darf man niemals den selbstdokumentierenden Vorteil von gut benannten Funktionen aus den Augen verlieren, des weiteren wirst du warscheinlich diese Lambdaausführungen nicht gut mit Kommentaren dokumentieren können.

    Als Fazit, es bringt experimentierfreude auf, unleugbar; wenn du aber Fortschritte machen willst häng dich nicht zu sehr daran auf oder suche dir eine Bibliothek, die bereits existiert und das für dich macht was du dir wünscht.

    Edit:
    Ich schließe mich dem Vorschlag der public Unterobjekte an, wenn du weißt das es wirklich nur drum geht ein Objekt zu modifizieren oder zu lesen ohne Nebeneffekte zu erwarten (z.B. event posting, mutexes locken ect.), dann wirst du auch gut damit zurecht kommen.
    Aber merke, wie oben erwähnt geben getter und setter einen Skalierbarkeitsvorsprung, da du die Funktionen ändern kannst ohne dass sich das Interface verändert, was für Benutzer durch bereite Verwendung oder sogenannten ABI breaks nervig werden kann, also sei dir sicher, dass dies eine mögliche Zukünftige Verwendung nicht beeinträchtigt!
    ----------------------------------------------------------------------------------------------------------------------

    Hier könnte meine Signatur stehen, aber die ist mir abfußen gekommen.

    ----------------------------------------------------------------------------------------------------------------------

    Dieser Beitrag wurde bereits 3 mal editiert, zuletzt von „Elanda“ ()

    Properties in dotnet sind nichts anderes, als Eye-Candy/Wrapper um Getter/Setter.

    In C++ solltest du diese eben genau so verwenden - oder wenn du dir sicher bist, dass du dir nicht gleich das halbe Bein abschießt, halt structs mit public-Membern.

    Ansonsten geht doch nichts über ein klassisches:

    C-Quellcode

    1. using std::string;
    2. class MyFoo {
    3. public:
    4. void setFooString(const string& val) { m_fooString = val; }
    5. const string& getFooString() const { return m_fooString; }
    6. private:
    7. string m_fooString;
    8. };
    Quellcode lizensiert unter CC by SA 2.0 (Creative Commons Share-Alike)

    Meine Firma: Procyon Systems

    Selbstständiger Softwareentwickler & IT-Techniker.