[C#] Van specifieke string(s) naar enum(s)

Pagina: 1
Acties:

  • DrDelete
  • Registratie: Oktober 2000
  • Laatst online: 09:24
Ik heb al flink zitten zoeken naar de juiste oplossing op Google, MSDN, etc. etc. maar ik kom er niet uit....

Ik wil weten hoe je van een enum naar een specifieke string converteert en hoe je de weer van die string de enum terug krijgt. Het is de bedoeling dat de naam van de string totaal anders kan zijn dan de enum waarde en vice versa (en da's lastig te vinden!).

bijv. "hallo" string opvoeren, en test als enum terugkrijgen.
en test als enum opvoeren en "hallo" als string terugkrijgen.

[ Voor 4% gewijzigd door DrDelete op 24-03-2005 11:24 ]


  • pjvandesande
  • Registratie: Maart 2004
  • Laatst online: 01-05 19:09

pjvandesande

GC.Collect(head);

Kan toch gewoon met een switch, je base type van een enum kan geen string zijn dus die kan je niet gebruiken, maar een switch will do it.

C#:
1
2
3
4
5
6
7
8
9
10
11
12
switch(enumType)
{
     case MyEnum.Test:
     {
          return "hallo";
     }

     case MyEnum.Test2:
     {
          return "doei";
     }
}

}

  • DrDelete
  • Registratie: Oktober 2000
  • Laatst online: 09:24
Dit bedoelde ik niet. In welk groot verband zie jij deze code dan ? Ik wil de 2 conversie slagen op 1 plek definiëren...

  • pjvandesande
  • Registratie: Maart 2004
  • Laatst online: 01-05 19:09

pjvandesande

GC.Collect(head);

Wat wil je dan precies doen?

  • whoami
  • Registratie: December 2000
  • Laatst online: 09-05 01:02
Maak een class:
code:
1
2
3
4
5
6
7
8
9
public class Bliep
{
     public static MyEnum GetEnumType( string s )
     {
     }

     public static string  GetSTringType( MyEnum e )
      {}
}

https://fgheysels.github.io/


  • riezebosch
  • Registratie: Oktober 2001
  • Laatst online: 04-05 13:09
questa schreef op donderdag 24 maart 2005 @ 12:51:
Kan toch gewoon met een switch, je base type van een enum kan geen string zijn dus die kan je niet gebruiken, maar een switch will do it.

C#:
1
2
3
4
5
6
7
8
9
10
11
12
switch(enumType)
{
     case Myenum.Test:
     {
          return "hallo";
     }

     case Myenum.Test2:
     {
          return "doei";
     }
}

}
Is dit trouwens de enige manier voor het converteren van een string naar enum? Ik vind het namelijk nogal lastig dat ik bij het wegschrijven naar een bestand wel netjes de enum in een string kan krijgen, maar bij het inlezen moet ik omslachtig doen om de string weer naar enum te krijgen. Zelf doe ik het nu door conversie van en naar int (enum is ook van het type int).

Canon EOS 400D + 18-55mm F3.5-5.6 + 50mm F1.8 II + 24-105 F4L + 430EX Speedlite + Crumpler Pretty Boy Back Pack


  • pjvandesande
  • Registratie: Maart 2004
  • Laatst online: 01-05 19:09

pjvandesande

GC.Collect(head);

riezebosch schreef op donderdag 24 maart 2005 @ 13:21:
[...]


Is dit trouwens de enige manier voor het converteren van een string naar enum? Ik vind het namelijk nogal lastig dat ik bij het wegschrijven naar een bestand wel netjes de enum in een string kan krijgen, maar bij het inlezen moet ik omslachtig doen om de string weer naar enum te krijgen. Zelf doe ik het nu door conversie van en naar int (enum is ook van het type int).
Inderdaad gewoon een int gebruiken. Dit werkt prima.

Anders kan het alleen maar d.m.v. een switch na mijn wetenheid.

Verwijderd

