Laden...

[Gelöst] Wie kann ich mit möglichst kurzer Syntax Items in einem Dictionary adressieren?

Erstellt von pollito vor 3 Jahren Letzter Beitrag vor 3 Jahren 675 Views
pollito Themenstarter:in
314 Beiträge seit 2010
vor 3 Jahren
[Gelöst] Wie kann ich mit möglichst kurzer Syntax Items in einem Dictionary adressieren?

Hallo!

Ich traue mich fast nicht, die Frage zu stellen, denn irgendwie habe ich den Eindruck, die Antwort darauf ist einfach – ich komme aber nicht wirklich darauf.

Ich versuche, anhand eines kleinen und extrem vereinfachten Codeschnipsels, es zu erklären.

Ich habe in einer Klasse ein Dictionary, auf dessen Elemente ich sehr oft zugreifen muss. In diesem Beispiel sind Key und Value einfache Zeichenketten, während in der echten Anwendung Value ein Klassenobjekt ist.

Um keine Fehler bei der Eingabe zu machen, möchte ich Intellisense von Visual Studio nutzen. Deswegen die statische Klasse "fld", die die Keys beherbergt. Wenn ich dann irgendwo im Code "fld." eingebe, zeigt mir Visual Code die möglichen Werte zur Auswahl an.

Es funktioniert auch alles richtig, aber die Ausdrücke werden dadurch zum Teil unendlich lang. Hier ein sehr einfaches Beispiel:

Console.WriteLine(TestObjekt.Field[**Testklasse.fld.**item1]);

Hier bekomme ich, wie erwartet, "Das ist item1" als Ausgabe.

Nun die Frage: Wie kann ich die Klasse umstellen, damit ich möglichst direkt das gewünschte Element im Dictionary adressieren kann?

Für jeden Tipp vielen Dank im Voraus und ein schönes Wochenende!

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Test1
{
	class Program
	{
		static void Main(string[] args)
		{
			var TestObjekt = new Testklasse();

			Console.WriteLine(TestObjekt.Field[Testklasse.fld.item1]);

			Console.ReadKey();
		}
	}

	public class Testklasse
	{
		public static class fld
		{
			public const string item1 = "item1";
			public const string item2 = "item2";
			public const string item3 = "item3";
			public const string item4 = "item4";
		}

		public Dictionary<string, string> Field = new Dictionary<string, string>()
		{
			{ fld.item1, "Das ist item1" },
			{ fld.item2, "Das ist item2" },
			{ fld.item3, "Das ist item3" },
			{ fld.item4, "Das ist item4" }
		};

		public Testklasse()
		{

		}
	}
}

René

T
2.219 Beiträge seit 2008
vor 3 Jahren

Im einfachsten Fall kannst du dir doch auch pro Item eine eigene Property in TestKlasse anlegen


public string Item1
{
    get
    {
        return this.Fields[fld.item1];
    }
}

// Zugriff
TestObjekt.Item1

Dies hätte auch den Vorteil, dass die Konstanten sowie das Dictionary komplett weggekapselt werden können und somit von Außen nicht erreichbar wären, falls du diese nur innerhalb der Klasse brauchst was die interne Klasse andeutet.

Nachtrag:
Alternativ kannst du auch den Index Operator überschreiben, falls du zu viele/dynamische Einträge hättest und die Aufrufe an das Dictionary weiterleiten.

T-Virus

Developer, Developer, Developer, Developer....

99 little bugs in the code, 99 little bugs. Take one down, patch it around, 117 little bugs in the code.

4.931 Beiträge seit 2008
vor 3 Jahren

Wenn es dir um Einsparen von Schreibarbeit (bzw. auch Lesbarkeit) geht, so würde ich die Klasse fld aus der übergeordneten Klasse herausziehen (damit du nicht immer den Hauptklassennamen, hier Testklasse, angeben mußt).

Wenn die Keys alle Identifiern entsprechen (also nur Buchstaben, Zahlen oder Unterstrich), dann würde ich dafür sogar ein enum stattdessen anlegen und mittels einer Methode (oder dem Indexer) darauf zugreifen (erspart das Schreiben von jeweils public const string itemX):


string GetField(FieldEnum fld)
{
  return Field(fld.ToString());
}

(oder gleich das enum als Key für das Dictionary angeben)

C
2.121 Beiträge seit 2010
vor 3 Jahren

die Ausdrücke werden dadurch zum Teil unendlich lang. Hier ein sehr einfaches Beispiel:
Console.WriteLine(TestObjekt.Field[Testklasse.fld.item1]);

58 Zeichen sind doch traumhaft kurz, bezogen auf die Anzahl Zeichen 😃

