[C#]Enum.Parse met Reserved word in Enum

Pagina: 1
Acties:

Acties:
  • 0 Henk 'm!

  • TeeDee
  • Registratie: Februari 2001
  • Laatst online: 16:01
Ik krijg via een WCF laag in mijn Silverlight App. een aantal Enums door. In de basis (VB.net) worden deze Enums gemaakt alsvolgt:
Visual Basic .NET:
1
2
3
4
5
6
Enum PasswordPolicy
None
Simple
[Default]
Strong
End Enum
Enums waarbij een [Default] instaat gaan in onderstaande methode volledig onderuit. Er volgt een InvalidCastException en dan houdt het uiteraard gewoon op.
C#:
1
2
3
4
5
6
7
8
9
10
11
12
13
public List<PropertyComboBoxSource> GetComboBoxSource<T>()
{
    List<PropertyComboBoxSource> PropertySource = new List<PropertyComboBoxSource>();
    T[] ComboBoxItems = Utility.EnumGetValues<T>(); //Silverlight ! Enum.GetValues();
    foreach (T PropertyItem in ComboBoxItems)
    {
        PropertyComboBoxSource ComboBoxItem = new PropertyComboBoxSource();
        ComboBoxItem.Key = (int)Enum.Parse(typeof(T), PropertyItem.ToString(), true);
        ComboBoxItem.Value = PropertyItem.ToString();
        PropertySource.Add(ComboBoxItem);
    }
    return PropertySource;
}

Waarbij PropertyComboBoxSource een kleine wrapper class is die bestaat uit een int en string.

Nu dacht ik, ik controleer in de methode gewoon of de PropertyItem value een "[Default]" is en cast dan op de zelfde ( (int)pp) ) manier naar int. Maar het is voor zover ik weet niet mogelijk om een PropertyItem (uit de GetComboBoxSource) direct te casten naar int.

Het prependen van PropertyItem met een @ geeft een InvalidCast omdat ik niet mag casten naar een string, terwijl ProperyItem.ToString() een cast naar string impliceert.

Zonder het Generic gedeelte, dus
C#:
1
2
3
4
5
6
7
8
PasswordPolicy[] ppPol = Utility.EnumGetValues<PasswordPolicy>();
foreach (PasswordPolicy pp in ppPol)
{
    PropertyComboBoxSource propsource = new PropertyComboBoxSource();
    propsource.Key = (int)pp;
    propsource.Value = pp.ToString();
    cbxSource.Add(propsource);
}
gaat het perfect.

[ Voor 4% gewijzigd door TeeDee op 06-03-2009 09:10 . Reden: topic afmaken voordat ik naar huis ga :D ]

Heart..pumps blood.Has nothing to do with emotion! Bored


Acties:
  • 0 Henk 'm!

  • Woy
  • Registratie: April 2000
  • Niet online

Woy

Moderator Devschuur®
Op welke regel gaat het precies mis dan? Op de ToString()?

Wat betekenen de [ en ] in VB.NET? In C# zou het op deze manier gewoon betekenen dat een Enum Item een attribute heeft, maar in VB.NET zal dat wel anders werken.

[ Voor 66% gewijzigd door Woy op 06-03-2009 09:11 ]

“Build a man a fire, and he'll be warm for a day. Set a man on fire, and he'll be warm for the rest of his life.”


Acties:
  • 0 Henk 'm!

  • TeeDee
  • Registratie: Februari 2001
  • Laatst online: 16:01
Het gaat mis op
C#:
1
ComboBoxItem.Key = (int)Enum.Parse(typeof(T), PropertyItem.ToString(), true); 
.
Waarbij PropertyItem een Value van None heeft. De brackets zijn (volgens de VB.net man) gelijk aan de @ in c#.

[ Voor 16% gewijzigd door TeeDee op 06-03-2009 09:17 ]

Heart..pumps blood.Has nothing to do with emotion! Bored


Acties:
  • 0 Henk 'm!

  • Woy
  • Registratie: April 2000
  • Niet online

Woy

Moderator Devschuur®
Wat ik me eigenlijk afvraag is waarom je het volgende doet
C#:
1
ComboBoxItem.Key = (int)Enum.Parse(typeof(T), PropertyItem.ToString(), true);

en niet
C#:
1
ComboBoxItem.Key = (int)PropertyItem;


