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
Wie kann ich eine Klasse festlegen, der erst zur Laufzeit feststeht?
GeneVorph
myCSharp.de - Member



Dabei seit:
Beiträge: 166

Themenstarter:

Wie kann ich eine Klasse festlegen, der erst zur Laufzeit feststeht?

beantworten | zitieren | melden

Hallo,

beim Frickeln habe ich ein Problem entdeckt, dessen Lösung mir gerade einiges Kopfzerbrechen bereitet. Alleine schon ein anschauliches Beispiel zu finden mit einem praktischen Bezug ist nicht so einfach - mal wieder taugt aber ein Schul-Besipiel.

Es existiert nur Pseudo-Code; ich suche nicht nach konkretem Code, eher einem Konzept, einer Roadmap sozusagen.

Folgendes Szenario: stellt euch eine Schule vor. Es gibt (Schul-)Klassen und Schüler. Jeder Schüler bekommt Noten.

Das könnte also so aussehen:


public class SClass
{
     List<Student> Students {get;set;}
}

public class Student
{
     List<Grading> Grades {get;set;}
}

Wie euch sicher aufgefallen ist, habe ich die Klasse Grading (Bewertung) weggelassen, denn sie stellt den Kern des Problems dar.
Es gibt nämlich Bewertungen rein in Ziffernform (Grundschule ab Kl.3, Sekundarstufe) und rein verbale Bewertungen (z. B. Förderschüler - nicht alle, aber bestimmte Gruppen).

Ich brauche also zwei bestimmte Bewertungs-Klassen:


public class RegularGrading
{
     //Regelschulbewertung
     public string GradeWord {get;set;}
     public string Grade {get;set;}
}

public class SpecialGrading
{
     //Förderschulbewertung
     public string VerbalGrade {get;set;}
}

Der Typ der Bewertung hängt ab vom Schülertyp (Regel-/Förderschüler).
Meine Idee war, dass die Bewertung ein generischer Typ ist. Dann würde das so aussehen:


public class Student<T>
{
     List<T> Grades {get;set;}   
}

Da kein Schüler-Objekt (im späteren Code) erstellt werden kann, ohne dass der Schülertyp festgelegt wurde, wäre das eigentlich schon die Lösung, es bräuchte lediglich


     Student<RegularGrading> NewStudent = new Student<RegularGrading>();
und die Sache wäre geritzt. Zwar müssten bei Zuweisungen im Code vorher immer noch mal der Typ geprüft werden (typeOf()), aber das wäre zu verschmerzen.
Das große Problem, das sich abzeichnet ist folgendes: die Schulklasse enthält eine Liste mit Schüler-Objekten. Diese sind nun aber generische Klassen, was wiederum bedeutet, dass auch die Schulklasse einen generischen Typ <T> bereithalten muss:


public class SClass<T>
{
     List<Student<T>> Students {get;set;}
}
Damit erklärt sich das Problem womöglich von selbst: ich kann nun keine Schulklassen mehr instanziieren, ohne explizit den Typ der Bewertung für Student angeben zu müssen. Das kann ich aber gar nicht, weil es
a) zum Zeitpunkt der Klassenerstellung noch gar keine Schüler geben kann (zuerst braucht man eine Schulklasse, und dann Schüler, die ihr zugeteilt werden können) und
b) jeder Schüler nur eines von zwei möglichen Bewertungsschemata haben kann.

Da es keine generischen Properties gibt, muss ich hier einen anderen Weg einschlagen - spontan fiel mir nur ein, statt das Grading generisch zu halten, vielleicht einfach eine List<object> in den Grading-Klassen anzulegen. Prinzipiell natürlich eine Lösung, hat jedoch zwei Schönheitsfehler:
a) jede Menge boxing und unboxing im Code
b)


//Gradings unter der Annahme, dass die Notenlisten den Typ <object> entgegennehmen:
RegularGrading g = new RegularGrading();
SpecialGrading s = new SpecialGrading();

