Qwertj (Dev Team)
Guru
Messaggi: 678
Iscritto: 30/05/2011
|
Questo topic è stato chiuso dal moderatore Salve a tutti,
Non mi riesco assolutamente a spiegare una cosa:
Nel mio programma chiamo una funzione che accetta due parametri ByVal, glieli passo entrambi. Uno di questi è una lista, quando gliela passo però viene passata invece che come ByVal, come ByRef, e viene modificata. Nonostante sia una proprietà ReadOnly
Il codice è circa questo
Codice sorgente - presumibilmente VB.NET |
'Funzione chiamata Private Function DoSomething(ByVal List1 As List(Of String), ByVal List2 As List(Of String)) As String Dim Result As String List1.RemoveRange(0, List2.Count) For Each Element As String In List1 Result &= Element Next Return Result End Function 'metodo "principale" Public Sub DoSomethingElse(ByVal List2 As List(Of String)) Dim AnObject As New AClass("example") 'questo stampa, ad esempio, 7 MessageBox.Show(AnObject.ReadOnlyList.Count) MessageBox.Show(DoSomething(AnObject.ReadOnlyList, List2)) 'questo stampa invece 0 quando List2.Count = AnObject.ReadOnlyList.Count MessageBox.Show(AnObject.ReadOnlyList.Count) End Sub
|
Ha un senso?
|
|
BionicGod (Normal User)
Rookie
Messaggi: 33
Iscritto: 16/06/2011
|
Che ne dici di postare tutto il sorgente...
Non so cosa sia AClass, non ho il suo funzionamento, come faccio ad aiutarti?
POSTA TUTTO...
|
|
Qwertj (Dev Team)
Guru
Messaggi: 678
Iscritto: 30/05/2011
|
Il problema non sta sicuramente in AClass, ma piuttosto nel codice che ti ho postato
Comunque, se vuoi anche quelli te li do, ma dubito che possano aiutarti
Codice sorgente - presumibilmente VB.NET |
Class AClass Public Sub New(ByVal Value As String) For Each Letter As Char in Value _ReadOnlyList.Add(Letter.ToString) Next End Sub Private _ReadOnlyList As New List(Of String) Public ReadOnly Property ReadOnlyList As List(Of String) Return _ReadOnlyList End Property End Class
|
Ultima modifica effettuata da Qwertj il 22/07/2011 alle 22:10 |
|
BionicGod (Normal User)
Rookie
Messaggi: 33
Iscritto: 16/06/2011
|
Codice sorgente - presumibilmente VB.NET |
Public Sub DoSomethingElse(ByVal List2 As List(Of String)) Dim AnObject As New AClass("example") Console.WriteLine(AnObject.ReadOnlyList.Count) Dim e As New List(Of String) For Each Letter As Char In AnObject.ReadOnlyList e.Add(Letter.ToString) Next Console.WriteLine(DoSomething(e, List2)) Console.WriteLine(AnObject.ReadOnlyList.Count) End Sub
|
La soluzione sarebbe creare un'altra lista così da non alterare il numero di valori in ReadOnlyList
Rimane comunque anomala la modifica nonostante sia ReadOnly.
Non so che dirti...
|
|
Qwertj (Dev Team)
Guru
Messaggi: 678
Iscritto: 30/05/2011
|
Infatti... è davvero strano
|
|
HeDo (Founder Member)
Guru^2
Messaggi: 2765
Iscritto: 21/09/2007
|
Se tu sapessi vagamente come funziona il linguaggio che stai usando, avresti ben chiaro il motivo per cui le liste (ed in generale tutti gli oggetti) vengono passati ByRef. Inoltre, se avessi studiato la differenza tra oggetti mutabili ed immutabili, sapresti immediatamente come risolvere questo "problema" che in realtà è il comportamento normale del codice.
|
|
BionicGod (Normal User)
Rookie
Messaggi: 33
Iscritto: 16/06/2011
|
Premetto che io non studio VB.NET, ma C#...però non ho mai sentito parlare di oggetti mutabili e immutabili. Siceramente nel libro di programmazione non ci sono riferimenti a questi termini. Potresti gentilmente spiegarci come funzionano?
|
|
Qwertj (Dev Team)
Guru
Messaggi: 678
Iscritto: 30/05/2011
|
In effetti hai ragione HeDo, mi ero scordato che gli oggetti reference sono passati per referenza Chiedo umilmente perdono
Però come risolvo? Che sono gli oggetti mutabili/immutabili?
Avevo provato anche a fare una cosa così:
Codice sorgente - presumibilmente C# / VB.NET |
Dim Copy As List(Of String) = List1.Take(List1.Count).ToList
|
Anche una cosa del genere passa a Copy una referenza di List1?
|
|
HeDo (Founder Member)
Guru^2
Messaggi: 2765
Iscritto: 21/09/2007
|
Postato originariamente da Qwertj:
In effetti hai ragione HeDo, mi ero scordato che gli oggetti reference sono passati per referenza Chiedo umilmente perdono
Però come risolvo? Che sono gli oggetti mutabili/immutabili?
Avevo provato anche a fare una cosa così:
Codice sorgente - presumibilmente C# / VB.NET |
Dim Copy As List(Of String) = List1.Take(List1.Count).ToList
|
Anche una cosa del genere passa a Copy una referenza di List1? |
il modo migliore per fare una cosa del genere se vuoi impedire che si modifichi la lista ma NON ti serve effettivamente una lista ma solo un array: passa un IEnumerable<T> (con T il tipo della lista). In questo modo la funzione si vedrà arrivare un insieme enumerabile senza avere la possibilità di moficarla.
Se invece ti serve passare una lista che la funzione può modificare ma senza che i cambiamenti si riflettano sulla lista del chiamante, l'unico modo è istanziarne una nuova:
Codice sorgente - presumibilmente C# / VB.NET |
void foo(List<int> lst) {
....
lst.Add(1);
...
}
List<int> callerList = new List<int>();
// Chiami la funzione istanziando una nuova lista
foo(new List<int>(callerList));
|
ricordati però che un approccio di questo genere genera una shallow copy, non una copia profonda dell'oggetto. Il risultato è che se la lista è una lista di oggetti mutabili e il chiamato modifica uno di questi oggetti, i cambiamenti si ripercuoteranno sul chiamante. Il motivo è che in una lista di oggetti si memorizzano i reference agli oggetti
|
|