Is dit trouwens de enige manier voor het converteren van een string naar enum? Ik vind het namelijk nogal lastig dat ik bij het wegschrijven naar een bestand wel netjes de enum in een string kan krijgen, maar bij het inlezen moet ik omslachtig doen om de string weer naar enum te krijgen. Zelf doe ik het nu door conversie van en naar int (enum is ook van het type int).
Dit kan ook:

C#:
1
2
3
4
5
MyEnum a = MyEnum.ValueA;

string str = a.ToString();

MyEnum b = (MyEnum)Enum.Parse(typeof(MyEnum), str);

  • TlighT
  • Registratie: Mei 2000
  • Laatst online: 22-03 10:40
code:
1
2
3
4
5
6
7
SomeEnum e = SomeEnum.value;

// convert enum to string
string s = e.ToString();   

// convert string back to enum
SomeEnum e2 = (SomeEnum) Enum.Parse(typeof(SomeEnum), s);


Edit:
hmm... net te laat ;)

[ Voor 8% gewijzigd door TlighT op 24-03-2005 13:43 ]


  • DrDelete
  • Registratie: Oktober 2000
  • Laatst online: 09:24
Verwijderd schreef op donderdag 24 maart 2005 @ 13:38:
[...]

Dit kan ook:

C#:
1
2
3
4
5
MyEnum a = MyEnum.ValueA;

string str = a.ToString();

MyEnum b = (MyEnum)Enum.Parse(typeof(MyEnum), str);
Dit is nou net niet de bedoeling.

De a.ToString levert een string waarde op die .NET zelf bepaalt (namelijk de naam van de string is identiek aan de naam van de enum value, hier dus "ValueA"). Dit is niet wenselijk in mijn geval.

  • gorgi_19
  • Registratie: Mei 2002
  • Laatst online: 16:12

gorgi_19

Kruimeltjes zijn weer op :9

Geef dan eens een duidelijk voorbeeld wat je wilt, want ik gok dat bijna niemand echt begrijpt wat je nu wilt.

Digitaal onderwijsmateriaal, leermateriaal voor hbo


  • pjvandesande
  • Registratie: Maart 2004
  • Laatst online: 01-05 19:09

pjvandesande

GC.Collect(head);

DrDelete schreef op donderdag 24 maart 2005 @ 13:57:
[...]


Dit is nou net niet de bedoeling.

De a.ToString levert een string waarde op die .NET zelf bepaalt (namelijk de naam van de string is identiek aan de naam van de enum value, hier dus "ValueA"). Dit is niet wenselijk in mijn geval.
Dan kan het toch niet anders dan met een case, wat is daar op tegen?

  • riezebosch
  • Registratie: Oktober 2001
  • Laatst online: 04-05 13:09
Nee, kan dus niet. Dacht dat je misschien string als type voor je enum op kon geven, maar blijkbaar alleen byte, sbyte, short, ushort, int, uint, long of ulong. :)

Canon EOS 400D + 18-55mm F3.5-5.6 + 50mm F1.8 II + 24-105 F4L + 430EX Speedlite + Crumpler Pretty Boy Back Pack


Verwijderd

Een combinatie van de voorbeelden van questa en whoami zou volgens mij voldoende moeten zijn om een perfect werkende oplossing te maken.

Een andere oplossing is om een class te maken die "voelt als een enum" en bovendien jou gevraagde functionaliteit biedt. In C# kun je zoiets bouwen

Hieronder zie je een snel in elkaar gedraaid voorbeeld van hoe dat er uit zou kunnen zien:

C#:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
public sealed class CustomEnum
{
    private static ArrayList _values = new ArrayList();

    // Define the possible values of CustomEnum as static members,
    // to create an Enumerator type of behavior.
    public static CustomEnum ValueA = new CustomEnum(1, "Hello World!");
    public static CustomEnum ValueB = new CustomEnum(2, "How are you?");
    public static CustomEnum ValueC = new CustomEnum(3, "See you later!");

    private int _id;
    private string _text;

    // The constructor is private. There exists only one instance of every
    // possible value of this "Enumerator".
    private CustomEnum(int id, string text)
    {
        this._id = id;
        this._text = text;
    
        CustomEnum._values.Add(this);
    }

    // Define the ToString() and Parse() methods to do the conversions between
    // CustomEnum and String types.
    
