Domanda

Quali sono gli aspetti da considerare quando si sceglie tra ByRef e ByVal.

Comprendo la differenza tra i due, ma non capisco completamente se ByRef risparmia risorse o se dobbiamo anche preoccuparci di ciò nell'ambiente .Net.

Come si decide tra i due se la funzionalità non ha importanza in una situazione?

È stato utile?

Soluzione

C'è molta disinformazione intorno a questo. La cosa principale è capire la differenza tra tipi di valore e tipi di riferimento e differenza tra passaggio per valore e passaggio per riferimento .

Quasi sempre vuoi passare per valore. Il passaggio per riferimento è quasi sempre per " Voglio restituire più di un risultato, e non solo aggiungendo cose a un elenco che viene passato. & Quot; L'esempio classico di un metodo che utilizza il pass-by-reference è Int32. TryParse dove il valore restituito è un esito positivo / negativo e il valore analizzato è "restituito" da un parametro out.

Altri suggerimenti

L'impostazione predefinita è byValue per TUTTI i tipi, ma è importante capire cosa significano le due opzioni per un tipo di riferimento "quot" (una classe) al contrario di un tipo di valore. (Le strutture).

Per un tipo di riferimento, se si dichiara una variabile del tipo di riferimento in un metodo, quella variabile è una posizione di memoria nel frame dello stack del metodo. Non è sul mucchio. Quando inizializzi quella variabile (usando new o factory, qualunque cosa), hai creato un oggetto reale sull'heap e l'indirizzo di quell'oggetto è memorizzato nella variabile di riferimento dichiarata nel tuo frame dello stack dei metodi.

Quando si passa un tipo di riferimento a un altro metodo daVal, si crea una copia dell'indirizzo memorizzato nello stack dei metodi di chiamata e si passa la copia di quel valore (l'indirizzo del puntatore) al metodo chiamato, in cui è archiviato un nuovo slot di memoria nello stack dei metodi chiamati. All'interno del metodo chiamato, la nuova variabile clonata punta direttamente allo stesso oggetto sull'heap. Quindi usarlo può cambiare le proprietà dello stesso oggetto. Ma non è possibile cambiare a quale oggetto heap punta la variabile di riferimento originale (nello stack dei metodi di chiamata). Se, nel metodo chiamato scrivo

  myVar = new object();

La variabile originale nel metodo chiamante non sarà cambiata per puntare a un nuovo oggetto.

Se passo un tipo di riferimento da Rif, otoh, sto passando un puntatore alla variabile dichiarata nello stack dei metodi di chiamata (che contiene un puntatore all'oggetto sull'heap) È quindi un puntatore a un puntatore all'oggetto . Indica la posizione di memoria nello stack dei metodi di chiamata, che punta all'oggetto sull'heap.
Quindi ora, se cambio il valore della variabile nel metodo chiamato, impostandolo su un nuovo oggetto (), come sopra, poiché si tratta di un "riferimento" " alla variabile nel metodo chiamante, sto effettivamente cambiando l'oggetto a cui punta la variabile nel metodo chiamante. Quindi, dopo che il metodo chiamato ritorna, la variabile nel metodo chiamante non punta più sullo stesso oggetto originale sull'heap.

ByVal dovrebbe essere il tuo " default " ;. Usalo a meno che tu non abbia un motivo specifico per usare ByRef

Il passaggio di un oggetto ByVal in .net non crea una copia dell'oggetto e non consuma più risorse di ByRef, un puntatore viene comunque passato alla funzione. Il runtime assicura solo che non è possibile modificare il puntatore nella funzione e restituire un valore diverso per esso. Puoi comunque apportare modifiche ai valori all'interno dell'oggetto e vedrai tali modifiche al di fuori della funzione. Ecco perché ByRef viene utilizzato così raramente. È necessario solo quando si desidera che una funzione cambi l'oggetto reale che sta tornando; quindi un parametro di output.

