Passaggio per parametri ref con matrici

domenica 31 maggio 2009 - 09.54

sanfra Profilo | Junior Member

Salve, io sin da quando ho iniziato a programmare in c++, il passaggio per paramteri, se dovevo fare dei cambiamenti alla variabile del metodo gli assegnavo il famoso puntatore, sia che fosse una variabile, sia un array,in c# ho notato che anche se non metto la parola chiave ref prima dell'array lo legge cmq, potete dirmi che cosa ancora tutt'oggi non ho capito bene della programmazione sui paramteri passati per riferimento?


Grazie


P.S.:mi basterebbe anche un link!


aiedail92 Profilo | Expert

Ciao

Quello che succede avviene per un semplice motivo (che, dato che conosci il c++, non ti sarà difficile comprendere):

In .net ci sono due tipi di dati: le strutture e le classi, che si distinguono per un'importante differenza: le strutture sono un value type, mentre le classi sono un reference type. In altre parole, le strutture sono come le strutture e le classi del c++, mentre le classi equivalgono ai puntatori. Il valore di una classe non è l'oggetto stesso, ma un indirizzo in cui l'oggetto effettivo risiede.

Ora, poiché l'array è una classe e non una struttura, quando passi un array ad una funzione puoi modificare i valori degli elementi anche senza usare la ref, infatti quello che viene "duplicato" e passato alla funzione non è l'oggetto stesso, ma un puntatore che punta allo stesso oggetto.

Se, invece di un array, passassi un int (che è un value type) senza la ref, non potresti modificarne il valore (o meglio potresti ma alla funzione chiamante non cambierebbe) perché quello che viene passato è una copia dell'int, e quello che modificheresti sarebbe solo la copia. Usando la ref potresti modificare il valore restituendolo alla funzione chiamante.

Riassumendo, senza ref puoi modificare i membri di un reference type ma non il puntatore stesso (perché quello viene copiato), e non puoi modificare il valore di un value type; con la ref puoi modificare i membri e il puntatore di un reference type, e puoi modificare il valore di un value type.

Spero sia abbastanza chiaro, se ci sono dubbi chiedi pure

Luca

sanfra Profilo | Junior Member

Innanzitutto grazie per il tuo intervento, ma quest'ultimo punto dove tu riassumi non mi è chiarissimo,che vuol dire che puoi modificare i membi di un reference type ma non il puntatore stesso(perchè quello viene copiato)?


>Riassumendo, senza ref puoi modificare i membri di un reference
>type ma non il puntatore stesso (perché quello viene copiato),
>e non puoi modificare il valore di un value type; con la ref
>puoi modificare i membri e il puntatore di un reference type,
>e puoi modificare il valore di un value type.


Comunque volevo capirlo meglio con degli esempi e se è possibile commentarli insieme.

Per esempio se io in una funzione:
void SomeTest(ref object[] valori) //in questo caso non avrebbe senso

se poi io creo una mia classe :


class Validator{

//proprietà

//membri

// costruttori
}


e in una funzione al di fuori di quest'ultima la richiamo così:

public void SomeTestClass(ref Validator v)// non ha senso neppure in questo modo.


Grazie ancora

tonyexpo Profilo | Senior Member

Ciao
ti faccio un esempio




tipo valore (structure)

void test(int i)
{
//se cambi i non cambia nel chiamante
}

void test(ref int i)
{
//se cambi i cambia anche nel chiamante
}



tipo riferimento (class)

void test(tipo o)
{
//se cambi il valore di o non cambia nel chiamante
//se cambi il valore di una proprietà di o questa è dell'oggetto puntato da o, e quindi del chiamante
}

void test(ref tipo o)
{
//se cambi o questo cambia nel chiamante
//se cambi una proprietà di o cambia nel chiamante
}


spero di essere stato chiaro
ciao

Antonio Esposito
MCTS .NET 3.5 WCF, .NET 2.0 Distributed applications
MCP .NET 3.5/2.0

sanfra Profilo | Junior Member