    public override string ToString()
    {
        return this._text;
    }

    public static CustomEnum Parse(string input)
    {
        foreach(CustomEnum e in CustomEnum._values)
        {
            if(e._text == input)
            {
                return e;
            }   
        }
    
        throw new ArgumentOutOfRangeException("input");
    }

    // Define some explicit type conversion operators, to enable casting to and
    // from a string or integer.

    public static explicit operator string(CustomEnum a)
    {
        return a._text;
    }

    public static explicit operator CustomEnum(string a)
    {
        return CustomEnum.Parse(a);
    }

    public static explicit operator int(CustomEnum a)
    {
        return a._id;
    }
    
    public static explicit operator CustomEnum(int a)
    {
        foreach(CustomEnum e in CustomEnum._values)
        {
            if(e._id == a)
            {
                return e;
            }   
        }
    
        throw new ApplicationException("inalid cast");
    }
}


dit kun je dan als volgt gebruiken:

C#:
1
2
3
4
5
6
7
8
9
10
CustomEnum x = CustomEnum.ValueA;

string str = x.ToString();
CustomEnum y = CustomEnum.Parse(str);

int i = (int)x;
CustomEnum z = (CustomEnum)i;

string str2 = (string)x;
CustomEnum t = (CustomEnum)str2;


Ik ben echter niet echt een voorstander van deze oplossing omdat het collega programmeurs behoorlijk in verwarring kan brengen.

  • riezebosch
  • Registratie: Oktober 2001
  • Laatst online: 04-05 13:09
En dat werk jij voor een voorbeeld even helemaal uit, om het vervolgens nog af te raden ook? ;)

Persoonlijk vind ik het ook niet erg netjes om ín de class static members van z'n eigen type aan te maken... Maar goed, misschien dat er argumenten zijn om dat wel te doen.

Canon EOS 400D + 18-55mm F3.5-5.6 + 50mm F1.8 II + 24-105 F4L + 430EX Speedlite + Crumpler Pretty Boy Back Pack


  • D4Skunk
  • Registratie: Juni 2003
  • Laatst online: 20-10-2025

D4Skunk

Kind of Blue

Dit zou het moeten doen (niet getest) :

C#:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
public enum Fruit
{Undefined=-1,Appel=0,Aardbei,Citroen};

private struct FruitMapping {Fruit Id,string Mapped};

private const FruitMapping[] FruitMappings = {
  new FruitMapping(Fruit.Appel,"Groen"),
  new FruitMapping(Fruit.Aardbei,"Rood"),
  new FruitMapping(Fruit.Citroen,"Geel")
}

public string FruitToMapping(Fruit fr) {
  foreach(FruitMapping fm in FruitMappings)
      if (fm.Id==fr) return fm.Mapped;
  return "";
}

public Fruit MappingToEnum(string s) {
  foreach(FruitMapping fm in FruitMappings)
      if (fm.Mapped==s) return fm.Id;
  return Fruit.Undefined;
}


Ik heb dit wel niet gecompiled etc, dus vraag me niet of de syntax goed is :)

[ Voor 33% gewijzigd door D4Skunk op 24-03-2005 17:00 . Reden: nog iets duidelijkere naamgeving variabelen ]


  • DrDelete
  • Registratie: Oktober 2000
  • Laatst online: 09:24
dit ziet er aardig uit, echter ik vind het erg jammer dat er zoveel coderegels voor nodig zijn, maar het zal wel niet anders kunnen.

Dit zag ik ergens anders:

code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
private enum Fruit
{
   [Description("Appeltje")]        Apple,    
   [Description("Banaantje")]       Banana,  
   [Description("Sinasappeltje")]   Orange,
}
    

public static string GetDescription(Enum value)
{
   FieldInfo fi=value.GetType().GetField(value.ToString());
   DescriptionAttribute[] attributes = 
       (DescriptionAttribute[]) 
         fi.GetCustomAttributes(
              typeof     (DescriptionAttribute), false);
   return (attributes.Length>0)?
       attributes[0].Description:value.ToString();
}


