referencia - ¿C#error del compilador o rareza COM normal?
referencia c# (1)
No creo que sea un error; se parece más a "COM vudú" como dices. Bajo el capó, el compilador de C # emite algo que de hecho es correcto, como este:
private static void Foo(IFoo o)
{
...
Guid g = Guid.NewGuid();
Guid <>r__ComRefCallLocal0 = g;
Bar(o, ref <>r__ComRefCallLocal0);
...
}
C # está, de hecho, lleno de trucos. Si agrega un método a IFoo, como este por ejemplo,
[ComImport, Guid("cb4ac859-0589-483e-934d-b27845d5fe74")]
interface IFoo
{
void Test([Optional] ref object test);
}
Usted, nuevamente, podrá declarar esto en C # 4:
static void Foo(IFoo o)
{
Guid g = Guid.NewGuid();
o.Test(g);
}
Por supuesto, todo esto solo funciona porque CSC.EXE tiene un conocimiento íntimo del atributo ComImport. Estos nuevos trucos mágicos de interoperabilidad se agregaron a C # 4.0 para poder interoperar fácilmente con las interfaces COM existentes. Bueno, para las interfaces y los métodos de Microsoft Office en su mayoría, y especialmente los ejércitos de espantosos parámetros de "falta de referencia" :-)
No creo que esto esté completamente especificado en ninguna parte. Esto es todo lo que la especificación C # 4 tiene que decir:
17.5 Atributos para la interoperación Nota: esta sección solo es aplicable a la implementación de Microsoft # .NET de C #. 17.5.1 Interoperación con componentes COM y Win32. El tiempo de ejecución de .NET proporciona una gran cantidad de atributos que permiten a los programas de C # interoperar con componentes escritos mediante DLL COM y Win32. Por ejemplo, el atributo DllImport se puede usar en un método externo estático para indicar que la implementación del método se encuentra en una DLL de Win32. Estos atributos se encuentran en el espacio de nombres System.Runtime.InteropServices, y la documentación detallada de estos atributos se encuentra en la documentación de tiempo de ejecución de .NET.
Y aquí hay algunas páginas en MSDN:
C # 4, para simplificar la interoperabilidad COM, permite a las personas que llaman a las interfaces COM omitir la palabra clave ref delante de los argumentos para los parámetros ref.
Me sorprendió ver hoy que esto también se aplica a los métodos de extensión que extienden las interfaces COM. Vea lo siguiente, compilación, código:
using System;
using System.Runtime.InteropServices;
[ComImport, Guid ("cb4ac859-0589-483e-934d-b27845d5fe74")]
interface IFoo {
}
static class Program {
public static void Bar (this IFoo self, ref Guid id)
{
id = Guid.NewGuid ();
}
static void Main ()
{
Foo (null);
}
static void Foo (IFoo o)
{
Guid g = Guid.NewGuid ();
Console.WriteLine (g);
// note that g is passed as is, and not as ref g
o.Bar (g);
Console.WriteLine (g);
}
}
No encontré nada en la especificación para explicar este comportamiento.
Mi sensación sería que el código fuera de la interfaz COM, incluso si se trata de un método de extensión que extiende una interfaz COM, debería seguir las reglas regulares de C # y hacer cumplir el uso de la palabra clave ref. Por lo tanto, presenté un error en conectar . No creo que esto se solucione, incluso si se considera como un error, ya existe un código que confía en esto.
¿Insecto? No es un error?