Zum Inhalt springen

Typisierte Parameter


Guybrush Threepwood

Empfohlene Beiträge

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?

Link zu diesem Kommentar
Auf anderen Seiten teilen

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 von Guybrush Threepwood
Link zu diesem Kommentar
Auf anderen Seiten teilen

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 von Guybrush Threepwood
Link zu diesem Kommentar
Auf anderen Seiten teilen

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());

		}

	}

Link zu diesem Kommentar
Auf anderen Seiten teilen

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);

		}

Link zu diesem Kommentar
Auf anderen Seiten teilen

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.

Link zu diesem Kommentar
Auf anderen Seiten teilen

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; }

			}

		}

Link zu diesem Kommentar
Auf anderen Seiten teilen

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...

Link zu diesem Kommentar
Auf anderen Seiten teilen

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 von Bubble
Link zu diesem Kommentar
Auf anderen Seiten teilen

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

Link zu diesem Kommentar
Auf anderen Seiten teilen

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.

Link zu diesem Kommentar
Auf anderen Seiten teilen

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.

Link zu diesem Kommentar
Auf anderen Seiten teilen

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.

Gast
Auf dieses Thema antworten...

×   Du hast formatierten Text eingefügt.   Formatierung wiederherstellen

  Nur 75 Emojis sind erlaubt.

×   Dein Link wurde automatisch eingebettet.   Einbetten rückgängig machen und als Link darstellen

×   Dein vorheriger Inhalt wurde wiederhergestellt.   Editor leeren

×   Du kannst Bilder nicht direkt einfügen. Lade Bilder hoch oder lade sie von einer URL.

Fachinformatiker.de, 2024 by SE Internet Services

fidelogo_small.png

Schicke uns eine Nachricht!

Fachinformatiker.de ist die größte IT-Community
rund um Ausbildung, Job, Weiterbildung für IT-Fachkräfte.

Fachinformatiker.de App

Download on the App Store
Get it on Google Play

Kontakt

Hier werben?
Oder sende eine E-Mail an

Social media u. feeds

Jobboard für Fachinformatiker und IT-Fachkräfte

×
×
  • Neu erstellen...