Entwickler-Ecke

Basistechnologien - Benötige hilfe beim Auslesen einer Enum


-CrimeTime- - So 28.11.10 22:03
Titel: Benötige hilfe beim Auslesen einer Enum
Hallo,
ich möchte gerne aus einer enum Daten vergleichen, und mir dann den Name der Enum ausgeben lassen, ich habe mir es so gedacht:


C#-Quelltext
1:
2:
3:
4:
if(enumEnthält(Zahl))
{
dein Geld reicht für Enum(getränk)
}


die Zahl wird bereits ausgelesen, mein Problem ist nur das vergleichen mit der enum und die wieder gabe des Getränks.


hier der Beispiel Code der Enum:

C#-Quelltext
1:
2:
3:
4:
5:
6:
7:
    public enum Getränke : int
    {
        Milch = 100,
        Cola = 110,
        Kakao = 105,
        Limo = 120
    }


Moderiert von user profile iconChristian S.: Code- durch C#-Tags ersetzt


jaenicke - So 28.11.10 23:29

Meinst du so etwas?

C#-Quelltext
1:
2:
3:
4:
foreach (int a in Enum.GetValues(typeof(Getränke)))
{
    if (a < Value)
...


Trashkid2000 - So 28.11.10 23:53

Weiß nicht, aber vielleicht wäre es bei so einem ungeordneten Enum hilfreich, die Werte erst einmal in die richtige Reihenfolge zu bringen:

C#-Quelltext
1:
2:
var orderedValues = Enum.GetValues(typeof(Getränke)).OfType<Getränke>()
                        .OrderBy(g => (int)Enum.Parse(typeof(Getränke), g.ToString()));

Und dann vielleicht noch die Abfrage, welche Werte überhaupt in dem Bereich des Wertes liegen:

C#-Quelltext
1:
var passingValues = orderedValues.Where(g => (int)g <= value);                    
Und dann hat mit einer ForEach durchgehen.
Marko


-CrimeTime- - Mo 29.11.10 00:19

also wenn ich es so versuche:

Quelltext
1:
if (Enum.GetValues(typeof(Getränke)) == Zahl)                    


bekomme ich diese Fehlermeldung:
Operator '==' cannot be applied to operands of type 'System.Array' and 'int'


jaenicke - Mo 29.11.10 00:21

GetValues gibt dir alle Werte zurück, die kannst du auch nicht alle gleichzeitig mit einem Wert vergleichen.


Kha - Mo 29.11.10 00:31

user profile iconTrashkid2000 hat folgendes geschrieben Zum zitierten Posting springen:

C#-Quelltext
1:
.OrderBy(g => (int)Enum.Parse(typeof(Getränke), g.ToString()));                    
Ein weniger abenteuerlicher Weg wäre .OrderBy(g => g) ;) .


Trashkid2000 - Mo 29.11.10 07:26

user profile iconKha hat folgendes geschrieben Zum zitierten Posting springen:
user profile iconTrashkid2000 hat folgendes geschrieben Zum zitierten Posting springen:

C#-Quelltext
1:
.OrderBy(g => (int)Enum.Parse(typeof(Getränke), g.ToString()));                    
Ein weniger abenteuerlicher Weg wäre .OrderBy(g => g) ;) .
Ups :oops: Habe noch nicht so die Megaerfahrungen mit Linq.
Aber gut zu wissen.


-CrimeTime- - Mo 29.11.10 07:29

das Problem bei mir ist das ich bereits eine geöffnete "foreach" Schleife habe, somit denke ich mir benötige ich eine If Schleife um den neuen "foreach" code den jaenicke gepostet hat nutzen zu können.

Ich bin jetzt bestimmt schon einige Stunden am Tüfteln wie ich am besten die if Schleife Realisiere, doch leider habe ich noch nicht viel mit sowas gearbeitet.


jaenicke - Mo 29.11.10 07:57

Ich kann LINQ auch nicht, aber es wurde doch schon gepostet:

C#-Quelltext
1:
2:
3:
4:
            foreach (Getränke a in Enum.GetValues(typeof(Getränke)).OfType<Getränke>().Where(g => (int)g <= Value))
            {
                MessageBox.Show(a.ToString());
            }