Alleen..... hoe gaat ie andere routine er uit zien om van bijv. "Appeltje" de enum Apple terug te krijgen ?

[ Voor 73% gewijzigd door DrDelete op 24-03-2005 19:10 ]


  • riezebosch
  • Registratie: Oktober 2001
  • Laatst online: 04-05 13:09
Namens ons allemaal: wáárom wil je dit?! :?

Als ik het op die manier doe, dan krijg ik bij een Fruit.ToString() nog steeds niet de Description maar gewoon de enum-value...

Misschien dat je wat met dit voorbeeld kan.

[ Voor 86% gewijzigd door riezebosch op 25-03-2005 09:14 ]

Canon EOS 400D + 18-55mm F3.5-5.6 + 50mm F1.8 II + 24-105 F4L + 430EX Speedlite + Crumpler Pretty Boy Back Pack


  • whoami
  • Registratie: December 2000
  • Laatst online: 09-05 01:02
Een enum is imho niet bedoeld om zo te gebruiken.

Als je het toch nog wilt doen, dan is het volgens mij nog de beste manier om met een switch statement te werken.
Met reflectie ga je er afaik niet komen, omdat de omgekeerde weg gewoon niet mogelijk is op die manier.
(Tenzij je dan iedere enum-waarde gaat gaan overlopen, en kijken of ze dat Description Attribute hebben, en dan kijken of de waarde die je ze gegeven hebt mbhv dat attribute overeenkomt. Maw: inefficient.).

https://fgheysels.github.io/


  • TlighT
  • Registratie: Mei 2000
  • Laatst online: 22-03 10:40
whoami schreef op vrijdag 25 maart 2005 @ 09:22:
Tenzij je dan iedere enum-waarde gaat gaan overlopen
Zoiets dus:
code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
public static Enum GetEnum(Type enumType, string description)
{
    if (enumType.BaseType != typeof(Enum))
        throw new ArgumentException("Type is not an enum.", "enumType");

    FieldInfo[] fields = enumType.GetFields(BindingFlags.Static | 
        BindingFlags.Public);

    foreach (FieldInfo field in fields)
    {
        DescriptionAttribute[] attributes = 
            (DescriptionAttribute[]) field.GetCustomAttributes(
            typeof (DescriptionAttribute), false);

        if (attributes.Length > 0 && 
            attributes[0].Description.Equals(description))
        {
            return (Enum) field.GetValue(null);
        }
    }
    
    throw new ArgumentException("Enum description not found.", 
                                "description");
}

  • Daos
  • Registratie: Oktober 2004
  • Niet online
Wat je nodig hebt is een lexical analyser. Je kan er een zelf maken door het volgende character te lezen en aan de hand van deze waarde naar een bepaalde toestand te gaan.

Vb
herkennen strings aa, ba en bb
code:
1
2
3
4
5
[start] -- a --> [a] -- a --> [aa]
   |
   + ----- b --> [b] -- a --> [ba]
                  |
                  + --- b --> [bb]
-- a --> betekent volgende character == a


Je kan ook lex gebruiken. Lex is een programma dat zo'n lexical analyser maakt voor je. Er zijn C# varianten te vinden op internet.

  • D4Skunk
  • Registratie: Juni 2003
  • Laatst online: 20-10-2025

D4Skunk

Kind of Blue

Daos schreef op vrijdag 25 maart 2005 @ 10:20:
Wat je nodig hebt is een lexical analyser.. .
??? :?

Hier had ik nu echt graag wat meer uitleg over gehoord ? Waarom in godsnaam een lexical analyzer, wat heeft dit met het topic te maken ?

  • riezebosch
  • Registratie: Oktober 2001
  • Laatst online: 04-05 13:09
Dan is idd een switch-statement net zo handig ;)

Canon EOS 400D + 18-55mm F3.5-5.6 + 50mm F1.8 II + 24-105 F4L + 430EX Speedlite + Crumpler Pretty Boy Back Pack


  • Daos
  • Registratie: Oktober 2004
  • Niet online
D4Skunk schreef op vrijdag 25 maart 2005 @ 11:21:
[...]


??? :?