Ciao tonyexpo e grazie anche per la tua spiegazione,

sinceramente pensavo di aver capito,ma adesso tu mi hai dato delle delucidazioni in più.

Volevo chiederti sull'esempi da te riportati in particolare questo:
//se cambi il valore di una proprietà di o questa è dell'oggetto puntato da o, e quindi del chiamante

questo vuol dire che anche se non posto ref davanti all'oggetto e cambio una proprietà all'interno della funzione il chiamante avrà comunque la proprietà dell'oggetto modificata?

//void function(Oggetto o){
o.nome="Prova";

}

txtnome.Text=o.nome;

la text avrà Prova

Corretto?


Grazie

tonyexpo Profilo | Senior Member


esatto

la differenza in uno scenario reference-type (class)
è che passando il parametro per valore (byval in VB, default in c#) nn fai che copiare il puntatore
hai quindi una variabile puntatore all'oggetto nel chiamante
e una variabile puntatore all'oggetto nel tuo metodo
i puntatori sono diversi, ma puntano allo stesso oggetto quindi se su quello fai modifiche a proprietà o invochi metodi ke lo fanno
le ritroverai altrove

passando il parametro per riferimento (byref in VB, ref in c#) passi un puntatore al tuo puntatore
quindi la variabile nel metodo punta alla variabile fuori
puoi sempre modificare proprietà dell'oggetto puntato ovviamente
ma puoi anche riassegnare alla variabile altri valori e questi saranno altresì assegnati alla variabile chiamante


spero di esser stato comprensibile

ciao
Antonio Esposito
MCTS .NET 3.5 WCF, .NET 2.0 Distributed applications
MCP .NET 3.5/2.0

sanfra Profilo | Junior Member

chiaro e comprensibile, però ancora mi manca da capire un cosa(sarà il caldo) e spero di non annoiarti(o annoiare gli utenti di dotnethell),ed è la seduente:

a che scopo creare un oggetto che faccia riferimento ancora ad un oggetto, sarebbe il corrispondente in C++ di
void tipo(oggetto ** o)

Perchè fare così, sempre se è come sto cercando di capire?

se io ho un oggetto che chiamiamo "Cliente" e nella funzione : void Function(Cliente c), in che caso dovrei mettere il ref davanti se io so che è già un puntatore che la sua proprietà verrà comunque passata al chiamante modificata?


P.S.:Faccio questa supposizione, perchè ho visto un esempio del genere sulla rete e quindi mi ha un pò confuso.


Grazie ancora

tonyexpo Profilo | Senior Member

>chiaro e comprensibile, però ancora mi manca da capire un cosa(sarà
>il caldo) e spero di non annoiarti(o annoiare gli utenti di dotnethell),ed
>è la seduente:
>
>a che scopo creare un oggetto che faccia riferimento ancora ad
>un oggetto, sarebbe il corrispondente in C++ di
>void tipo(oggetto ** o)
>
>Perchè fare così, sempre se è come sto cercando di capire?
>
>se io ho un oggetto che chiamiamo "Cliente" e nella funzione
>: void Function(Cliente c), in che caso dovrei mettere il ref
>davanti se io so che è già un puntatore che la sua proprietà
>verrà comunque passata al chiamante modificata?


l'unico caso è quando oltre la possibilità di modificarne le proprietà dell'oggetto, vuoi assegnare alla variabile chiamante una nuova istanza della stessa classe

es:
object o;

void assegnami(ref object o) {
o=new pippo();
}




>
>
>P.S.:Faccio questa supposizione, perchè ho visto un esempio del
>genere sulla rete e quindi mi ha un pò confuso.
>
>
>Grazie ancora

ciao
Antonio Esposito
MCTS .NET 3.5 WCF, .NET 2.0 Distributed applications
MCP .NET 3.5/2.0

sanfra Profilo | Junior Member

grazie adesso mi è tuttio chiaro!
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-2025
Running on Windows Server 2008 R2 Standard, SQL Server 2012 & ASP.NET 3.5