Dat is namenlijk de code die overeenkomt met je non-generic versie die gewoon goed werkt.

[ Voor 17% gewijzigd door Woy op 06-03-2009 09:12 ]

“Build a man a fire, and he'll be warm for a day. Set a man on fire, and he'll be warm for the rest of his life.”


Acties:
  • 0 Henk 'm!

  • TeeDee
  • Registratie: Februari 2001
  • Laatst online: 16:01
Woy schreef op vrijdag 06 maart 2009 @ 09:11:
Wat ik me eigenlijk afvraag is waarom je het volgende doet
C#:
1
ComboBoxItem.Key = (int)Enum.Parse(typeof(T), PropertyItem.ToString(), true);

en niet
C#:
1
ComboBoxItem.Key = (int)PropertyItem;


Dat is namenlijk de code die overeenkomt met je non-generic versie die gewoon goed werkt.
Bij (int)PropertyItem krijg ik netjes de melding "Cannot convert type 'T' to int. Als er op wat voor manier dan ook een mogelijkheid is om een Type T direct naar int (tryparse, parse, as int etc. ook geprobeerd inmiddels) ben ik ook klaar. Maar het lijkt erop dat het Generic gedeelte een beetje roet in het spreekwoordelijke eten gooit.

Heart..pumps blood.Has nothing to do with emotion! Bored


Acties:
  • 0 Henk 'm!

  • Niemand_Anders
  • Registratie: Juli 2006
  • Laatst online: 09-07-2024

Niemand_Anders

Dat was ik niet..

Als ik kijk naar hoe je in de twee situaties de key toewijst vraag ik me af waarom je dat bij de generic method ineens anders hebt gedaan. Als jij aangeeft dat T van het type enum moet zijn (generic constraint) kun je altijd de enum value direct terug casten naar een integer.

Je kunt daarna gewoon op regel 8 'Key = (int) PropertyItem' kunnen doen omdat PropertyItem namelijk een enum value is. Maar ik moet ook direct vermelden dat je benamingen van de variabelen erg verwarrend overkomen. Ik zou ComboBoxItems dus enumValues hebben genoemd en PropertyItem enumValue.

If it isn't broken, fix it until it is..


Acties:
  • 0 Henk 'm!

  • Woy
  • Registratie: April 2000
  • Niet online

Woy

Moderator Devschuur®
TeeDee schreef op vrijdag 06 maart 2009 @ 09:15:
[...]

Bij (int)PropertyItem krijg ik netjes de melding "Cannot convert type 'T' to int. Als er op wat voor manier dan ook een mogelijkheid is om een Type T direct naar int (tryparse, parse, as int etc. ook geprobeerd inmiddels) ben ik ook klaar. Maar het lijkt erop dat het Generic gedeelte een beetje roet in het spreekwoordelijke eten gooit.
Een beetje vieze hack daarvoor is
C#:
1
ComboBoxItem.Key = (int)(object)PropertyItem;

edit:
of natuurlijk gewoon
C#:
1
ComboBoxItem.Key = Convert.ToInt32(PropertyItem);

8)7
Niemand_Anders schreef op vrijdag 06 maart 2009 @ 09:15:
Als jij aangeeft dat T van het type enum moet zijn (generic constraint) kun je altijd de enum value direct terug casten naar een integer.
Enum is toch geen valide constraint. Volgens mij kun je alleen 'struct' als constraint opleggen, maar dat dekt nog niet alles af, en je hebt nog hetzelfde probleem.

[ Voor 32% gewijzigd door Woy op 06-03-2009 09:23 ]

“Build a man a fire, and he'll be warm for a day. Set a man on fire, and he'll be warm for the rest of his life.”


Acties:
  • 0 Henk 'm!

  • TeeDee
  • Registratie: Februari 2001
  • Laatst online: 16:01
Woy schreef op vrijdag 06 maart 2009 @ 09:18:
[...]

Een beetje vieze hack daarvoor is
C#:
1
ComboBoxItem.Key = (int)(object)PropertyItem;


[...]

Enum is toch geen valide constraint. Volgens mij kun je alleen 'struct' als constraint opleggen, maar dat dekt nog niet alles af, en je hebt nog hetzelfde probleem.
Ook daarbij krijg ik een "A first chance exception of type 'System.InvalidCastException". We gaan er toch niet aan voorbij dat dit een Silverlight applicatie betreft?

