Willkommen auf myCSharp.de! Anmelden | kostenlos registrieren
 | Suche | FAQ

Hauptmenü
myCSharp.de
» Startseite
» Forum
» Suche
» Regeln
» Wie poste ich richtig?

Mitglieder
» Liste / Suche
» Wer ist online?

Ressourcen
» FAQ
» Artikel
» C#-Snippets
» Jobbörse
» Microsoft Docs

Team
» Kontakt
» Cookies
» Spenden
» Datenschutz
» Impressum

  • »
  • Community
  • |
  • Diskussionsforum
Records vs. Class für Models/DTOs
Duesmannr
myCSharp.de - Member



Dabei seit:
Beiträge: 151
Herkunft: Münster

Themenstarter:

Records vs. Class für Models/DTOs

beantworten | zitieren | melden

Nabend,

ich schreibe mir gerade eine Library mit .NET 6 um entspannter mit einer API zu kommunizieren.
Dahingehend, erstelle ich für jede Response, explizite Klassen/Records, damit ich die direkt typisieren kann.

Bin noch nicht ganz auf den grünen Zweig mit Records gekommen.
Bei meiner Recherche, bin ich auch auf die Top Antwort von dem Stackoverflow Eintrag gestoßen.

Also habe ich meine Models/DTOs als Records definiert.

Funktioniert auch soweit so gut. Nur ist mir dann ein Problem aufgefallen.

Ich habe als Beispiel diesen Record:


public record CreateSessionRequest([property: JsonPropertyName("request_token")] string RequestToken);

Den Record nutze ich bspw. für ein Request.

Für ein zweiten Request brauche ich zu der genannten Property aber auch noch Username und Password. Also Vererbung. Um auch weniger schreiben zu müssen, aber auch die Übersichtlichkeit zu behalten.

Also ein 2. Record, der den oberen Record erbt.


//Ohne Vererbung
public record CreateSessionWithCredentialsRequest(
        [property: JsonPropertyName("username")] string Username,
        [property: JsonPropertyName("password")] string Password
        );

//Mit Vererbung
public record CreateSessionWithCredentialsRequest(
        [property: JsonPropertyName("username")] string Username,
        [property: JsonPropertyName("password")] string Password
        ) : CreateSessionRequest(); //Hier in den Klammern muss die Property RequestToken angegeben werden

Wie im Kommentar erwähnt, kommt hier meine Frage?/Problem auf.
Ich müsste dem 2. Record ebenfalls eine Property 'RequestToken' hinzufügen, damit ich den Wert zum Basis Record übergeben kann.

Das ist jetzt eine Property. Aber ich habe auch Fälle, da sind es gleich mal 20 Properties und da lohnt sich die Vererbung halt nicht, wenn ich jede Property neu definieren muss.

Ich könnte den Record jetzt genau so definieren, wie eine Klasse, weil ich dann einen parameterlosen Konstruktor habe, aber damit entfällt zB. auch die Funktionalität des Deconstructs (sinnig oder nicht, sei dahingestellt).

Und da stelle ich mir die Frage, macht ein Record überhaupt Sinn?
Da kann ich auch gleich normale Klassen verwenden. Und dahingehend, fällt mir dann auch kein Beispiel ein, wann ich denn Records nutzen soll.
Sie sind immutable und reichen Werte weiter. Aber sobald man mit Vererbung arbeiten möchte, würde nach meinem jetzigen Kenntnisstand, Records wegfallen, weil man eben die Properties alle neu definieren muss.

Ich freue mich auf auf Ideen, womit ich das besser verstehen kann oder auch, wenn ich etwas übersehe.

Schönen Abend noch!
private Nachricht | Beiträge des Benutzers
Palladin007
myCSharp.de - Member

Avatar #avatar-4140.png


Dabei seit:
Beiträge: 1545
Herkunft: Düsseldorf

beantworten | zitieren | melden

Die Frage, die ich mir stelle:

