2015-08-23 22 views
7

EDIT FINALMożliwe przykre skutki uboczne oszukiwanie .Net mieć opcjonalne parametry ref dla COM

ja bardziej dokładnie przetestowany „cecha” i napisany cały artykuł o tym: Optional passed by reference parameters with C# for VBA COM APIs

Każda opinia jest Witamy.


jakiegoś powodu w C# sposób nie może mieć opcjonalnieprzekazywane przez odniesienie (oznaczonego ref lub out) parametrów.

Ale w innych infrastruktur jak VBA, VB6 lub COM jest to możliwe.

Kiedy pomostowych C# z użyciem VBA COM Znalazłem drogę do przezwyciężenia ograniczeń C# przez oznaczenie parametrów ref jak [Optional] który AFAIK co kompilator C# generuje na zakończenie swojej kanalizacji.

void SomeDotNetCSMethod([Optional] ref someParameter) 

To wydaje się działać jak czar: Dzwoniąc z VBA do C# mogę pominąć parametry ref i oczywiście mogę czytać i zmieniać je od/C# .NET stronie.

Ale jak nie znalazłem żadnego zapisu na ten temat, chciałbym mieć pewność, że nie ma żadnych złych efektów ubocznych w tej "sztuczce".

Czy znasz jakieś? Czy możesz sobie wyobrazić?


EDIT

Z atrybutem [DefaultParameterValue] może Znalazłem sposób na VBA zobaczyć domyślne wartości dla parametru, ale tylko dla niektórych typów.

zrobię więcej testów, aby potwierdzić ten działa zgodnie z oczekiwaniami ...

+0

Co jest nie tak z przeciążeniem funkcji? – Comintern

+0

@Comintern Dziękuję za odpowiedź, ale COM nie obsługuje przeciążania. Jeśli przeładujesz C# skończysz z 'SomeDotNetCSMethod_1',' SomeDotNetCSMethod_2' ... – Pragmateek

Odpowiedz

1

Nie, to nie jest to ogólny sposób określić opcjonalny argument. Korzystasz z całkiem dziwacznej funkcji, która została dodana w języku C# v4, dzięki czemu programowanie Office Interop stało się bardziej smaczne. Zwykle można oczekiwać, że będzie to miało zamierzony skutek, im bliżej warstwy interopowej przypominać VBA lub IDispatch (inaczej Automatyzacja COM). Nie jest to ogólny mechanizm COM, tym bardziej uniwersalny jest sposób, aby kompilator klienta obserwował atrybut [defaultvalue] w bibliotece typów i stosował wartość w wywołaniu metody. Działa podobnie do C#.

Rodzaj argumentu ma duże znaczenie, zapomniałeś podać go w swoim fragmencie. Ale z oczekiwaniem, że jest to obiekt. Który pasuje do VARIANT w serwerze COM, dość powszechny typ w Visual Basic. Wyjaśnia także ref, domyślnym argumentem przechodzącym w starych wersjach VB był ByRef.

Przed C# v4 było bardzo żmudnym pisaniem kodu C# do wywoływania takiego serwera, w szczególności kod interopowy Office był obsypany bardzo dużą ilością ref Type.Missing.Inaczej inspiracją jest potrzeba obsługi języków skryptowych, rodzaju środowiska, w którym niemożliwe jest określenie domyślnej wartości opcjonalnego argumentu z biblioteki typów. Konwencja była więc potrzebna do przekazania "dzwoniącemu nie określił argumentu" sygnału do uczestnika, wybrali wariant typu vtError o wartości ustawionej na DISP_E_PARAMNOTFOUND. Kompatybilny z IDispatch :: Invoke().

Należy zauważyć, że jest to bardzo, bardzo różni się od sposobu, w jaki parametry opcjonalne są rozpatrywane w języku C# i dowolnym innym języku. Zawsze jest to wywołujący, który rozpoznaje wartość domyślną dla opcjonalnego argumentu, a wywoływany jest całkowicie nieświadomy, że kod pominął argument. W przypadku C# ta domyślna wartość jest zakodowana jako wartość metadanych w postaci .param. Kompilator używa wartości domyślnej w razie potrzeby do kompilacji wywołania metody.

Jeśli typem argumentu nie jest obiekt, to wywołasz inne dziwactwo, teraz osoba dzwoniąca ustawia wartość domyślną. Będzie to null dla obiektu lub interfejsu. Oczywiście zależy to od tego, w jaki sposób kod, do którego dzwonisz, interpretuje wartość wariantu jako "opcjonalny". Zauważ, że vtNull lub vtEmpty może mieć to samo znaczenie semantyczne.

+0

Dzięki @Hans za tę wspaniałą odpowiedź. :-) Myślę, że nie ma sposobu na określenie '[defaultvalue]' bez grania z jakimś ** IDL **. Jeśli chodzi o wartości domyślne, rzeczywiście zauważyłem, że dla ** daty ** ** VBA ** przechodzi "1899-12-30", które mogę obsłużyć, jeśli daty nie mogą być tak daleko w przeszłości. Więc jeśli dobrze zrozumiem, inna infrastruktura wywołująca, jak na przykład C++, przekazałaby inną domyślną wartość. W moim przypadku nie jest to możliwe, ale warto wiedzieć, aby kod był bardziej ogólny. – Pragmateek