De 'oplossing' in deze is simpel: Alleen voor deze enum de niet Generic gebruiken, met het risico dat nieuwe/aangepaste enums de hele handel onderuit halen. Of de enum aanpassen in de basis (nu kan het nog) en er om heen werken. Dat zijn in dit geval 2 pragmatische oplossingen alleen wil ik gewoon weten waarom het bij deze specifieke enum fout gaat.
Woy schreef op vrijdag 06 maart 2009 @ 09:18:
[...]
Enum is toch geen valide constraint. Volgens mij kun je alleen 'struct' als constraint opleggen, maar dat dekt nog niet alles af, en je hebt nog hetzelfde probleem.
struct, IComparable , IFormattable, IConvertible, IComparable<T>, IEquatable<T>

[ Voor 40% gewijzigd door TeeDee op 06-03-2009 09:27 ]

Heart..pumps blood.Has nothing to do with emotion! Bored


Acties:
  • 0 Henk 'm!

  • Woy
  • Registratie: April 2000
  • Niet online

Woy

Moderator Devschuur®
TeeDee schreef op vrijdag 06 maart 2009 @ 09:23:
[...]

Ook daarbij krijg ik een "A first chance exception of type 'System.InvalidCastException". We gaan er toch niet aan voorbij dat dit een Silverlight applicatie betreft?
Dat zou toch geen ene *&^@ uit moet maken? Het blijft gewoon .NET.

Maar als ik de volgende code draai gaat dat gewoon goed.
C#:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
public enum PasswordPolicy
{
    Simple,
    Default,
    Strong
}

void MyTest<T>() where T : struct 
{
    T[] values = (T[])Enum.GetValues(typeof (T));
    foreach (T ts in values)
    {
        int test = Convert.ToInt32(ts);
    }
}

MyTest<PasswordPolicy>();

[ Voor 10% gewijzigd door Woy op 06-03-2009 09:31 ]

“Build a man a fire, and he'll be warm for a day. Set a man on fire, and he'll be warm for the rest of his life.”


Acties:
  • 0 Henk 'm!

  • TeeDee
  • Registratie: Februari 2001
  • Laatst online: 16:01
Klopt, die tests e.d. heb ik ook allemaal gedaan, alleen zoals ik in de TS aanhaal:

De originele Enum komt uit een VB.net library waarbij Default een reserverd word is. Hierdoor dienen er brackets ([ ... ]) omheen gezet. Deze enum wordt aan de WCF doorgegeven welke op zijn beurt via Reflection de boel doorgeeft aan mijn Silverlight applicatie.

Heart..pumps blood.Has nothing to do with emotion! Bored


Acties:
  • 0 Henk 'm!

  • Woy
  • Registratie: April 2000
  • Niet online

Woy

Moderator Devschuur®
TeeDee schreef op vrijdag 06 maart 2009 @ 09:31:
Klopt, die tests e.d. heb ik ook allemaal gedaan, alleen zoals ik in de TS aanhaal:

De originele Enum komt uit een VB.net library waarbij Default een reserverd word is. Hierdoor dienen er brackets ([ ... ]) omheen gezet. Deze enum wordt aan de WCF doorgegeven welke op zijn beurt via Reflection de boel doorgeeft aan mijn Silverlight applicatie.
Ok maar dat is dan alleen de syntax die anders is. Een enum in C# zoals ik gebruik is in princiepe gewoon hetzelfde.

Wat gebeurt er als je mijn MyTest methode kopieert en die aanroept met jouw Enum?

“Build a man a fire, and he'll be warm for a day. Set a man on fire, and he'll be warm for the rest of his life.”


Acties:
  • 0 Henk 'm!

  • TeeDee
  • Registratie: Februari 2001
  • Laatst online: 16:01
Woy schreef op vrijdag 06 maart 2009 @ 09:49:
[...]

Ok maar dat is dan alleen de syntax die anders is. Een enum in C# zoals ik gebruik is in princiepe gewoon hetzelfde.

Wat gebeurt er als je mijn MyTest methode kopieert en die aanroept met jouw Enum?
Dat gaat niet werken, want, zoals vermeld heeft Silverlight geen Enum.GetValues. Daar heb ik een static voor
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
        
