Problema con Dictionary

mercoledì 22 aprile 2009 - 23.10

liuc Profilo | Junior Member

Ho una variabile dichiarata come segue :

Dictionary<TipoEnteID, TipoEnte> elenco;

dove TipoEnteID e TipoEnte sono due mie custom entity.

Non riesco ad accedere alla collection per recuperare i dati; il codice seguente, ad esempio, mi restituisce ente = null

hash = new Hashtable();
TipoEnteID codice = new TipoEnteID(1);
hash.Add(codice, new SIN.Dominio.TipoEnte(codice, "Ente 1", true));
codice = new TipoEnteID(2);
hash.Add(codice, new SIN.Dominio.TipoEnte(codice, "Ente 2", false));
codice = new TipoEnteID(3);
hash.Add(codice, new SIN.Dominio.TipoEnte(codice, "Ente 3", false));
TipoEnteID cod = new TipoEnteID(1);
TipoEnte ente = (TipoEnte)hash[cod];

luigidibiasi Profilo | Guru

Ciao,
credo che il problema sia da ricercare nell'utilizzo che vuoi fare dell'oggetto hashtable...

La funzione hash viene calcolata sul parametro key della funzione Add e dunque, nel tuo caso, su una istanza di classe....

Non puoi usare:
> TipoEnteID cod = new TipoEnteID(1);
> TipoEnte ente = (TipoEnte)hash[cod];

per accedere all'elemento aggiunto tramite questa riga:
> TipoEnteID codice = new TipoEnteID(1);
>hash.Add(codice, new SIN.Dominio.TipoEnte(codice, "Ente 1", true));

perchè quando hai usato Add hai fatto calcolare la funzione hash sull'istanza puntata dalla variabile "codice" mentre ora stai tendando di accedere tramite un'altra istanza ( quella salvata in cod )

Puoi provare ad effettuare l'ovverride del metodo getHashCode dei tuoi oggetti in modo da legare il valore ritornato dalla funzione al parametro intero che passi al costruttore (TipoEnteID(1) , TipoEnteID(2))

Infine dovresti usare :
>hash.Add(codice.getHashCode, new SIN.Dominio.TipoEnte(codice, "Ente 1", true));

Anche se non credo sia una soluzione ottimale....

Luigi Di Biasi
http://blogs.dotnethell.it/luigidibiasi/

liuc Profilo | Junior Member

Quindi non c'è modo di accedere all'istanza memorizzata nell'oggetto dictionary perchè ogni volta che creo una nuova istanza di tipoenteid questa avrà un hash diverso?

Proverò a fare l'override del metodo GetHashCode, ma perchè dici che non è la soluzione ottimale?


liuc Profilo | Junior Member

Chiedo scusa ma nel post iniziale ho mischiato due diverse versioni del codice.
Riscrico il codice che vorrei utilizzare :

Dictionary<TipoEnteID, TipoEnte> elenco = new Dictionary<TipoEnteID, TipoEnte>();
TipoEnteID codice;
codice = new TipoEnteID(1);
elenco.Add(codice, new SIN.Dominio.TipoEnte(codice, "Ente 1", 1));
codice = new TipoEnteID(2);
elenco.Add(codice, new SIN.Dominio.TipoEnte(codice, "Ente 2", 0));
codice = new TipoEnteID(3);
elenco.Add(codice, new SIN.Dominio.TipoEnte(codice, "Ente 3", 1));

DetailsView1.DataSource = elenco[new TipoEnteID(2)];
DetailsView1.DataBind();



Credo di aver capito che non può funzionare dal momento che viene calcolato un hash diverso nell'istruzione
DetailsView1.DataSource = elenco[new TipoEnteID(2)];
ed infatti a runtime ottengo l'errore che l'indice non è stato trovato.

Eseguendo l'override di GetHashCode per l'oggetto TipoEnteID per farmi ritornare l'indice intero che passo durante la creazione dell'istanza , ovviamente ottengo un errore di compilazione dal momento che la variabiel elenco si aspetta di avere una key del tipo TipoEnteID.


A questo punto provo a dichiarare elenco come Hashtable e vedo che succede.
In alternativa dovrei rinunciare ad utilizzare un oggetto come key?

luigidibiasi Profilo | Guru

Ciao,

>Eseguendo l'override di GetHashCode per l'oggetto TipoEnteID
>per farmi ritornare l'indice intero che passo durante la creazione
>dell'istanza , ovviamente ottengo un errore di compilazione dal
>momento che la variabiel elenco si aspetta di avere una key del
>tipo TipoEnteID.

Già... dimenticai di ridefinire la hashtable con tipo Key a integer

>In alternativa dovrei rinunciare ad utilizzare un oggetto come
>key?

Forse no... pensandoci bene una Hashtable non è altro che un dizionario che sulla key esegue una funzione prima di accedere alla memoria ....

Puoi pensare di costruire una Hashtable personalizzata andando a scrivere nei metodi Get e Set il calcolo della funzione come serve a te.

Il calcolo svolto dalla tua classe HashTable dovrebbe però assicurarsi che ad oggetti di tipo TipoEntita(i) identificati dallo stesso intero corrisponda lo stesso valore restituito dalla funzione....

>> non è soluzione ottimale...
Dicevo che non era soluzione ottimale ( a mio avviso ) perchè ogni volta che vuoi accedere alla memoria istanzi un oggetto...

Luigi Di Biasi
http://blogs.dotnethell.it/luigidibiasi/

liuc Profilo | Junior Member

Credo di aver risolto.

Nell'oggetto TipoEnteID ho aggiunto i seguenti metodi

public override int GetHashCode()
{
return this._codice;
}

public override bool Equals(Object obj)
{
return this.Equals((TipoEnteID)obj);
}

public bool Equals(TipoEnteID tipoenteid)
{
return this._codice == tipoenteid._codice;
}



Ed ora funziona.

Aggiungo gli oggetti in elenco con
codice = new TipoEnteID(1);
elenco.Add(codice, new SIN.Dominio.TipoEnte(codice, "Ente 1", 1));

e li leggo correttamente con

TipoEnte ente = elenco[new TipoEnteID(1)];


luigidibiasi Profilo | Guru

Ottimo!

Luigi Di Biasi
http://blogs.dotnethell.it/luigidibiasi/
Partecipa anche tu! Registrati!
Hai bisogno di aiuto ?
Perchè non ti registri subito?

Dopo esserti registrato potrai chiedere
aiuto sul nostro Forum oppure aiutare gli altri

Consulta le Stanze disponibili.

Registrati ora !
Copyright © dotNetHell.it 2002-2023
Running on Windows Server 2008 R2 Standard, SQL Server 2012 & ASP.NET 3.5