Hier had ik nu echt graag wat meer uitleg over gehoord ? Waarom in godsnaam een lexical analyzer, wat heeft dit met het topic te maken ?
Een Lexical Analyzer gaat maar 1 keer over de string die je wilt identificeren. Dit kan een hoop tijd besparen als je keuze hebt uit veel strings.
Een lexical analyzer wordt in een compiler gebruikt om keywords (for, int, static) te herkennen.

Het kan zo geimplementeerd worden. (Heb hier geen C#, daarom maar even in C)
C:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
#include <stdio.h>

int s2e(char *x) {
    /* niet herkend = -1, Groen = 0, Rood = 1, Geel = 2 */

    switch (x[0]) {
    case 'G':
        switch (x[1]) {
        case 'e':
            return 2;
        case 'r':
            return 0;
        default:
            return -1;
        }
    case 'R':
        return 1;
    default:
        return -1;
    }
}

int main() {
    char *x = "Geel";
    int res = s2e(x);

    printf("%s = %d\n", x, res);


    return 0;
}


edit:
Bovenstaande code herkend Geil ook als Geel. Je kan dit oplossen door de hele string te herkennen voordat je iets teruggeeft.
C:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
#include <stdio.h>

enum {
    ONBEKEND = -1,
    GROEN,
    ROOD,
    GEEL
};

char *kleuren[] = {
    "Groen",
    "Rood",
    "Geel"
};

int s2e(char *x) {
    if (x == 0)
        return ONBEKEND;

    switch (x[0]) {
    case 'G':
        switch (x[1]) {
        case 'e':
            switch (x[2]) {
            case 'e':
                switch (x[3]) {
                case 'l':
                    return GEEL;
                default:
                    return ONBEKEND;
                }
            default:
                return ONBEKEND;
            }
        case 'r':
            switch (x[2]) {
            case 'o':
                ...
                ...
}

int main() {
    char *x;
    int res;

    x = "Geel";
    res = s2e(x);
    if (res != ONBEKEND)
        printf("%s = %s\n", x, kleuren[res]);
    else
        printf("%s is niet herkend\n", x);

    return 0;
}



Vraagje voor TS:
Als ik het goed begrijp doe je dit:
1 Je zet een getal via een enum om in string en schrijft dit naar een bestand.
2 Je leest string uit een bestand en zet het weer om in het bijbehorende getal.

Waarom schrijf je niet gewoon het getal naar het bestand?

[ Voor 54% gewijzigd door Daos op 25-03-2005 15:44 ]


  • D4Skunk
  • Registratie: Juni 2003
  • Laatst online: 20-10-2025

D4Skunk

Kind of Blue

@Daos :
Ik weet wel wat een lexical analyzer is, maar dit is imho een beetje overkill.. :*)

Nuff said, ik denk dat de TS nu wel genoeg voorbeelden heeft, om er toch tenminste 1 uit te implementeren...

@TS :
ik sluit me aan bij riezebosch : waarom wil je dit eigenlijk ?
Als je hierover wat uitleg kan geven, zal misschien wel blijken dat je de oplossing i/d verkeerde hoek aan het zoeken bent, dus ga je gang.

  • DrDelete
  • Registratie: Oktober 2000
  • Laatst online: 09:24
D4Skunk schreef op vrijdag 25 maart 2005 @ 14:52:
@Daos :
Ik weet wel wat een lexical analyzer is, maar dit is imho een beetje overkill.. :*)

Nuff said, ik denk dat de TS nu wel genoeg voorbeelden heeft, om er toch tenminste 1 uit te implementeren...

@TS :
ik sluit me aan bij riezebosch : waarom wil je dit eigenlijk ?
Als je hierover wat uitleg kan geven, zal misschien wel blijken dat je de oplossing i/d verkeerde hoek aan het zoeken bent, dus ga je gang.
De enumerates zijn onderdeel van een soort object DB. De enum waarden van deze object DB zijn in strings, echter in de applicatie willen we niet met strings werken omdat dit vaak lelijke code oplevert bij afvragingen (veel or statements). Op één plek wil ik dan de conversie van de applicatie enum naar de "object DB enum" bijhouden.
Pagina: 1