/// <summary>
/// Returns an Array of a given Enum
/// </summary>
/// <typeparam name="T"></typeparam>
/// <returns>Array</returns>
/// <exception cref="ArgumentException"></exception>
public static T[] EnumGetValues<T>()
{
    Type enumType = typeof(T);
    if (!enumType.IsEnum)
    {
        throw new ArgumentException("Type '" + enumType.Name + "' is not an enum");
    }
    List<T> values = new List<T>();
    var fields = from field in enumType.GetFields()
             where field.IsLiteral
             select field;
    foreach (FieldInfo field in fields)
    {
        object value = field.GetValue(enumType);
        values.Add((T)value);
    }
    return values.ToArray();
}

Dus die moet ik wel even vervangen.

Met de Convert.ToInt32 (in combinatie met de where T : struct) gaat het perfect. Blijkbaar heb ik gisteren uit frustratie deze combinatie nog niet geprobeerd.

Een In32.TryParse, (int) en weet ik veel wat nog meer werkten compiletime al niet. Je bent mijn held, en dat zo vlak voor het weekend :D

Edit: de where T : struct mag zelfs weg.

[ Voor 6% gewijzigd door TeeDee op 06-03-2009 10:10 ]

Heart..pumps blood.Has nothing to do with emotion! Bored


Acties:
  • 0 Henk 'm!

  • Woy
  • Registratie: April 2000
  • Niet online

Woy

Moderator Devschuur®
TeeDee schreef op vrijdag 06 maart 2009 @ 10:05:
[...]

Dat gaat niet werken, want, zoals vermeld heeft Silverlight geen Enum.GetValues. Daar heb ik een static voor
Is het framework van Silverlight dan zo anders dan het gewone framework? Ik had altijd het idee dat het gewoon hetzelfde framework was, maar dat je met beperkte rechten draaide.
Edit: de where T : struct mag zelfs weg.
Ja het is niet nodig, maar het beperkt je methode ieder geval enigsinds. Je zult er toch bij moeten documenteren ( Als dat al niet duidelijk is door de naam ;) ) dat T van het type Enum moet zijn. Ik ben er ook al vaker tegen aan gelopen dat Enum geen geldige constraint is.

“Build a man a fire, and he'll be warm for a day. Set a man on fire, and he'll be warm for the rest of his life.”


Acties:
  • 0 Henk 'm!

  • TeeDee
  • Registratie: Februari 2001
  • Laatst online: 16:01
Woy schreef op vrijdag 06 maart 2009 @ 10:16:
[...]
Is het framework van Silverlight dan zo anders dan het gewone framework? Ik had altijd het idee dat het gewoon hetzelfde framework was, maar dat je met beperkte rechten draaide.
[...]
Silverlight is een subset van WPF. Een aantal dingen die ik nodig heb in mijn Silverlight applicatie moeten we helaas via zulke methodes doen. Laten we het al helemaal niet over DataTables hebben. :'(

Heart..pumps blood.Has nothing to do with emotion! Bored


Acties:
  • 0 Henk 'm!

Verwijderd

Probeer eens of je wel de waarde van default terug krijgt als je het volgende doet (TypeCast op ID):
C#:
1
 Console.WriteLine((PasswordPolicy)3);

Deze Enum zou standaard per enumerator een ID hebben (automatisch 1 t/m 4) in dit geval ( of 0 t/m 3 dit weet ik niet zeker)

[ Voor 27% gewijzigd door Verwijderd op 06-03-2009 12:16 ]


Acties:
  • 0 Henk 'm!

  • Woy
  • Registratie: April 2000
  • Niet online

Woy

Moderator Devschuur®
Verwijderd schreef op vrijdag 06 maart 2009 @ 12:15:
Probeer eens of je wel de waarde van default terug krijgt als je het volgende doet (TypeCast op ID):
C#:
1
 Console.WriteLine((PasswordPolicy)3);

Deze Enum zou standaard per enumerator een ID hebben (automatisch 1 t/m 4) in dit geval ( of 0 t/m 3 dit weet ik niet zeker)
Als je goed had gelezen had je gezien dat het probleem al was opgelost ;)

“Build a man a fire, and he'll be warm for a day. Set a man on fire, and he'll be warm for the rest of his life.”

Pagina: 1