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.
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 :) –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
@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. –