Ich beziehe die Begriffe "lang" und "kurz" gerne auf die Zeit die man beim Lesen und Verstehen braucht, nicht auf die Länge der Zeile.
Ich würde daher sogar fld noch ausschreiben. Wenn du später wieder in deinen Code schaust und nicht mehr auswendig weißt was das bedeuten soll, ärgerst du dich dass du "damals" nicht ein paar Buchstaben mehr verwendet hast, um zu beschreiben was das sein soll.
Mit den bisherigen Antworten bekommst du deinen Code verkürzt und er bleibt trotzdem noch lesbar und verständlich.

pollito Themenstarter:in
314 Beiträge seit 2010
vor 3 Jahren

Im einfachsten Fall kannst du dir doch auch pro Item eine eigene Property in TestKlasse anlegen

Danke, das hilft mir weiter. Ich wusste/spürte es, dass es einfacher geht.

Diese Klassen (Mehrzahl) sind Ableitungen einer anderen Klasse, die den gemeinsamen Code beherbergt. Ich rede von "den Klassen", da es viele davon geben kann, zum Teil mit bis zu über 200 Dictionary-Einträgen. Sie werden auch nicht manuell codiert, sondern automatisch aus einer Datenbank. Somit ist es egal, ob der Code durch die vielen Properties länger wird.

Das mit der Überladung des Index-Operators hatte ich schon versucht, leider bin ich daran gescheitert – vielleicht der späten Stunde geschuldet.

@Th69
Ich kann fld nicht aus der Klasse herausoperieren, da, wie bereits geschrieben, es mehrere Klassen gibt, die alle ein "fld" haben und demnach unweigerlich zu Kollisionen kommen würde.

@chilic
Mein Minimalbeispiel enthält nur eine Adressierung. Stelle dir einen langen Ausdruck vor, in dem viele solche Adressierung beteiligt sind – das wird nicht gerade leserlich.

Wenn ich anstelle von

TestObjekt.Field[Testklasse.fld.item1]

die Adressierung

TestObjekt.item1

nutze, so ist der zweite Ausdruck m. E. um einiges einfacher zu lesen.

Ich schaue heute Nachmittag, ob der Vorschlag von T-Virus es sich realisieren lässt.

An euch dreien vielen Dank und ein schönes Wochenende!

René

pollito Themenstarter:in
314 Beiträge seit 2010
vor 3 Jahren

Ich habe alles umgesetzt und es funktioniert super. Darüber hinaus kann ich dank von Properties auf die Verwendung von "fld" verzichten. Hier das Ergebnis eines Testlaufs direkt. Nochmals herzlichen Dank!

namespace isential.DbTables
{
        public partial class DBARTIKEL
        {
                public string NUMMER                    => this.Fields["NUMMER"];
                public string NUMMER_2                  => this.Fields["NUMMER_2"];
                public string BEZEICHNUNG               => this.Fields["BEZEICHNUNG"];
                .
                .
                .
                public string ESUPDATEPRICETIME         => this.Fields["ESUPDATEPRICETIME"];
                public string ESUPDATEPRICE             => this.Fields["ESUPDATEPRICE"];

                public Dictionary<string, string> Fields = new Dictionary<string, string>()
                {
                        { "NUMMER",                     "Das ist NUMMER" },
                        { "NUMMER_2",                   "Das ist NUMMER_2" },
                        { "BEZEICHNUNG",                "Das ist BEZEICHNUNG" },
                        { "KURZBEZ",                    "Das ist KURZBEZ" },
                        .
                        .
                        .
                        { "ESUPDATEPRICETIME",          "Das ist ESUPDATEPRICETIME" },
                        { "ESUPDATEPRICE",              "Das ist ESUPDATEPRICE" }
                };
        }
}

René

4.931 Beiträge seit 2008
vor 3 Jahren

Etwas unelegant finde ich es aber so, daß du die Strings jeweils doppelt angeben mußt.

pollito Themenstarter:in
314 Beiträge seit 2010
vor 3 Jahren

Diese Klassen werden automatisch erstellt und nie von Hand geändert. Deshalb kann man gut mit dieser Unschönheit leben.

René

A
764 Beiträge seit 2007
vor 3 Jahren

Hallo pollito

Du kannst noch nameof() verwenden:


public string Nummer => this.Fields[nameof(Nummer)];

public Dictionary<string, string> Fields = new Dictionary<string, string>()
{
    {nameof(Nummer), "Das ist NUMMER"},
};

Ansonsten noch ein Link zur Info: DynamicObject Class
Sowas sollte aber nur in absoluten Ausnahmefällen Anwendung finden.

Gruß
Alf

pollito Themenstarter:in
314 Beiträge seit 2010
vor 3 Jahren

Danke! Das kann man auch so machen, aber notwendig ist das in diesem speziellen Fall wirklich nicht. Die Keys werden aus den Datenbankschemen einzelner Datenbanktabellen ermittelt, so wie die Values auch, die die restlichen Infos einzelner Datenbankfelder beinhalten. Diese Klassen (eine je Datenbanktabelle) werden komplett automatisch erstellt und es finden keine manuellen Änderungen statt.

Nochmals danke und viele Grüße!

René