Guybrush Threepwood Geschrieben 17. Dezember 2008 Geschrieben 17. Dezember 2008 Erstmal sorry wegen der Überschrift aber mir fällt nichts passendes ein... Angenommen ich hab folgendes Programm: class Program { public class A { public static string a1 { get { return "a1"; } } } public class B { public static string b1 { get { return "a2"; } } } static void foo(string s) { Console.WriteLine(s); } static void Main(string[] args) { foo(A.a1); Console.ReadKey(); } } [/PHP] In foo() werden die strings benötigt welche in den Properties von A und B stecken, wie bekomme ich das hin das man auch nur diese übergeben kann und nicht einfach irgendeinen anderen String? Zitieren
Bubble Geschrieben 17. Dezember 2008 Geschrieben 17. Dezember 2008 Du könntest ein Interface definieren, dass die Klassen (im Beispiel A und implementieren müssen. Zitieren
Guybrush Threepwood Geschrieben 17. Dezember 2008 Autor Geschrieben 17. Dezember 2008 (bearbeitet) Ja sowas hab ich mir auch schon überlegt, aber wie würde denn dann die Übergabe aussehen. Weil in dem Beispiel oben hätte man ja keine Instanz von A oder B sondern nur die statischen Properties Mein aktueller Gedankengang geht da mehr in diese richtung: public class MyType { private string str; public MyType(string s) { str = s; } public string Str { get { return str; } } } public class A { public static MyType a1 { get { return new MyType("a1") ; } } } public class B { public static MyType b1 { get { return new MyType("b1"); } } } static void foo(MyType s) { Console.WriteLine(s.Str); } static void Main(string[] args) { foo(A.a1); foo(B.b1); Console.ReadKey(); } } [/PHP] Man könnte zwar immer noch einen beliebigen MyType übergeben, aber das wäre schonmal etwas weniger fehleranfällig als ein beliebiger String. Für bessere Vorschläge bin ich aber dankbar Bearbeitet 17. Dezember 2008 von Guybrush Threepwood Zitieren
Bubble Geschrieben 17. Dezember 2008 Geschrieben 17. Dezember 2008 Erzeuge doch einfach eine Instanz, was spricht dagegen? Zitieren
Guybrush Threepwood Geschrieben 17. Dezember 2008 Autor Geschrieben 17. Dezember 2008 (bearbeitet) Erzeuge doch einfach eine Instanz, was spricht dagegen? Aber dann steh ich ja wieder beim selben Problem nur an anderer Stelle. Diese Instanz müsste ja dann den Wert eines dieser Properties haben und ich müsste da irgendwie verhinden das das kein anderer String ist. Also als Beispiel bei public class A { public static string a1 { get { return "a1" ; } } public static string a2 { get { return "a2"; } } private string s; public A(string s) { this.s = s; } public string S { get { return s; } } } A a = new A(A.a1); // OK A a = new A("blubb"); // nicht OK [/PHP] könnte man ja dann beim Erstellen der Instanz einen beliebigen string übergeben. EDIT: Du hast mich aber auf folgende Idee gebracht: [PHP] class Program { public interface I { string GetString(); } public class A : I { public enum AE { a1, a2 } private static List<string> l = new List<string>(new string[] { "a1", "a2" }); private string s; public A(AE e) { s = l[(int)e]; } public string GetString() { return s; } } public class B : I { public enum BE { b1, b2 } private static List<string> l = new List<string>(new string[] { "b1", "b2" }); private string s; public B(BE e) { s = l[(int)e]; } public string GetString() { return s; } } static void foo(I s) { Console.WriteLine(s.GetString()); } static void Main(string[] args) { foo(new A(A.AE.a1)); foo(new B(B.BE.b2)); Console.ReadKey(); } } Weiterte Vorschläge? Bearbeitet 17. Dezember 2008 von Guybrush Threepwood Zitieren
Bubble Geschrieben 17. Dezember 2008 Geschrieben 17. Dezember 2008 Ausgehend von dem ersten Ansatz, habe ich ein Beispiel entworfen. Irgendwie sind Deine Ansätze bzw. Beispiele aber alle recht unterschiedlich. Was möchtest Du denn, unabhängig von einer Implementierung, erreichen? Wenn nötig, beschreibe es einmal genauer, vielleicht sollte man das Problem besser anders angehen. Das Beispiel: class Program { public interface IStringProvider { string MyString { get; } } public class A : IStringProvider { public static string a1 { get { return "a1"; } } public string MyString { get { return a1; } } } public class B : IStringProvider { public static string b1 { get { return "a2"; } } public string MyString { get { return b1; } } } static void foo(IStringProvider a) { Console.WriteLine(a.MyString); } static void Main(string[] args) { foo(new A()); foo(new B()); } } Zitieren
Guybrush Threepwood Geschrieben 17. Dezember 2008 Autor Geschrieben 17. Dezember 2008 Ja ich glaube das liegt daran das ich am ersten Beispiel an Properties gespart habe. Die Klassen sollen nicht nur jeweils eins haben sonderen mehrere und foo soll dann mit einem davon aufgerufen werden. Im Prinzip so als wären A und B enums nur halt mit strings als Werten. Zitieren
Bubble Geschrieben 17. Dezember 2008 Geschrieben 17. Dezember 2008 Und warum sollen die Strings statisch sein? Zitieren
Guybrush Threepwood Geschrieben 17. Dezember 2008 Autor Geschrieben 17. Dezember 2008 Müssen sie nicht zwangsläufig ich hatte am Anfang nur gehofft das man es dann später alla: foo(A.a1); foo(B.b1); [/PHP] aufrufen kann ohne extra eine Instanz erstellen zu müssen. Also das der Umgang am Ende wie mit einem Enum ist. Zitieren
Bubble Geschrieben 17. Dezember 2008 Geschrieben 17. Dezember 2008 Wie wäre es hiermit? Das sollte Deinen Wünschen doch weitgehend entsprechen. Beim Verwenden würde ich die Properties (d1, d2, d3) in meinem Beispiel allerdings durch Methoden ersetzen, da ich es unschön finde, bei einem Zugriff auf eine Property ein neues Objekt zu erstellen, das ist IMO in einer Methode schöner aufgehoben. class Program { public interface IStringProvider { string MyString { get; } } public class D : IStringProvider { static private string[] someStrings = { "d1", "d2", "d3" }; private int stringToUse; private D(int useThis) { stringToUse = useThis; } public static D d1 { get { return new D(0); } } public static D d2 { get { return new D(1); } } public static D d3 { get { return new D(2); } } public string MyString { get { return someStrings[(int)stringToUse]; } } } static void foo(IStringProvider a) { Console.WriteLine(a.MyString); } static void Main(string[] args) { foo(D.d1); foo(D.d2); foo(D.d3); } Zitieren
Bubble Geschrieben 17. Dezember 2008 Geschrieben 17. Dezember 2008 Noch eine Anmerkung: Diese Vorgehensweise verhindert natürlich nicht, dass jemand anderes ebenfalls die Schnittstelle implementiert und so doch andere Strings an foo übergibt. Nur der Aufwand steigt. Zitieren
Guybrush Threepwood Geschrieben 17. Dezember 2008 Autor Geschrieben 17. Dezember 2008 Ja sehr schöne Lösung die deckt sich fast genau mit der die mir ein Kollege gerade vorgeschlagen hat Nur das er meinte das es schöner wäre die Strings in ein Dictionary zu verpacken weil man sich ja sonst darauf verlassen muss das niemand in der Liste mit den Strings etwas an der falschen Position einfügt. Da ist nur noch das Problem das das Dictionary afaik keinen C-Tor hat um es direkt zu befüllen. Zu deiner Anmerkung: Ja das ist klar und soll auch sein. Die Benutzung von foo soll nur so einfach und klar wie Möglich sein und wenn man einfach so einen string übergeben kann ist das imho halt nicht so. Zitieren
Bubble Geschrieben 17. Dezember 2008 Geschrieben 17. Dezember 2008 Du musst nicht zwangsläufig mit dem statischen Array arbeiten, wenn Du Angst hast, dass etwas durcheinander gerät. Du könntest stringToUse als String festlegen und die Properties dann ein Objekt mit dem passenden String erstellen lassen. Das sähe dann beispielsweise so aus: public class D : IStringProvider { private string stringToUse; private D(string useThis) { stringToUse = useThis; } public static D d1 { get { return new D("d1"); } } public static D d2 { get { return new D("d2"); } } public static D d3 { get { return new D("d3"); } } public string MyString { get { return stringToUse; } } } Zitieren
Guybrush Threepwood Geschrieben 17. Dezember 2008 Autor Geschrieben 17. Dezember 2008 hmm ja das ist auch eine gute Idee, allerdings bedeutet das das bei jedem Aufruf eine neue Instanz erstellt wird. Bei der Lösung meines Kollegen war es so das im Dictionary nicht der String abgelegt wurde sondern eine Instanz der Klasse mit diesem String so dass für jeden String die Instanz nur einmal angelegt wurde. Ist halt die Frage was besser ist, deins finde ich schöner da es kompakter ist das andere ist könnte je nach Fall effizienter sein... Zitieren
Bubble Geschrieben 17. Dezember 2008 Geschrieben 17. Dezember 2008 (bearbeitet) hmm ja das ist auch eine gute Idee Sind das meine Ideen nicht immer? allerdings bedeutet das das bei jedem Aufruf eine neue Instanz erstellt wird. Bei der Lösung meines Kollegen war es so das im Dictionary nicht der String abgelegt wurde sondern eine Instanz der Klasse mit diesem String so dass für jeden String die Instanz nur einmal angelegt wurde. Ja, es wird eine neue Instanz erzeugt. Es ist aber die Frage, ob es sich wirklich lohnt, hier anders vorzugehen. Vielleicht wird es ja ohnehin optimiert. Willst Du es denn in einer performancekritischen Schleife verwenden? Wenn Du trotzdem möglichst selten ein Objekt der Klasse D erzeugen möchtest oder einfach mal eine andere Vorgehensweise testen willst: Du könntest (ohne associative array) die einzelnen Instanzen selbst cachen und sie nur dann erzeugen, wenn noch keine existiert, d.h. beim jeweils ersten Abruf eines Properties. Pro weiterem Property Aufruf wäre es dann nur die nötige if-Abfrage (ob die Instanz bereits existiert), sowie der Zugriff auf die gespeicherte Instanz des Objektes. Die Instanzen blieben jedoch bis zum Programmende im Speicher, da ständig eine Referenz auf sie gehalten wird, wenn Du dagegen nicht noch zusätzlich etwas unternehmen willst. Bearbeitet 17. Dezember 2008 von Bubble Zitieren
farmed Geschrieben 17. Dezember 2008 Geschrieben 17. Dezember 2008 (bearbeitet) Singleton (Entwurfsmuster ? Wikipedia) @Bubble: Nur als Ergänzung zur Implementierung Bearbeitet 17. Dezember 2008 von farmed Zitieren
Guybrush Threepwood Geschrieben 17. Dezember 2008 Autor Geschrieben 17. Dezember 2008 Sind das meine Ideen nicht immer? hehe Ja, es wird eine neue Instanz erzeugt. Es ist aber die Frage, ob es sich wirklich lohnt, hier anders vorzugehen. Vielleicht wird es ja ohnehin optimiert. Willst Du es denn in einer performancekritischen Schleife verwenden? Nein wahrscheinlich ist das egal und es wird so oder so nur eine Instanz erzeugt, ist mir dabei nur aufgefallen. Ich habs jetzt auch erstmal so wie von dir umgesetzt und im Zweifel liese sich das ja auch schnell ändern. Danke Zitieren
Bubble Geschrieben 17. Dezember 2008 Geschrieben 17. Dezember 2008 @farmed: Das habe ich eben beschrieben. Zitieren
Bubble Geschrieben 17. Dezember 2008 Geschrieben 17. Dezember 2008 Mir ist vorhin noch eine Variante eingefallen, die Dir auch gefallen könnte. Sie ersetzt die Properties durch statische Member-Variablen: public class E : IStringProvider { private string stringToUse; private E(string useThis) { stringToUse = useThis; } public static E e1 = new E("e1"); public static E e2 = new E("e2"); public static E e3 = new E("e3"); public string MyString { get { return stringToUse; } } } Der Zugriff auf die Objekte erfolgt dann, wie gehabt, z.B. mit E.e2. Zitieren
Bubble Geschrieben 18. Dezember 2008 Geschrieben 18. Dezember 2008 Noch eine kleine Ergänzung: Das ganze könntest Du zusätzlich noch mit Properties kombinieren, wenn Du lieber Properties haben willst, bei denen klar ist, dass man sie nicht verändern kann (das geht bei den Member-Variablen allerdings auch nicht, da der nötige Konstruktor privat ist), die Umsetzung (der Properties) variabel lassen willst oder Du einfach mal alle Properties ohne viel Aufand z.B. in einem PropertyGrid darstellen möchtest. Das sähe dann z.B. so aus: ... private static E e1 = new E("e1"); private static E e2 = new E("e2"); ... public static E E1 { get { return e1; } } public static E E2 { get { return e1; } } ... Das entspricht von der Verwendung her grundsätzlich der vorigen Lösung. Man könnte die Klasse zusätzlich noch als sealed anlegen, um deutlich zu machen, dass Erweiterungen zwecklos sind. Zitieren
Guybrush Threepwood Geschrieben 18. Dezember 2008 Autor Geschrieben 18. Dezember 2008 Ja sehr schön so wird auch die Instanz nur einmal erzeugt und ich spare mir das Überladen des == operators. Irgendwie frag ich mich gerade wo am Anfang überhaupt das Problem war Zitieren
Empfohlene Beiträge
Dein Kommentar
Du kannst jetzt schreiben und Dich später registrieren. Wenn Du ein Konto hast, melde Dich jetzt an, um unter Deinem Benutzernamen zu schreiben.