Dictionnary<T1,T2>

[Résolu]
Signaler
Messages postés
303
Date d'inscription
mardi 11 février 2003
Statut
Membre
Dernière intervention
24 avril 2009
-
Messages postés
303
Date d'inscription
mardi 11 février 2003
Statut
Membre
Dernière intervention
24 avril 2009
-
Bonjour,

Je vais simplifier ma question.

J'ai un Dictionnary MonDico

Dans ce dictionnary, j'ai ceci:

255, "Bonjour"
544, "Allo"
1234, "Salut"

Je peut donc faire MonDico[544] et sa me retourne "Allo"

Hors, si je fait MonDico[333], sa crash !

Je doit donc faire, avant chaque utilisation, ceci:

if( MonDico.ContainsKey(333) )
    return MonDico[333];

Et j'aimerais faire autrement.
Je voudrais un truc comme le GetSet, ou je ferais le test une seule fois, mais qu'il se ferait a chaque fois.

Je sais agir sur le MonDico, exemple faire un test si il est null quand on le demande. Je peux donc agir sur le GET de l'objet MonDico, mais moi je voudrais agir sur le GET d'un élément de Mondico ... vous me suivez ? Une solution a me proposer ?

Merci

Eric

12 réponses

Messages postés
5487
Date d'inscription
dimanche 4 août 2002
Statut
Modérateur
Dernière intervention
20 juin 2013
58
Salut,
Pas sûr non plus d'avoir compris la question... peut-être ceci (?) :

public
class
MyDictionary<T, U> :
Dictionary<T, U>
{
  
public
new U
this[T value]
   {
     
get
      {
        
return
this.ContainsKey(value) ?
this[value] :
default(U);
      }
   }
}

<hr />
-Blog-
Messages postés
5487
Date d'inscription
dimanche 4 août 2002
Statut
Modérateur
Dernière intervention
20 juin 2013
58
Le new n'est pas obligatoire mais conseilé, car tu "surécrit" un membre de la class de base. Avec new, tu indiques clairement que c'est un comportement voulu.

Concernant ton problème, le plus simple reste peut-être de définir une interface (voire une class abstraite) qui sera implémentée par Maison et Chien. Dans la déclaration de ta class Dictionnary, tu spécifie que le type U doit implémenter cette interface grâce à la clause where.

Ensuite, il te suffira d'appeler la valeur de l'interface que tu souhaites récupérer (retourner), je sais pas si c'est clair?

<hr />
-Blog-
Messages postés
303
Date d'inscription
mardi 11 février 2003
Statut
Membre
Dernière intervention
24 avril 2009
5
Et pour ceux qui liront ce post, un exemple plus concret

class Dictionary<TKey,TVal>
where TKey: IComparable, IEnumerable
where TVal: MyI
{
public void Add(TKey key, TVal val)
{
}
}
Messages postés
3246
Date d'inscription
lundi 25 avril 2005
Statut
Modérateur
Dernière intervention
27 octobre 2012
41
Salut, pas trop compris la question.. mais la classe Dictionary à une méthode TryGetValue rapide et pratique.
Messages postés
303
Date d'inscription
mardi 11 février 2003
Statut
Membre
Dernière intervention
24 avril 2009
5
Bon, j'ai fait quelque petites recherches pour le TryGetValue
C'est intéressant, mais c'est pas encore ce que je recherche.

En fait, si la Key n'existe pas, j'aimerais le gerer moi meme.

un peu du style comme sa

private Dictionnary _MonDico = new Dictionnary();
public Dictionnary MonDico
{
   get{ return _MonDico; }
   set{ _MonDico = value; }
}
public Dictionnary MonDico[index]
{
   get
   { 
      if( MonDico.ContainsKey(index)) 
         return MonDico[index]; 
      else 
         return "Inconnu";
   }
   set
   {       
      if( MonDico.ContainsKey(index)) 
         MonDico[index] = value;  
   }
}

Je me doute que ce type de programmation ne fonctionne pas, mais sa illustre bien et clairement ce que je recherche

Eric
Messages postés
66
Date d'inscription
samedi 24 février 2007
Statut
Membre
Dernière intervention
7 octobre 2007

Salut, tu peux peut être utiliser un bloc try catch

public partial class Form1 : Form
    {
        System.Collections.Generic.Dictionary dico = new Dictionary();

        public Form1()
        {
            InitializeComponent();
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            dico.Add(533, "Hello");
            dico.Add(1234, "Bonjour");
            try
            {
                string chaine = dico[333];
            }
            catch (Exception ex)
            {
                MessageBox.Show("Erreur.");
            }
        }
    }

A plus.
Messages postés
303
Date d'inscription
mardi 11 février 2003
Statut
Membre
Dernière intervention
24 avril 2009
5
Je croit que Bidou à ce que compris ce que je veux.