Usa " ByRef " solo se il parametro è "output" parametro. Altrimenti usa "ByVal". Utilizzo di " ByRef " su parametri che esplicitamente non dovrebbero restituire valori è pericoloso e può facilmente generare bug.

Direi che ByRef non dovrebbe mai essere usato - che è una cattiva pratica. Lo applicherei anche al suo tipico caso d'uso di consentire a una funzione di restituire più valori (tramite i parametri ByRef). Sarebbe meglio per la funzione restituire una risposta strutturata che includesse quei valori di ritorno multipli. È più chiaro e più ovvio se una funzione restituisce valori solo tramite la sua istruzione return.

Contrassegnando alcuni argomenti come ByRef mostra all'utente della tua funzione che la variabile allocata a tale argomento ** verrà modificata. ****

Se usi ByRef per tutti gli argomenti, non ci sarà modo di dire quali variabili sono modificate dalla funzione e quali sono appena lette da essa. (a parte sbirciare all'interno della sorgente della funzione!)

Secondo Microsoft, la scelta di ByVal o ByRef può influire sulle prestazioni per valori sufficientemente grandi (vedere Passaggio di argomenti per valore e per riferimento (Visual Basic) ):

  

Prestazioni. Sebbene il meccanismo di passaggio possa influire sulle prestazioni   del tuo codice, la differenza è generalmente insignificante. Un'eccezione   a questo è un tipo di valore passato da ByVal. In questo caso, Visual Basic   copia l'intero contenuto dei dati dell'argomento. Pertanto, per a   grande valore come una struttura, può essere più efficiente passare   ByRef.

[enfasi aggiunta].

Sub last_column_process()
Dim last_column As Integer

last_column = 234
MsgBox last_column

trying_byref x:=last_column
MsgBox last_column

trying_byval v:=last_column
MsgBox last_column

End Sub

Sub trying_byref(ByRef x)
x = 345
End Sub

Sub trying_byval(ByRef v)
v = 555
End Sub

Tanta confusione cercherò di semplificare. Fondamentalmente hai 4 scelte:

  1. Passa un tipo di valore per Val
  2. Passa un tipo di valore con Rif
  3. Passa un oggetto byVal
  4. Passa un oggetto con Rif

Alcune persone dicono che non mai usato da Rif. Mentre sono tecnicamente corretti, una cosa è certa. Dovresti MAI usare la parola mai . Se stai progettando un sistema da zero, allora byRef dovrebbe essere evitato a tutti i costi. Usarlo rivela un difetto di progettazione. Tuttavia, lavorare su un sistema esistente potrebbe non fornire la stessa flessibilità per implementare un buon design. A volte è necessario effettuare delle concessioni, ovvero utilizzando byRef. Ad esempio, se puoi ottenere una correzione in 2 giorni usando byRef, allora è preferibile reinventare la ruota e impiegare una settimana per ottenere la stessa correzione solo per evitare di usare byRef.

Sommario:

  1. Uso di byVal su un tipo di valore: passa un valore a una funzione. Questo è il modo preferito di funzioni di progettazione.
  2. Uso di byRef su un tipo di valore: utile per restituire più di un valore da una funzione. Se tu stanno creando una funzione che deve restituire più di un valore a un sistema esistente questo può essere migliore della creazione di un oggetto (e dell'impostazione delle proprietà e dello smaltimento) per una funzione.
  3. Uso di byVal su un oggetto: passa un puntatore di un oggetto a una funzione. La funzione può modifica l'oggetto.
  4. Uso di byRef su un oggetto: passa un puntatore a un puntatore di un oggetto a una funzione. permette cambiando l'oggetto a cui punta il chiamante. Questo può causare alcuni Difficile trovare bug e non riesco a pensare a nessuna buona ragione per usarlo. Non significa che non ce n'è uno, ma se ce ne sono sono pochi e molto lontano.
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top