2011-01-24 15 views
7

Pod System.Runtime.InteropServices istnieje atrybut <Out()>. Ale po co to jest? Byłbym zadowolony, gdybyś mógł wykorzystać poniższy przykład jako bazę dla swoich odpowiedzi.Atrybut <Out()>. Jaki pożyteczny cel ma służyć?

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

Odpowiedz

7

Celem tego atrybutu jest dwojaki:

  • obsługi połączeń-site , czy wymusić zmienną inicjalizacji lub nie
  • rozrządowych

Jeśli było wywołanie tej metody z C# lub podobny język z podobnymi semantyki, taki parametr będzie znany kompilator nie potrzebuje wartości początkowej.

Innymi słowy, można to zrobić:

int a; 
CallSomeMethodWithOutParameter(out a); 

i kompilator wie, że nie ma potrzeby, aby upewnić się, że a ma już wartość przed dokonaniem połączenia.

Z drugiej strony, bez atrybutu dodaje byłyby potrzebne, znowu w C#:

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

Drugim celem jest dla wywołań metod, które będą przetaczane w innym kontekście wywołującym, na przykład poprzez P/Wywołaj do innej domeny aplikacji lub do usługi sieciowej, aby powiadomić procedury rozrządowe, że dany parametr będzie zawierał wartość, gdy metoda się zwróci, ale nie ma potrzeby przekazywania żadnej wartości do tej metody podczas jej wywoływania .

Może to mieć znaczenie, gdy parametry i zwracane wartości muszą zostać spakowane i przetransportowane do zdalnego miejsca, w którym odbywa się faktyczne połączenie.

Innymi słowy, jeśli były, aby określić, że na wezwanie metoda stosowana przez P/Invoke nie marshalling nastąpi istniejącej wartości parametru gdy metoda jest zwanego, ale gdy metoda zwraca jego wartość zostanie przeniesiona z powrotem do twojego kodu wywołującego.

Należy pamiętać, że ta optymalizacja zależy od procedury zestawiania, czy też nie, są to szczegóły implementacji. Atrybut po prostu informuje rutynowo, jakie parametry może to zrobić, to nie jest instrukcja, która zawsze będzie przestrzegana.

0

nie wiem o VB, ale przy założeniu, że jest to równoznaczne z C# 's out słów kluczowych:

zachowuje się podobnie jak ref ale nie wymaga rozmówcę do zainicjowania zmiennej przekazanej w parametrze ponieważ out funkcja nie będzie go czytać.

Prawdopodobnie ma to wpływ na marshaling, jeśli używasz COM lub p-invoke.

3

Oznacza to, że parametr jest postrzegany jako parametr "out" przez C#, na jedną rzecz. W tym przypadku C# kompilator zakłada, że:

  • Wszelkie istniejące wartość zmiennej przekazywane przez referencję nie ma znaczenia, tak określony przydział nie ma znaczenia
  • Zmienna będzie przypisano odpowiednią wartość do czasu, gdy metoda powróci, chyba że istnieje wyjątek - więc jest on definitywnie przypisany na końcu instrukcji.

Inne języki mogą oczywiście używać atrybutu [Out] na różne sposoby, ale ten rodzaj interpretacji jest najbardziej naturalny. Zasadniczo mówi, że parametr jest prawie jak dodatkowa wartość zwracana. (Istnieje wiele różnic, oczywiście, o różnym stopniu subtelności, ale to ogólna uczucie z parametr wyjściowy).

+0

Czy nie miałoby to znaczenia dla C#, tylko gdyby miało ono skompilować dany kod? Czy "call" i "out" nie są identyczne na stronie call? - nieważne :) –

+0

W rzeczywistości oznacza to, że jeśli zmienna nie została napisana przed wywołaniem danej procedury, kompilator po cichu wstawi kod, aby zainicjować miejsce przechowywania, które zawiera zmienną, zamiast narzekać na nią (nie ma gwarancji, gdzie taki kod zostanie umieszczony, ani nie ma gwarancji, że zmienna, która opuszcza i ponownie wchodzi w zakres, nie będzie nadal używać tej samej lokalizacji pamięci bez ponownej inicjalizacji). Kompilator nie może w rzeczywistości założyć, że zmienna została zapisana, ponieważ nie może być pewna, że ​​wywoływana procedura faktycznie ją zapisuje. – supercat

+0

@supercat: To zależy od poziomu, na którym rozważamy różne rzeczy. "Sprawdzanie, czy twój kod źródłowy jest prawidłowy" poziom * nie * zakłada, że ​​zmienna została zapisana. Poziom "emitowania IL" nie jest - choć inna implementacja targetowania na inną platformę * może * być w stanie. –

2

Jest używany w typach ComVisible, aby wskazać, że wygenerowana biblioteka typów COM powinna udekorować parametr za pomocą atrybutu [out].

0

Przy stosowaniu do parametrów metody i zwracanych wartości, atrybuty te kontrolują kierunek fałdowania, dlatego są określane jako atrybuty kierunkowe. [OutAttribute] mówi CLR, aby po powrocie oddzwonił od wywoływacza do dzwoniącego. Zarówno wywołujący, jak i wywoływany mogą być niezarządzanym lub zarządzanym kodem. Na przykład w wywołaniu P/Invoke zarządzany kod wywołuje niezarządzany kod. Jednak w odwrotnym P/Invoke niezarządzany kod mógł wywoływać zarządzany kod za pomocą wskaźnika funkcji.

Istnieją przypadki, w których [OutAttribute] zostanie zignorowany. Na przykład [OutAttribute]int nie ma sensu, więc [OutAttribute] jest po prostu ignorowany przez CLR. To samo dotyczy ciągu znaków [OutAttribute], ponieważ ciąg znaków jest niezmienny.

Na przykład ten atrybut nie ma sensu. Więcej o tym atrybucie i skorelowanym atrybucie <In()> można znaleźć here.