-CrimeTime- - Mo 29.11.10 12:14

da beisst die Maus kein Faden ab ich benötige das in einem if String, weil der sonst x mal kakao schreibt, und mit dem if String wird dies verhindert, da er dies dann so handelt:


C#-Quelltext
1:
2:
3:
4:
5:
6:
7:
If (Getränk == Zahl)
{
foreach schleife von jaenicke
}
else
{
}


Moderiert von user profile iconChristian S.: C#-Tags hinzugefügt


Trashkid2000 - Mo 29.11.10 14:34

Hallo,

also Du willst nur den string des Wertes aus dem Enum zurückgeben, wenn der Wert exakt passt?
Dann könnte die Abfrage so aussehen:

C#-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
int i = 100;
if (Enum.IsDefined(typeof(Getränke), i))
{
   Getränke getränk = (Getränke)i;
}
else

   //der Wert wurde nicht im Enum gefunden
}
Hatte es aber eigentlich so verstanden, dass Du das (teuerste) Getränk ausgeben willst, was man sich mit dem Wert kaufen kann. Dann müsstest Du die Werte per Schleife durchlaufen. Oder Du filterst erst alle Getränke raus, die man mit dem Wert kaufen könnte, und davon dann noch den Max-Wert:

C#-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
int i = 100;
IEnumerable<Getränke> getränkeImBereich = Enum.GetValues(typeof(Getränke)).OfType<Getränke>().Where(g => (int)g <= i);
if (getränkeImBereich != null && getränkeImBereich.Count() > 0)
{
   Getränke teuerstesGetränk = getränkeImBereich.Max();
}
else

   //keine Getränke für den Wert zu haben!
}

LG


-CrimeTime- - Mo 29.11.10 15:10

sorry für die ganzen Missverständnisse, aber ich benötige es nun endgültig in dieser Form:


