Zum Inhalt springen
View in the app

A better way to browse. Learn more.

Fachinformatiker.de

A full-screen app on your home screen with push notifications, badges and more.

To install this app on iOS and iPadOS
  1. Tap the Share icon in Safari
  2. Scroll the menu and tap Add to Home Screen.
  3. Tap Add in the top-right corner.
To install this app on Android
  1. Tap the 3-dot menu (⋮) in the top-right corner of the browser.
  2. Tap Add to Home screen or Install app.
  3. Confirm by tapping Install.

Empfohlene Antworten

Veröffentlicht

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?

Du könntest ein Interface definieren, dass die Klassen (im Beispiel A und B) implementieren müssen.

  • Autor

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

Erzeuge doch einfach eine Instanz, was spricht dagegen?

  • Autor
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

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

		}

	}

Und warum sollen die Strings statisch sein?

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

		}

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.

  • Autor

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.

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

			}

		}

  • Autor

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

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

  • Autor
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

@farmed: Das habe ich eben beschrieben.

Danke

Bitte :)

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.

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.

Erstelle ein Konto oder melde dich an, um einen Kommentar zu schreiben.

Configure browser push notifications

Chrome (Android)
  1. Tap the lock icon next to the address bar.
  2. Tap Permissions → Notifications.
  3. Adjust your preference.
Chrome (Desktop)
  1. Click the padlock icon in the address bar.
  2. Select Site settings.
  3. Find Notifications and adjust your preference.