2009-05-06 5 views
4

Je coursKeyedCollection avec ENUM type de clé ne sera pas l'index par int

public class FooKeyedCollection : KeyedCollection<FooType,Foo> 
{ 
} 

public enum FooType 
{ 
    FooType1, 
    FooType2, 
    FooType3 
} 

public Foo 
{ 
    public FooType Type { get; set; } 
    public string Value { get; set; } 
} 

Lorsque j'ajouter des articles à mon FooKeyedCollection, je peux les indexer par FooType, mais lorsque je tente de les indexer int, int est interprété comme l'enum FooType. En conséquence, elle conduit à une erreur de confusion, à savoir

public static void main() 
{ 
    FooKeyedCollection fkc = new FooKeyedCollection(); 

    Foo myFoo = new Foo(); 
    myFoo.Type = FooType.FooType3; 
    myFoo.Value = "someValue"; 

    foo.Add(myFoo); 

    Foo myFooByType = foo[FooType.FooType3]; 
    Foo myFooByIndex = foo[0]; // <-- exception thrown here 
} 

Le résultat de l'exécution de ce code est une exception lorsque l'on tente d'extraire l'élément par l'indice entier. J'espère exposer le FooKeyedCollection dans le cadre d'une API publique, et je veux protéger les consommateurs de cette API de cette erreur. Est-il possible que je puisse modifier la classe FooKeyedCollection pour obtenir un comportement approprié?

Répondre

3

Vous pouvez envisager d'utiliser le « nouveau » mot-clé ici:

public new Foo this[int index] 
{ 
    get 
    { 
     IList<Foo> self = this; 
     return self[index]; 
    } 
    set 
    { 
     (IList<Foo>)[index] = value; 
    } 
} 

Cela vous permettra d'indexer par valeur entière. L'utilisation de l'énumération retournera explicitement à l'implémentation KeyedCollection.

+0

Cela a fonctionné comme un champion, merci! – JadeMason

2

Le problème est que 0 est implicitement convertible en FooType. Si vous utilisez un autre numéro, ça ira. Si vous utilisez ce code, il devrait fonctionner aussi:

int index = 0; 
Foo myFooByIndex = foo[index]; 

EDIT: Malheureusement coulée ne permet pas ici - le compilateur reconnaît toujours comme une constante 0.

+1

J'ai essayé de lancer vers (int), mais il a quand même été résolu en FooType et a lancé l'exception. – JadeMason

3

Voici une méthode d'extension utile pour éviter ces les cas où les deux indexeurs se chevauchent - il aide également si la clé est int:

static class CollectionUtils 
{ 
    public static TValue GetByIndex<TKey,TValue> 
     (this KeyedCollection<TKey, TValue> collection, int index) 
    { 
     return collection[index]; 
    } 
} 

puis appelez fkc.GetByIndex(0) et cela fonctionnera très bien. À l'intérieur de la méthode générique, il peut seulement résoudre index à l'indexeur int.

+0

Personnellement, je pense que c'est la meilleure solution. En dehors de toute autre chose, cela signifie que vous ne vous tromperez pas si vous finissez par l'utiliser comme une KeyedCollection (où la solution de Jeff tombe). –

+0

@Jon - mes pensées exactement ;-p –

Questions connexes