Benutzer mit den meisten Antworten
Klasseninstanzen in einer Methode abarbeiten

Frage
-
Hi Forum,
ich habe mehrere Klassen(ca. 20), deren Aufbau bezüglich Properties und Methoden gleich sind, aber unterschiedliche Daten liefern. Zum Test, ob die Methoden in den Klassen fehlerfrei arbeiten, möchte ich jeweils eine Instanz davon über eine Methode (zB.: public void Ausgabe(xxx nnn)) abarbeiten.
Mein erstes Problem beginnt schon damit, wie ich die Signatur der Methode Ausgabe erstelle. Geschafft habe ich es vorerst mit der Signatur object o), dann aber stehe ich schon an, was das Zugreifen auf die Inhalte und Ergebnisse der Properties u. Methoden dieser Instanzen anlangt. Vor allem, weil ja die Klassen u.a. auch verschieden aufgebaute Methoden haben wie mit und ohne Rückgabewerte, mit und ohne Parameter usw.).
Für entsprechende Hinweise wäre ich dankbar. Sollten für euch Codebeispiele hilfreich sein, kein Problem.
MfG
vranky
Herzlichen Gruß vranky
- Typ geändert Ciprian Bogdan Donnerstag, 17. April 2014 11:00 keine Rückmeldung des Fragestellenden
- Typ geändert Tom Lambert (Koopakiller)Moderator Samstag, 26. April 2014 19:47 Rückmeldung des Fragestellenden
Antworten
-
Hallo vranky,
ich hab nicht so ganz verstanden, ob Du jetzt 20 Instanzen einer Klasse oder wirklich 20 gleiche Klassen hast, die den gleichen Code beinhalten und nur andere Daten liefern. Falls letzteres, warum? Das macht doch keinen Sinn!?
Wenn Du 20 Klassen hast, die zwar einen gleichen Aufbau haben, innendrin aber komplett unterschiedliche Aufgaben haben und der Code entsprechend ein anderer ist, bietet es sich eigentlich an, ein Interface zu erstellen und die Klassen das Interface implementieren zu lassen. Siehe dazu:
http://msdn.microsoft.com/de-de/library/87d83y5b.aspx
http://msdn.microsoft.com/de-de/library/ms173156.aspx
Im Prinzip gibst Du über die Schnittstelle die Methoden und Eigenschaften vor, die deine Klassen beinhalten müssen. Auch die Signaturen der Methoden werden so festgelegt.
Für dich hat das dann den Vorteil, dass die Klassen und die Instanzen der Klassen gemeinsam IDeineSchnittstelle implementieren und Du dann auch mit diesem Interface arbeiten kannst (alsi auch deine Methode Ausgabe( ... ) einfach für jede Instanz aufrufen kannst)
---
Falls Du etwas anderes meintest, wäre es wahrscheinlich aber schon sehr sinnvoll, wenn Du das Problem bzw. deine Anforderungen detaillierter hier darstellst und entsprechende Codebeispiele postest.
Gruß, Stefan
Microsoft MVP - Visual Developer ASP/ASP.NET
http://www.asp-solutions.de/ - Consulting, Development
http://www.aspnetzone.de/ - ASP.NET Zone, die ASP.NET Community
- Bearbeitet Stefan FalzModerator Samstag, 5. April 2014 11:38
- Als Antwort markiert vranky Montag, 28. April 2014 10:15
-
Hallo vranky,
kurz zum Forum:
Ciprian hat die Frage in eine Diskussion umgewandelt, das kannst du rückgängig machen wenn du über deiner Frage auf "Typ ändern" klickst. Ich habe das in diesem Fall für dich übernommen. (Der Fragesteller und alle Moderatoren sind dazu in der Lage das zu ändern).
Des Weiteren brauchst du nur einmal zu antworten (weil Stefan und ich scheinbar die selbe Antwort erhalten haben), weil wir alle eine Benachrichtigung erhalten, auch wenn die Hirariche Ansicht des Forums etwas anderes vermuten lässt.Zu deinem Problem:
Ich würde hier auf eine Generische Lösung setzen, wenn deine Klassen alle zu 100% gleich initialisiert werden. Das setzt aber vorraus, dass alle Klassen einen Parameterlosen Konstruktor haben, sonst geht es nicht. Ein Ansatz für die Methode:private T GetInstance<T>(string wert) where T : EinsatzMaxEHBaseClass, new()//T muss von EinsatzMaxEHBaseClass abgeleitet sein und einen Parameterlosen Konstruktor haben { var x = new T();//neue Instanz deiner Klasse initialisieren x.Property1 = wert;//Den übergebenen Wert einer Eigenschaft zuweisen return x;//Neue Instanz zurück geben. }
Der Aufruf könnte dann so aussehen:
var x = GetInstance<Chance35Plein>("Test");//Neue Instanz erzeugen var y = x.ChanceIndex();//Du kannst hier Klassenspezifische Dinge aufrufen, die nicht in der Basisklasse stehen. Das geht durch den Generischen Parameter bei GetInstance
Wenn du dagegen keinen Parameterlosen Konstruktor hast und nur Eigenschaften und Methoden innerhalb der "GetInstance"-Methode benutzen kannst, dann könnte die Funktion so aussehen:private void InitInstance(EinsatzMaxEHBaseClass x, sting wert){ x.Property1 = wert;//Deine Eigenschaften zuweisen }
Dann sieht der Aufruf so aus:
var x = new Chance35Plein();//Neue Instanz anlegen InitInstance(x, "Test");//Eigenschaften etc. initialisieren var y = x.ChanceIndex();//Klassenspezifische Dinge aufrufen
Da Du mit Klassen arbeitest, wird "x" als Referenz übergeben. D.h. alle Änderungen in InitInstance werden auf das übergebene "x" angewendet.
Für Beide gilt:
Du kannst nur Dinge setzen, die in der Basiskalsse implementiert sind. Alternativ kannst du auch die Schnittstelle angeben - in dem Fall könntest du alles aufrufen, was in der Schnittstelle vorgegeben ist.
Ob sich der Aufwand lohnt musst du selbst wissen. Wegen 10 Eigenschaften würdest du vielleicht 5 Zeilen pro Initialisierung sparen, jedoch 90% der Übersichtlichkeit verlieren. Ich kann aber kein definitives Urteil fällen, da ich deinen Code und dein Vorhaben wirklich zu 100% kennen müsste. Und selbst wenn ich das täte, dann wäre es noch immer reine Ansichtssache.
Tom Lambert - C# MVP
Bitte bewertet- und markiert Beiträge als Antwort. Danke.
Nützliche Links: .NET Quellcode | C# ↔ VB.NET Konverter
Ich: Webseite | Code Beispiele | Facebook | Twitter | Snippets- Als Antwort markiert vranky Montag, 28. April 2014 10:21
Alle Antworten
-
Hallo vranky,
ich hab nicht so ganz verstanden, ob Du jetzt 20 Instanzen einer Klasse oder wirklich 20 gleiche Klassen hast, die den gleichen Code beinhalten und nur andere Daten liefern. Falls letzteres, warum? Das macht doch keinen Sinn!?
Wenn Du 20 Klassen hast, die zwar einen gleichen Aufbau haben, innendrin aber komplett unterschiedliche Aufgaben haben und der Code entsprechend ein anderer ist, bietet es sich eigentlich an, ein Interface zu erstellen und die Klassen das Interface implementieren zu lassen. Siehe dazu:
http://msdn.microsoft.com/de-de/library/87d83y5b.aspx
http://msdn.microsoft.com/de-de/library/ms173156.aspx
Im Prinzip gibst Du über die Schnittstelle die Methoden und Eigenschaften vor, die deine Klassen beinhalten müssen. Auch die Signaturen der Methoden werden so festgelegt.
Für dich hat das dann den Vorteil, dass die Klassen und die Instanzen der Klassen gemeinsam IDeineSchnittstelle implementieren und Du dann auch mit diesem Interface arbeiten kannst (alsi auch deine Methode Ausgabe( ... ) einfach für jede Instanz aufrufen kannst)
---
Falls Du etwas anderes meintest, wäre es wahrscheinlich aber schon sehr sinnvoll, wenn Du das Problem bzw. deine Anforderungen detaillierter hier darstellst und entsprechende Codebeispiele postest.
Gruß, Stefan
Microsoft MVP - Visual Developer ASP/ASP.NET
http://www.asp-solutions.de/ - Consulting, Development
http://www.aspnetzone.de/ - ASP.NET Zone, die ASP.NET Community
- Bearbeitet Stefan FalzModerator Samstag, 5. April 2014 11:38
- Als Antwort markiert vranky Montag, 28. April 2014 10:15
-
Hallo,
Wenn alle Klassen die selben Eigenschaften und Methoden aufweißen, dann nehme ich mal an, dass diese eine Basiskalsse besitzen. Somit wäre das einfachste diese Basisklasse zurück zu geben:
MyBase GetInstance(...){}
Beim Aufrufen der Methode kannst du das Ergebnis dann in deine Kind-Klasse casten.
----
Alternbativ kannst du versuchen mit Generika zu arbeiten:
T GetInstance<T>(...) where T : MyBase{}
Damit kannst du deine Methode nun so aufrufen:
var class1_instance = GetInstance<Class1>(...);
Durch den Typ-Parameter erhälst du den von dir gewünschten Typ. Durch die where-Einschränkung müssen alle Klassen von MyBase abgeleitet sein. Diese Einschränkung kannst du aber auch weg lassen.
----
Solange du bei der Initialisierung der Klasseninstanz in der Methode keine Probleme hast, kann der von dir erdachte Weg natürlich gut funktionieren. Wenn nicht, solltest du es vielleicht doch alles manuell machen.
Tom Lambert - C# MVP
Markiert bitte beantwortende Posts als Antwort und bewertet hilfreiche Beiträge. Danke.
Nützliche Links: .NET Quellcode | C# ↔ VB.NET Konverter
Meine Seiten: Webseite | Code Beispiele | Facebook | Twitter | Snippets -
Hi,
ist dieser Thread noch aktuell ? Bist Du hier inzwischen weitergekommen ?
Gruß,
Ciprian
Ciprian Bogdan, MICROSOFT
Bitte haben Sie Verständnis dafür, dass im Rahmen dieses Forums, welches auf dem Community-Prinzip„Entwickler helfen Entwickler“ beruht, kein technischer Support geleistet werden kann oder sonst welche garantierten Maßnahmen seitens Microsoft zugesichert werden können.
-
*****************************************************************************************************
Dieser Thread wurde mangels weiterer Beteiligung des Fragestellenden ohne bestätigte Lösung abgeschlossen.
Neue Rückfragen oder Ergänzungen zu diesem Thread bleiben weiterhin möglich.
*****************************************************************************************************Ciprian Bogdan, MICROSOFT
Bitte haben Sie Verständnis dafür, dass im Rahmen dieses Forums, welches auf dem Community-Prinzip„Entwickler helfen Entwickler“ beruht, kein technischer Support geleistet werden kann oder sonst welche garantierten Maßnahmen seitens Microsoft zugesichert werden können.
-
Hallo Stefan!
Durch ein technisches Gebrechen bin ich erst jetzt in der Lage, auf deine rasche Reaktion zu antworten.
In meinen Klassen verwende ich ein Interface und auch eine "Basis-Klasse" von der geerbt wird.
Ein Auszug aus einer dieser Klassen:
public class Chance35Plein : EinsatzMaxEHBaseClass, IChance { #region IChance Member /// <summary> /// Die französische Chancenbezeichnung, wenn sie /// für den Anwender sichtbar gemacht werden soll. /// </summary> public string ChanceBezeichnungFranzös() { return FixeWerte.EnumsRL.EnumRLChancBezFöff.Plein.ToString(); } /// <summary> /// Auszahlungsquote zu dieser Chance als Integer-Wert. /// </summary> public int ChanceAuszahlungsQuote() { return (int)FixeWerte.EnumsRL.EnumRLChancBezFQuote.Plein; } /// <summary> /// Gibt den Attributwert dieser Chance aus der /// "FixeWerte.EnumsRL.EnumRLChancBezFi." zurück. /// </summary> public int ChanceIndex() { return (int) FixeWerte.EnumsRL.EnumRLChancBezFiUndIndex.Plein; } #endregion }
Die "Basisklasse", von der geerbt werden kann:
public class EinsatzMaxEHBaseClass { /// <summary> /// Gibt den Euro-Mindesteinsatz, entsprechend einem dieser Methode /// als Parameter mitzugebende Integer-Wert aus der eben verwendeten Instanz-Methode "ChanceIndex", /// die Höchstanzahl der zu setztenden Einheiten zurück. /// </summary> /// <returns>Einheiten</returns> public string GetEinsatzMaxBei02Euro(int methodChanceIndx) { return FixeWerte.WerteMinMax.HoeEinsatzEHbei02Euro[methodChanceIndx]; } }
Hier ein Auszug aus Methoden in einer anderen Klasse der Anwendung, zu dem wie der Umsetzung ich gefragt habe:
private void VeranlassWas() { RL_ChancenLib.Chancen.Chance35Plein pl = new RL_ChancenLib.Chancen.Chance35Plein(); RL_ChancenLib.Chancen.Chance17Cheval cv = new RL_ChancenLib.Chancen.Chance17Cheval(); //string maxeinsatz = pl.GetEinsatzMaxBei02Euro(pl.ChanceIndex()); Ausgabe("Chance Plein: ", pl); Ausgabe("Chance Cheval", cv);
//usw. } private void Ausgabe(string text, object o) { //Hier sollte so was ähnliches möglich sein wie das Auskommentierte in //der Methode "VeranlassWas()" }
Die "Klassen" und die dazu angelegten Enums habe ich in eine DLL ausgelagert, auf die über Verweis zugegriffen werden kann.
Ich hoffe, mein Problem halbwegs verständlich dargelegt zu haben.
Herzlichen Gruß vranky
- Bearbeitet vranky Samstag, 26. April 2014 19:10
-
Hallo Tom!
Durch ein technisches Gebrechen bin ich erst jetzt in der Lage, auf deine rasche Reaktion zu antworten.
In meinen Klassen verwende ich ein Interface und auch eine "Basis-Klasse" von der geerbt wird.
Ein Auszug aus einer dieser Klassen:
public class Chance35Plein : EinsatzMaxEHBaseClass, IChance { #region IChance Member /// <summary> /// Die französische Chancenbezeichnung, wenn sie /// für den Anwender sichtbar gemacht werden soll. /// </summary> public string ChanceBezeichnungFranzös() { return FixeWerte.EnumsRL.EnumRLChancBezFöff.Plein.ToString(); } /// <summary> /// Auszahlungsquote zu dieser Chance als Integer-Wert. /// </summary> public int ChanceAuszahlungsQuote() { return (int)FixeWerte.EnumsRL.EnumRLChancBezFQuote.Plein; } /// <summary> /// Gibt den Attributwert dieser Chance aus der /// "FixeWerte.EnumsRL.EnumRLChancBezFi." zurück. /// </summary> public int ChanceIndex() { return (int) FixeWerte.EnumsRL.EnumRLChancBezFiUndIndex.Plein; } #endregion }
Die "Basisklasse", von der geerbt werden kann:
public class EinsatzMaxEHBaseClass { /// <summary> /// Gibt den Euro-Mindesteinsatz, entsprechend einem dieser Methode /// als Parameter mitzugebende Integer-Wert aus der eben verwendeten Instanz-Methode "ChanceIndex", /// die Höchstanzahl der zu setztenden Einheiten zurück. /// </summary> /// <returns>Einheiten</returns> public string GetEinsatzMaxBei02Euro(int methodChanceIndx) { return FixeWerte.WerteMinMax.HoeEinsatzEHbei02Euro[methodChanceIndx]; } }
Hier ein Auszug aus Methoden in einer anderen Klasse der Anwendung, zu dem wie der Umsetzung ich gefragt habe:
private void VeranlassWas() { RL_ChancenLib.Chancen.Chance35Plein pl = new RL_ChancenLib.Chancen.Chance35Plein(); RL_ChancenLib.Chancen.Chance17Cheval cv = new RL_ChancenLib.Chancen.Chance17Cheval(); //string maxeinsatz = pl.GetEinsatzMaxBei02Euro(pl.ChanceIndex()); Ausgabe("Chance Plein: ", pl); Ausgabe("Chance Cheval", cv);
//usw. } private void Ausgabe(string text, object o) { //Hier sollte so was ähnliches möglich sein wie das Auskommentierte in //der Methode "VeranlassWas()" }
Die "Klassen" und die dazu angelegten Enums habe ich in eine DLL ausgelagert, auf die über Verweis zugegriffen werden kann.
Ich hoffe, mein Problem halbwegs verständlich dargelegt zu haben.
Herzlichen Gruß vranky
-
Hallo vranky,
kurz zum Forum:
Ciprian hat die Frage in eine Diskussion umgewandelt, das kannst du rückgängig machen wenn du über deiner Frage auf "Typ ändern" klickst. Ich habe das in diesem Fall für dich übernommen. (Der Fragesteller und alle Moderatoren sind dazu in der Lage das zu ändern).
Des Weiteren brauchst du nur einmal zu antworten (weil Stefan und ich scheinbar die selbe Antwort erhalten haben), weil wir alle eine Benachrichtigung erhalten, auch wenn die Hirariche Ansicht des Forums etwas anderes vermuten lässt.Zu deinem Problem:
Ich würde hier auf eine Generische Lösung setzen, wenn deine Klassen alle zu 100% gleich initialisiert werden. Das setzt aber vorraus, dass alle Klassen einen Parameterlosen Konstruktor haben, sonst geht es nicht. Ein Ansatz für die Methode:private T GetInstance<T>(string wert) where T : EinsatzMaxEHBaseClass, new()//T muss von EinsatzMaxEHBaseClass abgeleitet sein und einen Parameterlosen Konstruktor haben { var x = new T();//neue Instanz deiner Klasse initialisieren x.Property1 = wert;//Den übergebenen Wert einer Eigenschaft zuweisen return x;//Neue Instanz zurück geben. }
Der Aufruf könnte dann so aussehen:
var x = GetInstance<Chance35Plein>("Test");//Neue Instanz erzeugen var y = x.ChanceIndex();//Du kannst hier Klassenspezifische Dinge aufrufen, die nicht in der Basisklasse stehen. Das geht durch den Generischen Parameter bei GetInstance
Wenn du dagegen keinen Parameterlosen Konstruktor hast und nur Eigenschaften und Methoden innerhalb der "GetInstance"-Methode benutzen kannst, dann könnte die Funktion so aussehen:private void InitInstance(EinsatzMaxEHBaseClass x, sting wert){ x.Property1 = wert;//Deine Eigenschaften zuweisen }
Dann sieht der Aufruf so aus:
var x = new Chance35Plein();//Neue Instanz anlegen InitInstance(x, "Test");//Eigenschaften etc. initialisieren var y = x.ChanceIndex();//Klassenspezifische Dinge aufrufen
Da Du mit Klassen arbeitest, wird "x" als Referenz übergeben. D.h. alle Änderungen in InitInstance werden auf das übergebene "x" angewendet.
Für Beide gilt:
Du kannst nur Dinge setzen, die in der Basiskalsse implementiert sind. Alternativ kannst du auch die Schnittstelle angeben - in dem Fall könntest du alles aufrufen, was in der Schnittstelle vorgegeben ist.
Ob sich der Aufwand lohnt musst du selbst wissen. Wegen 10 Eigenschaften würdest du vielleicht 5 Zeilen pro Initialisierung sparen, jedoch 90% der Übersichtlichkeit verlieren. Ich kann aber kein definitives Urteil fällen, da ich deinen Code und dein Vorhaben wirklich zu 100% kennen müsste. Und selbst wenn ich das täte, dann wäre es noch immer reine Ansichtssache.
Tom Lambert - C# MVP
Bitte bewertet- und markiert Beiträge als Antwort. Danke.
Nützliche Links: .NET Quellcode | C# ↔ VB.NET Konverter
Ich: Webseite | Code Beispiele | Facebook | Twitter | Snippets- Als Antwort markiert vranky Montag, 28. April 2014 10:21