Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/csharp-4.0/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C#编译器错误还是正常的COM异常?_C#_C# 4.0_Compiler Construction_Csc - Fatal编程技术网

C#编译器错误还是正常的COM异常?

C#编译器错误还是正常的COM异常?,c#,c#-4.0,compiler-construction,csc,C#,C# 4.0,Compiler Construction,Csc,C#4,为了简化COM互操作,允许COM接口的调用方在by ref参数的参数前面省略ref关键字 今天我很惊讶地看到,这也适用于扩展COM接口的扩展方法。请参阅下面的编译代码: using System; using System.Runtime.InteropServices; [ComImport, Guid ("cb4ac859-0589-483e-934d-b27845d5fe74")] interface IFoo { } static class Program { p

C#4,为了简化COM互操作,允许COM接口的调用方在by ref参数的参数前面省略ref关键字

今天我很惊讶地看到,这也适用于扩展COM接口的扩展方法。请参阅下面的编译代码:

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);
    }
}
我在规范中没有找到任何东西来解释这种行为

我的感觉是,COM接口之外的代码,即使是扩展COM接口的扩展方法,也应该遵循常规的C#规则,并强制使用ref关键字。因此,我提交了一份报告。我并不认为这会被修复,即使它被认为是一个bug,已经有代码依赖于此


臭虫?不是虫子吗?

我不认为它是虫子;它看起来更像你说的“COM巫毒”。在引擎盖下,C#编译器发出一些事实上正确的东西,比如:

private static void Foo(IFoo o)
{
    ...
    Guid g = Guid.NewGuid();
    Guid <>r__ComRefCallLocal0 = g;
    Bar(o, ref <>r__ComRefCallLocal0);
    ...
}
同样,您可以在C#4中声明:

当然,所有这些都只起作用,因为CSC.EXE非常熟悉ComImport属性。这些新的互操作魔术被添加到C#4.0中,以便能够轻松地与现有COM接口进行互操作。嗯,对于Microsoft Office界面和方法来说,尤其是那些可怕的“ref-missing”参数:-)

我认为这并没有在任何地方得到充分的说明。这就是C#4规范的全部内容:

17.5互操作属性注意:本节仅适用于C#的Microsoft.NET实现。 17.5.1与COM和Win32组件的互操作.NET运行时提供了大量属性,使C#程序能够 与使用COM和Win32 DLL编写的组件进行互操作。对于 例如,DllImport属性可用于静态外部方法 指示该方法的实现将在 Win32 DLL。这些属性可以在 System.Runtime.InteropServices命名空间和详细文档 有关这些属性的详细信息,请参见.NET运行时文档

以下是有关MSDN的一些页面:


非常有趣。4.0规范在这里确实显得模棱两可。它说这适用于COM类型的方法(第22+22.1节)。但我找不到任何明确表示或不表示扩展方法以这种方式被视为类型的一部分的内容。我猜是个虫子。我相信埃里克很快就会来澄清。这听起来确实像个错误。今天我的车还没开,因为雪上下着冻雨,所以我不在办公室。下周我会看一看。感谢您在Connect上输入此问题!西蒙,我知道编译器发出的信息是有效的。我还知道COM接口方法的调用站点可以省略by ref参数参数的ref,但这不是问题所在。问题是要知道这是否适用于扩展方法,因为规范中没有规定。从这个问题中知道什么和不知道什么并不清楚。我试着回答“有没有虫子”。我相信这不是一个bug,因为它是C#的Microsoft.NET实现,所以实现和支持的场景正是微软决定的。@SimonMourier,这意味着C#永远不会有任何bug,这是胡说八道。C#编译器由C#规范管理。如果编译器和规范冲突,那就意味着存在bug。它可能是编译器或规范中的一个错误,甚至可能是故意的,但它肯定是一个错误。@svick-C#spec(有趣的部分在我的回答中被完全引用)明确指出它在.NET运行时文档中有记录,而事实上,它不是。所以绝对没有冲突,没有违反规则。这并不是因为听起来不合逻辑,它才是一个bug。规范中也没有指定Automatic ref'd参数,所以这应该是该功能存在的bug吗?@SimonMourier,我指的是C#4.0新版本的C#4.0规范。您可以在这里找到:总结一下问题:关于第22.1节,将此行为应用于扩展方法是否被视为bug?“这不是一个bug,因为微软的实现是参考”并没有回答这个问题。还有其他一些情况下,微软的实现违反了规范,可能被认为是一个bug,这没关系,只要有文档记录就行了。
[ComImport, Guid("cb4ac859-0589-483e-934d-b27845d5fe74")]
interface IFoo
{
    void Test([Optional] ref object test);
}
static void Foo(IFoo o)
{
    Guid g = Guid.NewGuid();
    o.Test(g);
}