MyStudent.Grades.Add(g);
MyStudent.Grades.Add(s); //da die Liste Items vom Typ object entgegennimmt funktioniert das zwar, kann aber zu Fehlern führen, da ein Schüler stets nur 1 einem Bewertungsschema zugeordnet werden kann.

Wie könnte ich dieses Problem angehen? Müsste ich konzeptuell etwas verändern?

Gruß
Vorph




private Nachricht | Beiträge des Benutzers
Palladin007
myCSharp.de - Member

Avatar #avatar-4140.png


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

beantworten | zitieren | melden

Zitat
jede Menge boxing und unboxing im Code

Das nennt man Casting und nicht Boxing. Boxing bezeichnet das Konvertieren von einem Werttyp in ein Objekt.
Es klingt zwar ähnlich, aber im Hintergrund passieren grundlegend verschiedene Dinge, also nicht verwechseln
Wenn also jemand davon spricht, Boxing sollte man vermeiden, dann meint dieser Jemand vermutlich nur Werttypen.

Und dein Problem:

Du hast einen generellen Knackpunkt bei Generics gefunden - sie ziehen sich überall durch und Du bekommst sie nur schwer wieder weg.
Das kann man zwar mit Reflection umgehen, sollte man aber nicht tun bzw. sowas stinkt meilenweit gegen den Wind nach einem Design-Fehler.

Was Du brauchst, ist eine gemeinsame Basisklasse oder Schnittstelle.
Wie das konkret aussieht, hängt natürlich von den Anforderungen ab. Wenn Du z.B. Noten miteinander vergleichen möchtest, dann könntest Du ein Interface bauen, das eine solche Vergleichsfunktion anbietet und für die Darstellung gibt's eine Methode, die einen Namen ausgibt.

Wenn es um die reinen Daten geht, sieht das etwas anders aus.
OR-Mapper wie EntityFramework können zwar Objektorientierung über die Datenbank simulieren, doch im Wesentlichen schreiben die einfach alle Daten in die Datenbank und laden dann eben nur das, was die konkrete Klasse braucht und lassen den Rest weg - Du hättest also drei Spalten, je nach Konzept etwas anders organisiert.
Besser wäre ein allgemeines System und das würde ich anhand eines Typs (Enum) und anhand eines (oder von zwei) Strings festmachen, die konkrete Implementierung hat dann die Aufgabe, diese Daten zu verstehen und die benötigte Funktionalität anzubieten.

Im Falle von "RegularGrading" sehe ich aber auch keinen Vorteil in den verschiedenen Properties.
Für mich ist das ein konkreter Wert (die Zahl der Note) und eine Methode, die eine Bezeichnung für diese Note bestimmen kann - bei einfachen Noten (1-6) wäre das ein switch oder eine Tabelle.
Die zwei getrennten Properties haben nämlich den Nachteil, dass ihre Zustände voneinander abhängig sind, der Eine funktioniert nicht ohne den Anderen - das birgt Fehlerpotential ohne wirklichen Vorteil. Ich persönlich würde einen simplen Wert (int oder Enum) definieren und erst die UI entscheidet dann, wie diese Note tatsächlich dargestellt wird; das könnte dann auch mit verschiedenen Sprachen umgehen.

Wenn man "GradeWord" weg lässt, sind die beiden Klassen auch gar nicht mehr so verschieden und den konkreten Typ könnte man anhand eines Enums abbilden. Dann brauchst Du auch keine gemeinsame Basisklasse mehr (ein Interface kann aber trotzdem Sinn machen)

Am Ende gibt's also nur ein GradeType-Enum (Regular und Special) und eine Klsse mit zwei Properties GradeType und GradeValue.
Dein ganzes Problem löst sich mit ein bisschen Umdenken also einfach in Luft auf
private Nachricht | Beiträge des Benutzers
GeneVorph
myCSharp.de - Member



Dabei seit:
Beiträge: 166

Themenstarter:

beantworten | zitieren | melden

Hallo Palladin - sorry für die späte Rückantwort! Wo fange ich an? Erstmal vielen Dank für deine Vorschläge und die Richtigstellungen - meine Verwendung des Begriffs 'boxing' war natürlich falsch - und ich wusste es nicht mal

Gestern Abend kam ich dazu ein bisschen zu coden und ich muss sagen: die Idee mit den Interfaces gefällt mir ziemlich gut. Ich weiß nicht, ob ich das alles richtig verstanden habe, aber über's Wochenende dürfte ich etwas ausgiebiger uzm Programmieren kommen und dann werde ich meine Lösung mal hier posten.

Zitat
Wenn man "GradeWord" weg lässt, sind die beiden Klassen auch gar nicht mehr so verschieden [...]

Dein ganzes Problem löst sich mit ein bisschen Umdenken also einfach in Luft auf

Ganz so einfach ist es dann doch nicht Wenn man versucht, die Realität abzubilden, braucht man für ein Regelschulzeugnis zwei Werte: Note als Punktwert mit vorangestellter Null plus Notenname (GradeWord), z. B.: '08' befriedigend.
Wohingegen eine verbale Beurteilung einfach ein Text ist, der Aufschluss über den Entwicklungsstand von Förderschülern in bestimmten Bildungsgängen geben soll, die prinzipiell nicht durch Ziffernnoten beurteilt werden, sozusagen eine Beurteilung im Fließtext. Beides zählt aber als 'Benotung', wenn es auch faktisch zwei verschiedene Dinge sind. So kommt man dann über's Programmieren zu der Erkenntnis, dass das derzeitige Bildungssystem erhebliche Schwachstellen haben muss

OK, wie gesagt, die Lösung werde ich hier noch posten, sobald ich weiß, dass mein Code tut was er soll.

Gruß
Vorph

P.S:
Ich stelle fest, dass meine Überschrift geändert wurde !? Fände ich gut, wenn man da eine automatisierte Info per Mail bekäme - ich habe jetzt erstmal im Forum gesucht und war schon verblüfft, weil ich dachte mein Thread sei weg!
Außerdem: das mit dem Festlegen der Klasse hat sich ja nun eigentlich erst aus dem Lösungsvorschlag von Palladin ergeben - grundsätzlich ging es ja schon erst mal um die Feststellung, dass ein Property da ist, dessen Typ zur Compile-Time noch nicht feststeht. Finde ich sehr verwirrend.

private Nachricht | Beiträge des Benutzers
Palladin007
myCSharp.de - Member

Avatar #avatar-4140.png


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

beantworten | zitieren | melden

Also kann es auch Bewertungen mit dem selben Notenwert, aber unterschiedlichem Notentext geben?
Wenn ja - ok, dann kann man Letzteres natürlich nicht weg lassen.

Zitat
Ich stelle fest, dass meine Überschrift geändert wurde !? Fände ich gut, wenn man da eine automatisierte Info per Mail bekäme

Sprich das doch mal hier an.
Aber erwarte keine super zügige Anpassung, das Forum ist gerade nagelneu entwickelt und die Kinderkrankheiten sind vermutlich erst mal wichtiger.
Außer das ist ein Fehler, aber das muss dann Abt beurteilen.
private Nachricht | Beiträge des Benutzers
JimStark
myCSharp.de - Member

Avatar #dOpLzh7hN1az1g0eGRc0.jpg


Dabei seit:
Beiträge: 225

beantworten | zitieren | melden

Zitat von GeneVorph

Gestern Abend kam ich dazu ein bisschen zu coden und ich muss sagen: die Idee mit den Interfaces gefällt mir ziemlich gut. Ich weiß nicht, ob ich das alles richtig verstanden habe, aber über's Wochenende dürfte ich etwas ausgiebiger uzm Programmieren kommen und dann werde ich meine Lösung mal hier posten.




Ich glaube eine abstrakte Basisklasse wäre da besser zu gebrauchen. Und dann je nach Student-Type einfach casten.



public abstract class Grading
{
    public double Grade {get;set;}
}
public class RegularGrading : Grading
{
     //Regelschulbewertung
     public string GradeWord {get;set;}
}

public class SpecialGrading : Grading
{
     //Förderschulbewertung
     public string VerbalGrade {get;set;}
}

Dieser Beitrag wurde 2 mal editiert, zum letzten Mal von JimStark am .
private Nachricht | Beiträge des Benutzers
FZelle
myCSharp.de - Experte



Dabei seit:
Beiträge: 10065

beantworten | zitieren | melden

Du solltest dir dringend nochmal anschauen, wofür man eine abstrakte Klasse benutzt.

Das was Du hier zeigst ist einfach eine Basisklasse, und das wurde schon erwähnt
private Nachricht | Beiträge des Benutzers
JimStark
myCSharp.de - Member

Avatar #dOpLzh7hN1az1g0eGRc0.jpg


Dabei seit:
Beiträge: 225

beantworten | zitieren | melden

Meinst du jetzt mich?
Er wird niemals den Basistyp erstellen müssen wenn er Regular und Special getrennt definieren will, deswegen abstrakt.
Und lieber Klasse als Interface bei diesem "is-a", vorallem wenn es mal in eine Datenbank soll.

Und ich sehe gerade, Grade ist bei Special nicht dabei, also kann die noch raus aus der Baseclass.
Dieser Beitrag wurde 1 mal editiert, zum letzten Mal von JimStark am .
private Nachricht | Beiträge des Benutzers
GeneVorph
myCSharp.de - Member



Dabei seit:
Beiträge: 166

Themenstarter:

beantworten | zitieren | melden

Danke für den Einwurf bezgl. Basisklasse - ich hatte das kurz in Erwägung gezogen, aber es macht IMHO hier nicht wirklich Sinn, weil die Bewertungen wirklich grundverschieden sind. Ich versuche das nochmal ganz kurz zu skizzieren - ich weiß, die Thematik ist sehr speziell.

Regelschüler = R
Förderschüler = F

Grundsätzlich erhalten beide ein Zeugnis. Bei R sind das Ziffernnoten von 15 bis 00. Bei bestimmten F (z. B. geistige Behinderung) besteht das Zeugnis nur aus einer verbalen Beurteilung - keine Ziffernnoten. Die Krux: an einer Förderschule können Schüler aus verschiedenen Bildungsgängen dieselbe Klasse besuchen, z. B. jemand der den Hauptschulabschluss macht und jemand, der im Bereich geistige Behinderung unterrichtet wird. Formal unterschieden sich die Schülertypen nur in der Bewertung (eine Schülerakte wäre also völlig identisch aufgebaut, würde sich aber in diesem Punkt fundamental unterscheiden).

Daraus ergibt sich, dass ich in meiner App zwei verschiedene Typen Schüler in ein und derselben Klasse unterbringen möchte. Ich hätte gleich zwei Typen von Schülern anlegen können, dabei aber jede Menge Code-Duplikate produziert, was sehr unschön gewesen wäre, da sie sich - formal - nur im Bewertungsteil so substantiell unterscheiden.

Daher bin ich auch von der Basisklasse abgerückt - es gibt in diesem Punkt keinen wirklich gemeinsamen Nenner.
Aber: ich glaube, die Idee von Palladin gestattet mir eine elegante Lösung, die zumindest praktikabel gehandhabt werden kann. Wie gesagt: für diesen Part existiert noch kein konkreter Code, ich kann mich erst übermorgen ausgiebig damit beschäftigen.
Zitat
Und lieber Klasse als Interface bei diesem "is-a", vorallem wenn es mal in eine Datenbank soll.
Könntest dur mir erläutern, wo genau du da Probleme siehst? Ja, später soll es in eine Datenbank (defacto entwickle ich meine DB parallel), aber ich sehe jetzt beim Interface eigentlich nur den Nachteil (wenn man das so nennen will), dass ich mehr Code zu schreiben habe. Ansonsten sehe ich einen Benefit in Sachen Wartbarkeit, Erweiterung und ease-of-use. Bin aber nur Hobby-Coder von daher kann es natürlich gut sein, dass ich offensichtliche Schwachstellen nicht sehe/bedacht habe.

Grüße
vorph
private Nachricht | Beiträge des Benutzers
JimStark
myCSharp.de - Member

Avatar #dOpLzh7hN1az1g0eGRc0.jpg


Dabei seit:
Beiträge: 225

beantworten | zitieren | melden

Ich verstehe das Problem nicht, sie unterscheiden sich in der Bewertung:


public class Student 
{
    public StudentType type {get;set;}
    public List<Grading> Grades {get;set;}
}

Je nach StudentType castest du dann auf SpecialGrading oder RegularGrading. So wurde es oben ja auch schon erwähnt.

Die Baseclass kann dann z.B. enthalten:


public abstract class Grading
{
    public int Id;
    public int StudentId;
    public DateTimeOffset Date;
....
}


also das ganze Zeug das beide gemeinsam haben und du eh für die Datenbank brauchst.

Oder verstehe ich da was komplett falsch?!
Dieser Beitrag wurde 2 mal editiert, zum letzten Mal von JimStark am .
private Nachricht | Beiträge des Benutzers
Palladin007
myCSharp.de - Member

Avatar #avatar-4140.png


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

beantworten | zitieren | melden

Diese Beispiel-Basisklasse enthält aber nur ein paar grundsätzliche Daten, die man für die meisten Daten so braucht: ID, diverse ForeignKeys und Zeitstempel.
Das eigentliche Problem mit den grundlegend verschiedenen Noten ist damit nicht gelöst, um mit Beidem umgehen zu können, müsste man trotzdem wieder casten.

Daher auch der Gedanke mit dem Interface, doch wie das aufgebaut ist, kann man ohne Details zur geforderten Funktionalität nicht sagen.

Und für die Daten selber würde ich vermutlich drei Spalten einführen:
- GradeType
- GradeValue
- GradeText

Mit der Aufstellung könnte man das dann auch wiederum in einer Klasse abdecken, die sich dann je GradeType anders verhält.
Aber auch da kann man nicht sagen, ob und wie sinnvoll das ist, ohne Details über die geforderten Funktionalitäten zu haben.

Wenn es einzig und allein ums Speichern der Daten geht, sodass man sie später anzeigen oder drucken kann:
Warum überhaupt die Trennung? Mach es als simplen Text, bei den "richtigen" Noten steht dann eben eine Zahl vor dem Text.

Damit meine ich:
Übertreibe es nicht mit der Detailtreue, damit machst Du dir schnell alles kaputt, obwohl Du das gar nicht so genau brauchst.
Überlege dir, was Du wirklich brauchst und dann, wie Du die benötigten Daten behandeln kann, nicht umgekehrt mit den Daten anfangen und dann die Funktionen überlegen.
private Nachricht | Beiträge des Benutzers
Gasimodo
myCSharp.de - Member



Dabei seit:
Beiträge: 9

beantworten | zitieren | melden

Wahrscheinlich denke ich gerade zu simpel aber ist dies nicht "einfach" mittels einem Strategypattern zu lösen?
private Nachricht | Beiträge des Benutzers
Palladin007
myCSharp.de - Member

Avatar #avatar-4140.png


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

beantworten | zitieren | melden

Das Strategy-Pattern setzt doch voraus, dass Du schon irgendwelche Daten hast, mit denen Du dann auf verschiedene Weisen arbeiten kannst.

Und da liegt der Knackpunkt: Wie die zwei völlig verschiedenen Datensätze in Einem darstellen?
Dieser Beitrag wurde 1 mal editiert, zum letzten Mal von Palladin007 am .
private Nachricht | Beiträge des Benutzers
witte
myCSharp.de - Member



Dabei seit:
Beiträge: 966

beantworten | zitieren | melden

Zitat von GeneVorph
Daraus ergibt sich, dass ich in meiner App zwei verschiedene Typen Schüler in ein und derselben Klasse unterbringen möchte. Ich hätte gleich zwei Typen von Schülern anlegen können, dabei aber jede Menge Code-Duplikate produziert, was sehr unschön gewesen wäre, da sie sich - formal - nur im Bewertungsteil so substantiell unterscheiden.
Es ist schwer hier einen Rat zu geben weil zuwenig Informationen vorhanden sind. Du denkst nicht objektorientiert - man sieht nur Daten, es wird aber kein Verhalten gezeigt. Möglicherweise sind aber zwei Stundentenklassen ein besserer Weg zumal du Gemeinsames in einer Basisklasse auslagern könntest. Vorteil wäre dass du dass sauber implementieren könntest und dir JimStarks imperative StudentType-Lösung sparen könntest. Nachteil wäre allerdings dass du wahrscheinlich früher oder später Probleme mit der Kovarianz bekommst.

private Nachricht | Beiträge des Benutzers
GeneVorph
myCSharp.de - Member



Dabei seit:
Beiträge: 166

Themenstarter:

beantworten | zitieren | melden

So, hier also die versprochene Rückmeldung. Zunächst - es hat für meine Zwecke super geklappt, tut was es soll; und dabei, ist es auch noch schön praktisch Vielen Dank also an alle Hilfesteller!

Ohne mich groß zu wiederholen, hier kommt der Code:

Die Klasse Student wurde also um eine List<> ergänzt, in der sowohl Ziffern, als auch Verbalzbenotungen untergebracht werden können. Dazu hab ich folgendes Interface erstellt


   public interface IGrading 
     {
        int GradeId {get; set;}
        string DateOfGrading {get;set;}
     }

Da nun zwei verschiedene Benotungsweisen unter einen Hut zu bringen waren, brauchte es natürlich zwei entsprechende Klassen:


   public class RegularGrading : IGrading 
     {
        public int GradeId {get; set;}
        public string DateOfGrading {get;set;}

        public string GradeAsWord {get;set;}
        public string GradeWithLeadingZero {get;set;}
     }


   public class SpecialGrading : IGrading
     {
        public int GradeId {get;set;}
        public string DateOfGrading {get;set;}
        public string VerbalGrade [get;set;}
      }

Dementsprechend sieht meine Schüler-Klasse nun so aus:


   public class Student  
     {
        //...andere Properties s. oben
        public List<IGrading> Grading {get;set;}
     }

Tja, und das war es dann tatsächlich auch schon.

Und wie wird das Ganze nun genutzt? Nun, wenn eine neue Bewertung erstellt werden soll, sieht das Ganze in etwa so aus:


//Methode im ViewModel   
     public void CreateGrading(Student selectedStudent) 
     {
        if (selectedStudent.StudentType == StudentType.Regular)
	  {
	      RegularGrading r = new RegularGrading();
              r = CalculateValues(points);
	      
	      selectedStudent.Grading.Add(r);
          }
	 else
	  {
	      SpecialGrading s = new SpecialGrading();
	      s = GetVerbalGrade(textBody);    

              selectedStudent.Grading.Add(s);
           }

Wie gesagt, das funktioniert und wirkt auf mich recht elegant gelöst.

Der einzige Nachteil ist: you gotta get your sh** together!
Denn folgendes ist im Code möglich, macht aber von der Logik her keinen Sinn:


   public void UnLogicalMethod() 
     {
        RegularGrading r = new RegularGrading();
        SpecialGrading s = new SpecialGrading();

        r = FillRGWithSomeValues();
        s = FillSGWithAValue();

        selectedStudent.Grading.Add(r);
        selectedStudent.Grading.Add(s); //funktioniert beides, macht aber keinen Sinn, da ein Schüler nur die eine Art der Bewertung erhält ODER die andere!
     }

@Witte:
Danke für die Hinweise.

Zitat
Du denkst nicht objektorientiert - man sieht nur Daten, es wird aber kein Verhalten gezeigt.
OK, meinst du damit man sieht nicht, wie die Objekte im Code genutzt werden? Falls ja, habe ich vielleicht zu kurz gedacht, weil ich eigentlich einen ganz anderen Weg eingeschlagen hatte und mein Thread einen ganz anderen Titel hatte. So wie es sich jetzt liest, klingt es wirklich ein bisschen knapp, vor allem das, was ich im ersten Post geschrieben habe. Ansonsten erläutere bitte, was du mit "nicht objektorientiert denken" meinst, ich lerne gerne dazu und vielleicht gehe ich ja grundsätzlich nicht so an die Sache heran, wie es für objektorientiert angebracht wäre.


Grüße
Vorph
private Nachricht | Beiträge des Benutzers
JimStark
myCSharp.de - Member

Avatar #dOpLzh7hN1az1g0eGRc0.jpg


Dabei seit:
Beiträge: 225

beantworten | zitieren | melden

Zitat von GeneVorph

Der einzige Nachteil ist: you gotta get your sh** together!
Denn folgendes ist im Code möglich, macht aber von der Logik her keinen Sinn:


   public void UnLogicalMethod() 
     {
        RegularGrading r = new RegularGrading();
        SpecialGrading s = new SpecialGrading();

        r = FillRGWithSomeValues();
        s = FillSGWithAValue();

        selectedStudent.Grading.Add(r);
        selectedStudent.Grading.Add(s); //funktioniert beides, macht aber keinen Sinn, da ein Schüler nur die eine Art der Bewertung erhält ODER die andere!
     }


Das macht sogar sehr viel Sinn, du erbst ja vom selben Interface Könntest evtl. eine Methode zum Hinzufügen machen mit zwei Überladungen (Regular und Special)
Dieser Beitrag wurde 1 mal editiert, zum letzten Mal von JimStark am .
private Nachricht | Beiträge des Benutzers
GeneVorph
myCSharp.de - Member



Dabei seit:
Beiträge: 166

Themenstarter:

beantworten | zitieren | melden

Zitat
Das macht sogar sehr viel Sinn, du erbst ja vom selben Interface

Ja - ich meinte eher im echten Leben. Vom Code her klar. Die Idee mit der überladenen Methode gefällt mir.
private Nachricht | Beiträge des Benutzers
trib
myCSharp.de - Member



Dabei seit:
Beiträge: 689

beantworten | zitieren | melden

Hi,

gibt es einen Grund hierfür?


public string DateOfGrading {get;set;}
Wäre ein DateTime nicht eleganter und nimmt Dir im Zweifel Berechnungen in Schaltjahren ab. Oder wirft einen Fehler, wenn das Datum ungültig hinterlegt wird.
Und da Du von "App" schreibst, sollte auch die lokale Zeitzone vom Anwender Dir keinen Strich mehr durch die Rechnung machen.
private Nachricht | Beiträge des Benutzers
Abt
myCSharp.de - Team

Avatar #avatar-4119.png


Dabei seit:
Beiträge: 15618
Herkunft: BW

beantworten | zitieren | melden

Wenn dann ein DateTimeOffset und bitte kein DateTime.
[FAQ] DateTime vs. DateTimeOffset und der Umgang mit Zeiten in .NET
private Nachricht | Beiträge des Benutzers
GeneVorph
myCSharp.de - Member



Dabei seit:
Beiträge: 166

Themenstarter:

beantworten | zitieren | melden

@trib: na ja, es gibt genau eine Stelle in der App, an der man ein Datum "eingeben" kann - nämlich beim Anlegen eines neuen Schülers. Und dort auch nur per DatePicker, der in XAML so angelegt wurde, dass man keine händische Eingabe vornehmen kann. Normalerweise mag ich diese User-Gängelung nicht, aber es handelt sich hier um einen überschaubaren Personenkreis (außer mir vlt. noch vier, fünf Kollegen), die später einmal diese App nutzen. Da hielt ich es für vertretbar, das eingegebene Datum direkt in einen String umzuwandeln, bevor es in die Datenbank geschrieben wird.
Tatsächlich wird beim Auslesen der Daten der String nochmal in DateTime konvertiert, um das aktuelle Alter der Schüler zu berechnen. Ich glaub', das waren vier Zeilen Code...

@Abt: stimmt. Ich glaube, das hattest du mir schon mal empfohlen. Auch hier war ich einfach davon ausgegangen, dass - solange keine anspruchsvollen Datumsberechnungen vorliegen - der alte DateTime reicht.
private Nachricht | Beiträge des Benutzers
Palladin007
myCSharp.de - Member

Avatar #avatar-4140.png


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

beantworten | zitieren | melden

Abt meint einen generellen Grundsatz, DateTimeOffset zu nutzen, da Du (fast) keinen Nachteil hast, aber den Vorteil, dass das DateTime überall auf der Welt gültig ist.
Und mit "fast" meine ich so Kleinigkeiten, wie das etwas komplexere Format von ToString(), aber dafür kann man auch ein eigenes Format mit geben.


Und Thema DateTime als String:

Warum??? Das macht genau keinen Sinn
Die Datenbank kann das auch von sich darstellen, ein EFCore kann das auch korrekt mappen.
Wenn Du das als String rum schiebst, baust Du dir nur Probleme ohne jeden Vorteil.


Und Thema "Gängelung" vom Anwender:
Ich finde, man sollte den Anwender so viel "gängeln" wie nur möglich, denn die neigen dazu, Dinge auszuprobieren und dabei ggf. Blödsinn zu schreiben.
Besser wäre natürlich eine TextBox, die beides kann: Text-Eingabe direkt auf gültiges Datum prüfen und das Geparste anzeigen oder ein Kalender-Ansicht zum Klicken. Das gibt es, meines Wissens aber nicht direkt von Microsoft, sondern nur über externe Frameworks.
Dieser Beitrag wurde 1 mal editiert, zum letzten Mal von Palladin007 am .
private Nachricht | Beiträge des Benutzers
Abt
myCSharp.de - Team

Avatar #avatar-4119.png


Dabei seit:
Beiträge: 15618
Herkunft: BW

beantworten | zitieren | melden

Zitat von Palladin007
Und mit "fast" meine ich so Kleinigkeiten, wie das etwas komplexere Format von ToString()
Das ist ein Standard und nennt sich ISO 8601.
Das ist genau das, was DateTime in der Form nicht validiert kann, weil beim Serialisieren die Zeitzone verloren geht.
Zitat von Palladin007
Die Datenbank kann das auch von sich darstellen, ein EFCore kann das auch korrekt mappen.
Korrekt. Auch EF Core empfiehlt DateTimeOffset für Zeitstempel.
Zitat von GeneVorph
der alte DateTime reicht.
Sorry, das ist eine absolute Quatschargumentation.
Es gibt genau null Grund, wieso man noch DateTime nutzen sollte; leider ist es trotzdem weit verbreitet.
Es gibt auch genau null Argumente, dass "DateTime" reichen würde; DateTimeOffset bietet nicht "mehr" sondern ist die einzige Art und Weise wie man in .NET neutral und korrekt Zeitstempel speichern kann, ohne manuell eingreifen zu müssen.

Mir ein Rätsel, wie man das unterschlagen / abwimmeln kann.
private Nachricht | Beiträge des Benutzers
GeneVorph
myCSharp.de - Member



Dabei seit:
Beiträge: 166

Themenstarter:

beantworten | zitieren | melden

Zitat
Sorry, das ist eine absolute Quatschargumentation.
Mir ein Rätsel, wie man das unterschlagen / abwimmeln kann.
Heute wieder viel Code zum Weinen gesehen?

Ich denke, wer sich meine Posts in Ruhe durchgelesen hat, der wird feststellen, dass ich lediglich meinen Beweggrund dargelet habe, indem ich auf tribs Frage geantwortet habe. Ich dachte, das kann man so machen - jetzt weiß ich es besser. Ich fände es schade, wenn der Eindruck aufkommen würde, ich täte etwas unterschlagen/abwimmeln - ich bin hier, um mich in meinem Hobby zu verbessern und nehme diese Ratschläge auch gerne an. Um mich mal selbst zu zitieren "Ich war davon ausgegangen..." --> Präteritum, und alles is jut

Vielen Dank für eure Hilfe!
private Nachricht | Beiträge des Benutzers