Est-ce que ce que tu me donne retournera ceci ?




MyDictionary MonDico = new MyDictionary();
MonDico.Add(111,"A");
MonDico.Add(222,"B");



MonDico.Add(333,"C");
string string1 = MonDico[222]; // string1 aura "A" comme valeur;
string string1 = MonDico[444]; // string1 aura null comme valeur;



????

Si c'est bon, c'est donc ce que je recherche.

Autre chose, si au lieu de string, j'ai MyDictionary MonDico. Y-a-til un moyen de définir le "default value" de ma propre classe ?? En fait définir la valeur retournée dans default(U);

Merci pour tout

Eric
Messages postés
5487
Date d'inscription
dimanche 4 août 2002
Statut
Modérateur
Dernière intervention
20 juin 2013
58
Oui, si tu prends l'exemple que je t'ai donné, alors tu auras le comportement que tu souhaites.
Pour le dictionnaire, ça ne change rien la façon dont tu l'initialises (avec un string ou MaClasse) étant donné qu'il est Généric... Tout ce que tu dois faire, c'est retourne un type "U"

<hr />
-Blog-
Messages postés
303
Date d'inscription
mardi 11 février 2003
Statut
Membre
Dernière intervention
24 avril 2009
5
En fait, ce que je veux dire, c'est que imaginons 2 classes, Chien et Maisons

Dans mon code, j'ai ceci

MyDictionary MonDico1 = new MyDictionary();
MonDico1.Add(111,new Chien("Fido",5));
MonDico1.Add(222,new Chien("Ralphy",8)););
MonDico1.Add(333,new Chien("Boxie",5)););
string string1 = MonDico1[111]; // string1 aura le chien du nom de Fido comme valeur;
string string2 = MonDico1[444]; // string1 aurait le chien new Chien("Inconnu",0); comme valeur
MyDictionary MonDico2 = new MyDictionary();
MonDico2.Add(555,new Maison("Paris","rue 1"));
MonDico2.Add(666,new Maison("Québec","rue 2")););
MonDico2.Add(777,new Maison("New Yorl","rue 3")););
string string1 = MonDico[555]; // string1 aura la maison a Paris comme valeur;
string string2 = MonDico[888]; // string1 aurait la maison new Maison("Inconnu","Inconnu"); comme valeur

Je souhaite donc définir la valeur par défaut de la classe Chien et de la classe Maison. Pour que dans la classe MonDictionnary, je puisse faire default(U); et si U est typeof(Maison), sa me retourne new Maison("Inconnu","Inconnu");, si U est typeof(Chien), sa me retourne new Chien("Inconnu",0);, et si U est un autre type, sa me retourne son default() normal.
Ya moyen de faire cela ?

Et Sinon, autres question, dans la ligne
public new U this[T value]
Est-ce que le "new" est obligatoire ? et Pourquoi ?

Merci encore

Eric
Messages postés
303
Date d'inscription
mardi 11 février 2003
Statut
Membre
Dernière intervention
24 avril 2009
5
Oui, j'avais penser a l'interface ou a la classe bastraite, je me demandais si yavais moyen autre de le faire :)

J'ai tout compris, sauf l'histoire de la clause where :)
Messages postés
303
Date d'inscription
mardi 11 février 2003
Statut
Membre
Dernière intervention
24 avril 2009
5
C'est bon, google est mon ami :)

using System;

class MyClassy<T, U>
where T : class
where U : struct
{
}
Messages postés
303
Date d'inscription
mardi 11 février 2003
Statut
Membre
Dernière intervention
24 avril 2009
5
Encore moi.

Je bloque sur la derniere partie de ma question, jai tout compris ce que l'on m'a dit de faire, le probleme étant au moment de l'exécuter.

Voila ce que jai tenter, mais encore une fois, en me doutant que ça ne fonctionnerait pas:

ICookingEntry<T>
=
public

interface
ICookingEntry<T>
{
   
static T DefaultEntry
   {
      
get;
   }
}

=

CookingDico<T,U> : Dictionnary<T,U>
=

public
class
CookingDico<TKey, TValue> :
Dictionary<TKey, TValue>
            
where TValue :
ICookingEntry<TValue>
{
   
public
new TValue
this[TKey value]
   {
      
get
      {
         
if ( ContainsKey( value ) )
            
return
base[value];
         
else
            return ( (
ICookingEntry<TValue>)TValue ).DefaultEntry;
      }
   }
}


En effet, il me semblait bien que mettre un membre static a une interface était étrange ... et que la ligne 
 return ( (ICookingEntry<TValue>)TValue ).DefaultEntry;
Était d'autant plus étrange.

Comment devrais-je faire le tout ???
Eric