Brauchst Du Vererbung, oder willst Du dir nur Schreibarbeit ersparen?
Überleg dir gut, ob Du Vererbung nutzen willst, denn nachträglich wieder raus nehmen, kann sehr anstrengend werden.
Oder Du hast schnell einiges an zusätzlicher Komplexität, wenn die Daten größtenteils gleich sind, sich dann aber doch irgendein Detail unterscheidet.

Ersparen von Schreibarbeit ist mMn. nur dann ein Grund, wenn der gesamte Quellcode nicht mit der Basisklasse, sondern einem Interface arbeitet - also eine Art Default-Basis-Implementierung.
Bei den Records sieht die Vererbung eher danach aus, dass das Ziel "echte" Vererbung ist, also um auch die Konzepte zu nutzen und nicht nur um Schreibarbeit zu sparen.

Mir ist aber auch keine Möglichkeit bekannt, außer alles nochmal anzugeben.
Vermutlich geht das auch gewollt, denn bei manchen Funktionen ist ja auch die Reihenfolge der Werte wichtig.

Du könntest natürlich auch einfach normale Klassen nutzen - brauchst Du denn überhaupt das, was bei den Records generiert wird?
Was genau das ist, kannst Du dir mit einem Decompiler oder https://sharplab.io/ anschauen.
private Nachricht | Beiträge des Benutzers
Briefkasten
myCSharp.de - Member

Avatar #avatar-1523.gif


Dabei seit:
Beiträge: 445

beantworten | zitieren | melden

Du meinst sowas oder?


public record CreateSessionWithCredentialsRequest : CreateSessionRequest
{
    public CreateSessionWithCredentialsRequest(string username, string password, string RequestToken) 
        : base(RequestToken)
    {
        Username = username;
        Password = password;
    }

    public string Username { get; set; }
    public string Password { get; set; }
}

und in kurz


public record CreateSessionRequest(string RequestToken);

public record CreateSessionWithCredentialsRequest(string RequestToken, string Username, string Password) : CreateSessionRequest(RequestToken);
PS: Ich habe C# LangVersion 9.0 aktiviert.

Beim record hast du im Unterschied zur normalen Klasse folgendes:
Zitat
An override of Object.Equals(Object).
A virtual Equals method whose parameter is the record type.
An override of Object.GetHashCode().
Methods for operator == and operator !=.
Record types implement System.IEquatable<T>.
Quelle: https://docs.microsoft.com/en-us/dotnet/csharp/whats-new/tutorials/records#characteristics-of-records
Schaut mal im IRC vorbei:
Server: https://libera.chat/ ##chsarp
private Nachricht | Beiträge des Benutzers
Abt
myCSharp.de - Team

Avatar #avatar-4119.png


Dabei seit:
Beiträge: 16224

beantworten | zitieren | melden

Zitat
Ich müsste dem 2. Record ebenfalls eine Property 'RequestToken' hinzufügen, damit ich den Wert zum Basis Record übergeben kann.
Auch Klassen-Konstruktoren brauchen eine Doppeldeklaration in so einem Fall.
Daher ja: musste doppelt deklarieren.
Zitat
Aber ich habe auch Fälle, da sind es gleich mal 20 Properties und da lohnt sich die Vererbung halt nicht, wenn ich jede Property neu definieren muss.
Das ist in jeder anderen Schreibweise derzeit ebenfalls explizit notwendig.
Zitat
Und da stelle ich mir die Frage, macht ein Record überhaupt Sinn?
Ja, in den Fällen, in den die Schreiberleichtung sinn macht - und das ist nicht überall der Fall.
Zitat
Aber sobald man mit Vererbung arbeiten möchte, würde nach meinem jetzigen Kenntnisstand, Records wegfallen, weil man eben die Properties alle neu definieren muss.
Ja und nein; kommt drauf an.
- performance is a feature -

Microsoft MVP - @Website - @blog - @AzureStuttgart - github.com/BenjaminAbt
private Nachricht | Beiträge des Benutzers