2011-01-24 14 views
7

Sotto System.Runtime.InteropServices l'attributo <Out()>. Ma a cosa serve? Sarei felice se potessi usare il seguente esempio come base per le tue risposte.L'attributo <Out()>. Quale scopo utile è servire?

Shared Sub Add(ByVal x As Integer, ByVal y As Integer, <Out()> ByRef Result As Integer) 
    Result = x + y 
End Sub 

risposta

7

Lo scopo di tale attributo è duplice:

  • gestione delle chiamate in loco , se applicare l'inizializzazione variabile o non
  • marshalling

Se si dovesse chiamare quel metodo da C#, o una lingua simile con la semantica simili, tale parametro sarebbe noto a il compilatore non ha bisogno di un valore iniziale.

In altre parole, si può fare questo:

int a; 
CallSomeMethodWithOutParameter(out a); 

e il compilatore sa che non v'è alcuna necessità di assicurare che a ha già un valore prima di effettuare la chiamata.

D'altra parte, senza l'attributo, sarebbe necessaria la seguente, di nuovo in C#:

int a = 0;        // <-- notice initialization here 
CallSomeMethodWithOutParameter(ref a); // <-- and ref here 

L'altro scopo è per chiamate di metodo che saranno dispiegate in un contesto di chiamata diverso, ad esempio tramite P/Invoke, verso un dominio app diverso, o verso un servizio web, per notificare le routine di marshalling che il parametro in questione conterrà un valore quando il metodo restituisce, ma non è necessario passare alcun valore nel metodo quando lo si chiama .

Questo potrebbe fare la differenza quando i parametri ei valori di ritorno devono essere impacchettati e trasportati nella posizione remota in cui passa la chiamata effettiva.

In altre parole, se si dovesse specificare che su una chiamata di metodo utilizzato per P/Invoke, no smistamento sia fatta la volontà del valore del parametro esistente quando il metodo viene chiamato, ma quando il metodo ritorna sua il valore viene ripristinato nel codice di chiamata.

Si noti che questa ottimizzazione dipende dalla routine di marshalling da utilizzare, oppure no, si tratta di dettagli di implementazione. L'attributo dice semplicemente alla routine con quale parametro può farlo, non è un'istruzione che verrà sempre seguita.

0

Non so su VB, ma ammesso che sia equivalente a C# 's out parola chiave:

Si comporta proprio come ref ma non richiede al chiamante di inizializzare la variabile passata al parametro out perché la funzione non la leggerà.

E probabilmente ha un effetto sul marshalling se si utilizza COM o p-invoke.

3

Significa che il parametro è visto come un parametro "out" da C#, per una cosa. In tal caso, il compilatore C# si assume che:

  • Qualsiasi valore esistente della variabile passata per riferimento è irrilevante, l'assegnazione in modo preciso non importa
  • La variabile sarà è stato assegnato un valore appropriato nel momento in cui il metodo ritorna, a meno che non ci sia un'eccezione, quindi è definitivamente assegnato alla fine dell'istruzione.

Altre lingue possono scegliere di utilizzare l'attributo [Out] in modi diversi, ovviamente, ma questo tipo di interpretazione è la più naturale. Fondamentalmente dice che il parametro è quasi come un valore di ritorno extra. (Ci sono un sacco di differenze, naturalmente, di vari gradi di sottigliezza, ma questo è il generale sensazione di un parametro out.)

+0

Non importa a C# solo se compilasse il codice in questione? "Ref" e "out" non sono identici al call-site? - non importa :) –

+0

In realtà, ciò significa che se la variabile non è stata scritta prima di chiamare la routine in questione, il compilatore inserirà silenziosamente il codice per inizializzare il percorso di archiviazione che contiene la variabile anziché lamentarsi (non vi è alcuna garanzia su dove verrà inserito tale codice, né vi è alcuna garanzia che una variabile che lascia e rientri nello scope non continui a utilizzare la stessa posizione di memorizzazione senza re-inizializzazione). Il compilatore non può realmente assumere che la variabile sia stata scritta, poiché non può essere sicuro che la routine chiamata effettivamente la scriva. – supercat

+0

@supercat: dipende dal livello al quale stiamo considerando le cose. Il "controllo che il tuo codice sorgente è valido" livello * fa * presuppone che la variabile sia stata scritta. Il livello "emitting IL" non lo è, anche se una diversa implementazione rivolta a una piattaforma diversa * potrebbe * essere in grado di. –

2

Viene utilizzato in tipi ComVisible per indicare che la libreria di tipi COM generata deve decorare il parametro con l'attributo [out].

0

Quando si applicano i parametri del metodo e i valori restituiti, questo attributo controlla la direzione del marshalling, quindi è noto come attributi direzionali. [OutAttribute] dice al CLR di tornare dal callee al chiamante al ritorno. Sia il chiamante che il chiamato possono essere codice non gestito o gestito. Ad esempio, in una chiamata P/Invoke, il codice gestito sta chiamando il codice non gestito. Tuttavia, in un P/Invoke inverso, il codice non gestito può chiamare il codice gestito tramite un puntatore a funzione.

Ci sono casi in cui [OutAttribute] verrà ignorato. Ad esempio, [OutAttribute]int non ha alcun senso, quindi [OutAttribute] viene semplicemente ignorato dal CLR. Lo stesso vale per la stringa [OutAttribute] perché la stringa è immutabile.

Quindi, per l'esempio questo attributo non ha senso. Ulteriori informazioni su questo attributo e correlato attributo <In()> possono trovare here.