Quelltext
1:
if (!((Enum.GetValues(typeof(Getränke(Zahl)) != -1) |(Enum.GetValues(typeof(Essen(Zahl) != -1)))                    


doch leider bekomme ich bei diesem code diese Fehlermeldung:
Method name expected und er markiert (typeof(Getränke rot. das selbe passiert auch bei Essen.

edit:
die Enum Essen existiert bereits!


Kha - Mo 29.11.10 20:06

Das geht ab 4.0 ganz einfach:

C#-Quelltext
1:
Enum.IsDefined(typeof(Getränk), Zahl)                    

Ansonsten kannst du diese Methode natürlich leicht mit jaenickes foreach-Code nachbauen, wenn du dort "<" durch "==" ersetzt. Natürlich geht es auch wieder mit LINQ, aber das wäre wohl noch etwas zu früh :) .


Trashkid2000 - Mo 29.11.10 21:32

Sorry, aber ich finde echt, dass schon alle möglichen Abfragemechanismen gepostet wurden. Und da spielt es auch keine Rolle, ob Du nun ein oder zwei Enums abfragen willst!
Und die Frage, ob Du abfragen willst, ob nun genau ein Wert in den Enum (oder den 2) enthalten sein muss, oder nur der maximale Wert aus dem Enum zurückgegeben werden soll (bei 2 schon komlizierter) hast Du auch noch nicht beantwortet.

Vielleicht schreibst Du einfach mal, was Du erreichen willst. Das wäre mal ganz interessant, um weiter zu helfen!
Marko


-CrimeTime- - Di 30.11.10 02:50

Danke Kha für den Code, doch leider bringt er nicht das gewünschte Ergebniss, hier wie ich ihn verwende:

Quelltext
1:
                    if (!((Enum.IsDefined(typeof(Getränke), Zahl) != -1) | (Enum.IsDefined(typeof(Essen), Zahl) != -1)))                    


Fehlermeldung: Operator '!=' cannot be applied to operands of type 'bool' and 'int'

@ Trashkid:
Also ich möchte einfach wenn die Zahl in Essen oder Getränke vorhanden ist das er den Code in der If Schleife durchführt.

Edit:
Ich habe es nun so:


Quelltext
1:
2:
3:
4:
                    if (!((Enum.IsDefined(typeof(Getränke), Zahl)) == true | (Enum.IsDefined(typeof(Essen), Zahl)) == true))
                    {
                        continue;
                    }

unter diesem Code ist eine Weitere If Schleife, die ausgeführt werden soll wenn die Zahl in Getränke oder Essen vorhanden ist, doch leider findet er diese Zahl nicht obwohl sie in der Enum Vorhanden ist, und geht nicht zur nechsten If Schleife.


jaenicke - Di 30.11.10 06:50

Was für eine Schleife? Ich sehe keine. [http://if-schleife.de/]

Und dann frage ich mich, warum du es dir eigentlich so kompliziert machst:

C#-Quelltext
1:
2:
3:
if (Enum.IsDefined(typeof(Getränke), Value) | Enum.IsDefined(typeof(Essen), Value))
{
    ...


-CrimeTime- - Di 30.11.10 07:04

das sieht doch schonmal viel besser aus, nur irgendwie glaube ich das ich es mit GetValue brauche weil ich ja nicht den Name des Getränks bzw. des Essens auslesen möchte sondern die Zahl.

Oder macht der Code das so?


jaenicke - Di 30.11.10 07:07

Wie meinen? :gruebel:

Der Code schaut einfach nur, ob der Wert in einem der beiden Enums drin ist, der liest gar nix aus. :nixweiss:


-CrimeTime- - Di 30.11.10 07:29

also ich Teste ihn jetzt schon die ganze Zeit, und mir kommt es so vor als würde er nur den Name des Getränks oder Essens Auslesen, und nicht den Wert.

Edit:
was natürlich auch sein kann ist das meine 2. if Schleife einfach nur Datenschrott ist.

hier der Code davon:


C#-Quelltext
1:
2:
3:
4:
if (Enum.IsDefined(typeof(Getränk), Zahl) && blacklist.IndexOf(Zahl) == -1 && checkbox1.Checked)
{
MessageBox.Show("Test");
}


Moderiert von user profile iconChristian S.: Code- durch C#-Tags ersetzt


jaenicke - Di 30.11.10 07:53

Hast du dir denn beim Debuggen einmal die einzelnen Werte angeschaut?

Und bist du sicher, dass && richtig ist? Ich dachte das wäre bitweise, d.h. hier wäre & richtig.


-CrimeTime- - Di 30.11.10 08:10

Super, genau das war es wohl jedenfalls geht es nun 1A.

Danke euch allen die beteiligt waren :)

Edit:

nun habe ich nur noch ein Problem das wäre wie ich in einer Emun einen wert mit Leerzeichen mache z.B.
Frischer Kaffee = 154


jaenicke - Di 30.11.10 09:46

user profile icon-CrimeTime- hat folgendes geschrieben Zum zitierten Posting springen:
nun habe ich nur noch ein Problem das wäre wie ich in einer Emun einen wert mit Leerzeichen mache z.B.
Frischer Kaffee = 154
Irgendwie verwechselst du da was, das ist der Bezeichner in C#, das hat nichts mit dem zu tun, was du ggf. dem Benutzer anzeigst. Und Bezeichner können nun einmal keine Leerzeichen enthalten, woher sollte C# auch wissen, dass das zusammengehören soll? :nixweiss:


-CrimeTime- - Di 30.11.10 10:06

ich überprüfe aber noch den Name, und somit brauche ich dort ein Leerzeichen oder ich muss es aus einer Externen Textdatei überprüfen, was ich nun so machen werde.


Greenberet - Di 30.11.10 10:11

Ich glaube für dich wäre ein Dictionary<string,int> besser geeignet als ein Enum.

Falls du unbedingt ein Enum brauchst kannst du ja statt dem Leerzeichen ein Unterstrich machen. Wenn du jetzt die Texteingabe hast, ersetzt du im Code( string.replace ) alle Leerzeichen durch Unterstriche. So kommst du auch zu deinem "Frischer Kaffee"


Yogu - Di 30.11.10 14:40

user profile iconGreenberet hat folgendes geschrieben Zum zitierten Posting springen:
Ich glaube für dich wäre ein Dictionary<string,int> besser geeignet als ein Enum.

Dem stimme ich zu, wobei es vielleicht noch einer Erklärung bedarf:

Enumerations sind Aufzählungen. Dabei sind die Zahlenwerte (also das, was nach dem = steht), normalerweise unbedeutend. In manchen Fällen gibt man ihn auch an, allerdings handelt es sich dann eher um eine eindeutige Zahl, z.B. die Artikelnummer.

Das technische Problem ist, dass kein Wert doppelt auftreten kann. Wenn du nun zwei Produkte hast, die gleich viel kosten, kommst du mit deinem Ansatz nicht weiter. Außerdem lässt sich die Datenbank schlecht erweitern, da alle Artikel bereits beim Programmieren feststehen müssen.

Ein Dictionary dagegen ist erweiterbar und darf mehrere Einträge mit gleichem Wert (natürlich nicht mit gleichem Namen) enthalten. Außerdem sind auch Leerzeichen erlaubt.

Um im Dictionary nach passenden Produkten zu suchen, kannst du folgende Schleife verwenden:


C#-Quelltext
1:
2:
3:
4:
5:
foreach (var item in dictionary) {
  if (item.Value <= geld) {
    MessageBox.Show(item.Key);
  }
}


-CrimeTime- - Di 30.11.10 15:38

Also danke für all die weiteren Ratschläge, aber ich mache es Lieber in einer neuen Ini-Datei wo ich die Namen der Getränke / Essen ablagere das ich das Problem mit dem Leerzeichen löse, ist auch so besser für meine Methode, das neue Problem wäre dann nur wie ich das anstelle weil laut meiner Erfahrung kann man in eine *.ini nicht so Auslesen wie ich es vorhabe (den gesamten Text von [Getränke] Auslesen und schauen ob der Name vorhanden ist) oder liege ich da Falsch?

Eine *.ini Lade / Lese Funktion besitze ich bereits!


Yogu - Di 30.11.10 16:01

Schonmal was von Punkten gehört? :gruebel:

user profile icon-CrimeTime- hat folgendes geschrieben Zum zitierten Posting springen:
ich mache es Lieber in einer neuen Ini-Datei wo ich die Namen der Getränke / Essen ablagere

Gut, so kannst du die Daten natürlich auf die Festplatte speichern. Das hat aber eigentlich nichts damit zu tun, wie du sie während der Laufzeit verwaltest. Ein Dictionary eignet sich übrigens wirklich gut, um in eine Ini-Datei gespeichert oder aus einer ausgelesen zu werden, denn es ist im Grunde genau so aufgebaut.


C#-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
    private Dictionary<stringint> loadDictionary(string iniData) {
      Dictionary<stringint> dictionary = new Dictionary<stringint>();

      string[] lines = iniData.Split('\n');
      foreach (string line in lines) {
        string[] data = line.Split(new char[] { '=' }, 2);
        dictionary[data[0]] = int.Parse(data[1]);
      }

      return dictionary;
    }


user profile icon-CrimeTime- hat folgendes geschrieben Zum zitierten Posting springen:
das neue Problem wäre dann nur wie ich das anstelle weil laut meiner Erfahrung kann man in eine *.ini nicht so Auslesen wie ich es vorhabe (den gesamten Text von [Getränke] Auslesen und schauen ob der Name vorhanden ist) oder liege ich da Falsch?

Wie meinst du das?


-CrimeTime- - Di 30.11.10 16:19

also für mich eignet sich eine Dictionary auf garkeinen fall, da ich dieses Programm in mehreren Sprachen Veröffentliche und wenn dann in der Dictionary Deutsche Getränke oder Essen sind sieht es verdammt blöd aus wenn dann ein Russe sich das Programm ansieht.

Also ich meine es so:
Wenn ich versuche eine *.ini file Auszulesen deren Inhalt so ist

Quelltext
1:
2:
3:
4:
[Inhalt]
A=B
C=D
E=F


kann ich nur das hinter den = Zeichen Auslesen, was eigentlich nicht Schlimm wäre da ich ja einfach das was ich brache hinter dem = Schreibe, nur der knackpunkt ist wie stelle ich das an das der Endweder die gesamte Ini-File Öffnet und jederzeit schauen kann ob der Name des Getränks/Essens in der Datei vorhanden ist.

Aber am Liebsten wäre mir es so:

Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
[Getränke]
Cola
Kaffee
Saft
Limonade
Wasser
[Essen]
Jägerschnitzel
Weisswurst
Rotkohl mit Klöse


das er dies so verwendet und auch Checkt ob der Name in der Datei bzw. *.ini vorhanden ist.

sollten weitere Fragen sein, bitte Fragen ;)


Yogu - Di 30.11.10 17:05

user profile icon-CrimeTime- hat folgendes geschrieben Zum zitierten Posting springen:
also für mich eignet sich eine Dictionary auf garkeinen fall, da ich dieses Programm in mehreren Sprachen Veröffentliche und wenn dann in der Dictionary Deutsche Getränke oder Essen sind sieht es verdammt blöd aus wenn dann ein Russe sich das Programm ansieht.

Aha, und mit einem Enum geht das besser?

Aus deinen Fragen schließe ich, dass du während des Programmablaufs ständig aus der Ini-Datei lesen willst, ist das richtig? Das scheint mir nicht so ganz das richtige Konzept zu sein.

Nochmal zusammengefasst, wie ich es lösen würde:


Um zu prüfen, ob ein Name im Dictionary vorhanden ist, kannst du ContainsKey verwenden.


-CrimeTime- - Di 30.11.10 17:35

wenn ich dies nun mit einem Dictionary machen möchte, gibts wieder Probleme beim "wie mache ich die If Schleife", aber ich werde es mal so versuchen wie du es beschrieben hast.

Edit:
Also ich bekomme schonmal nicht die komplette *.ini gelesen weil meine ReadIni Funktion nur Werte zurück gibt, wie kann ich die Gesamte Datei einlesen und dann in den Dictionary packen?


Yogu - Di 30.11.10 19:02

user profile icon-CrimeTime- hat folgendes geschrieben Zum zitierten Posting springen:
"wie mache ich die If Schleife"

Gar nicht, denn es gibt keine If-Schleifen [http://if-schleife.de/] ;) Ne, was meinst du damit denn?

user profile icon-CrimeTime- hat folgendes geschrieben Zum zitierten Posting springen:
wie kann ich die Gesamte Datei einlesen und dann in den Dictionary packen?

In meinem vorletzten Beitrag hab ich doch den Code dazu gepostet.


-CrimeTime- - Di 30.11.10 19:07

(string iniData) wie komme ich an das iniData?

und zu dem if, wurde auch schon vorher gepostet, ich muss ja die Daten vergleichen in einer If Schleife, und mit der Dictionary wird sich da sicherlich was ändern.

Edit:
habe es nun hinbekommen mit dem Lesen einer Kompletten Ini-File, doch leider klappt nun der Split von Yogu nicht mehr da es ein string[] ist.

hier sein Code:


Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
        private Dictionary<string, int> loadDictionary(string[] iniData)
        {
            Dictionary<string, int> dictionary = new Dictionary<string, int>();

            string[] lines = iniData.Split('\n');
            foreach (string line in lines)
            {
                string[] data = line.Split(new char[] { '=' }, 2);
                dictionary[data[0]] = int.Parse(data[1]);
            }
            return dictionary;
           
        }


Das .Split it Rot unterstrichen mit dieser Fehlermeldung:'System.Array' does not contain a definition for 'Split' and no extension method 'Split' accepting a first argument of type 'System.Array' could be found (are you missing a using directive or an assembly reference?)


Yogu - Di 30.11.10 19:35

user profile icon-CrimeTime- hat folgendes geschrieben Zum zitierten Posting springen:
wie komme ich an das iniData?

Das ist der Inhalt der Ini-Datei, den kannst du z.B. so auslesen:


C#-Quelltext
1:
2:
3:
string iniData;
using (StreamReader reader = new StreamReader(fileName, new UTF8Encoding()))
  iniData = reader.ReadToEnd();


user profile icon-CrimeTime- hat folgendes geschrieben Zum zitierten Posting springen:
und zu dem if, wurde auch schon vorher gepostet, ich muss ja die Daten vergleichen in einer If Schleife, und mit der Dictionary wird sich da sicherlich was ändern.

Dafür hab ich dir auch schon mal etwas Quelltext gepostet.

user profile icon-CrimeTime- hat folgendes geschrieben Zum zitierten Posting springen:
Edit:
habe es nun hinbekommen mit dem Lesen einer Kompletten Ini-File, doch leider klappt nun der Split von Yogu nicht mehr da es ein string[] ist.

Mach das iniData wieder zu einem string und lese ihn wie oben beschrieben aus, dann müsste es klappen.

Edit: Fehler korrigiert (hervorgehoben)


-CrimeTime- - Di 30.11.10 19:40

also ich bekomme hier die Fehlermelung: 'System.IO.StreamReader' is a 'type' but is used like a 'variable'
und es Markiert StreamReader nach dem "=".

hier der Code:

Quelltext
1:
2:
            using (StreamReader reader = StreamReader(Application.StartupPath + "\\deDE.ini", new UTF8Encoding()))
            iniData = reader.ReadToEnd();


Yogu - Di 30.11.10 20:11

Sorry, da hat ein new gefehlt.


-CrimeTime- - Di 30.11.10 20:27

der Code von dir Funktioniert Super, doch wie packe ich das nun in meine If Schleife?

Das einzigste was ich von dir gefunden habe ist eine foreach Schleife unzwar diese hier:


Quelltext
1:
2:
3:
4:
5:
foreach (var item in dictionary) {
  if (item.Value <= geld) {
    MessageBox.Show(item.Key);
  }
}


so sieht momentan meine If Schleife aus:

Quelltext
1:
 if ((Enum.IsDefined(typeof(Getränk), Zahl)) & blacklist.IndexOf(Zahl) == -1 & checkbox1.Checked))                    


jaenicke - Di 30.11.10 20:30

user profile icon-CrimeTime- hat folgendes geschrieben Zum zitierten Posting springen:
der Code von dir Funktioniert Super, doch wie packe ich das nun in meine If Schleife?
:autsch:
Da verliert man dann ziemlich schnell die Lust zu helfen.


-CrimeTime- - Di 30.11.10 20:41

sorry jaenicke, aber was soll ich machen wenn ich einen Vorschlag bekomme doch mit der Funktion des Vorschlags noch nie gearbeitet habe dazu ist das C# gebiet noch recht Neuland für mich, und um die Frage mit den Basic's vorzubeugen ja ich habe mich schon durch ein paar Kapitel gelesen doch leider noch nicht die Zeit gehabt mir das Komplette E-Book durchzulesen.


Yogu - Di 30.11.10 21:26

user profile iconjaenicke bezog sich wahrscheinlich auch auf meinen Kommentar:

user profile iconYogu hat folgendes geschrieben Zum zitierten Posting springen:
user profile icon-CrimeTime- hat folgendes geschrieben Zum zitierten Posting springen:
"wie mache ich die If Schleife"

Gar nicht, denn es gibt keine If-Schleifen [http://if-schleife.de/] ;) Ne, was meinst du damit denn?

Es keine If-Schleifen; was du meinst, ist eine If-Struktur oder eine bedingte Anweisung.

Deine "If Schleife" prüft also, ob ein Getränk existiert, dessen Preis Zahl beträgt, ob es nicht auf der Blacklist steht und schließlich, ob irgendeine Checkbox aktiviert ist.

Nun, meine Schleife sucht nach Produkten, die unter einen bestimmten Preis fallen. Das "unter einen Preis fallen" in ein "mit dem gegebenen Preis genau übereinstimmen" zu ändern, dürfte kein Problem darstlelen, wenn man sich den Code anschaut. Und den Rest kannst du ja so belassen, wie er ist.


jaenicke - Di 30.11.10 21:40

Das meinte ich, ja. Und vorher hatte ich es ja auch schon geschrieben.
user profile iconjaenicke hat folgendes geschrieben Zum zitierten Posting springen:
Was für eine Schleife? Ich sehe keine. [http://if-schleife.de/]
Und wenn es dann doch konsequent weiter falsch gemacht wird, zweifle ich halt ein wenig, ob ich noch viel Lust habe weiter zu helfen.