Ответ 1
Я не думаю, что это ошибка; он больше похож на "COM voodoo", как вы говорите. Под капотом компилятор С# испускает то, что на самом деле правильно, например:
private static void Foo(IFoo o)
{
...
Guid g = Guid.NewGuid();
Guid <>r__ComRefCallLocal0 = g;
Bar(o, ref <>r__ComRefCallLocal0);
...
}
С# на самом деле полна трюков. Если вы добавите метод в IFoo, например,
[ComImport, Guid("cb4ac859-0589-483e-934d-b27845d5fe74")]
interface IFoo
{
void Test([Optional] ref object test);
}
вы, опять же, сможете объявить это в С# 4:
static void Foo(IFoo o)
{
Guid g = Guid.NewGuid();
o.Test(g);
}
Конечно, все это работает только потому, что CSC.EXE обладает глубоким знанием атрибута ComImport. Эти новые магические трюки Interop были добавлены в С# 4.0, чтобы иметь возможность легко взаимодействовать с существующими COM-интерфейсами. Ну, для интерфейсов и методов Microsoft Office в основном, и особенно для армий ужасных параметров "ref missing": -)
Я не думаю, что это полностью указано где угодно. Это все, что должно сказать спецификация С# 4:
17.5 Атрибуты для взаимодействия. Примечание. Этот раздел применим только к реализации Microsoft.NET С#. 17.5.1. Взаимодействие с компонентами COM и Win32. Время выполнения .NET предоставляет большое количество атрибутов, которые позволяют программам С# взаимодействовать с компонентами, написанными с использованием COM и Win32 DLL. Для Например, атрибут DllImport можно использовать для статического метода extern чтобы указать, что реализация метода находится в Win32 DLL. Эти атрибуты находятся в Пространство имен System.Runtime.InteropServices и подробная документация для этих атрибутов содержится в документации по времени выполнения .NET.
И вот несколько страниц на MSDN: