无法将基类型的变量作为输出参数传递?

use*_*188 5 c# out

刚刚注意到这不起作用:

var dict = new Dictionary<int, XElement>();
XContainer element;
//...
if (dict.TryGetValue(idx, out element)) { //...
Run Code Online (Sandbox Code Playgroud)

然后我尝试了这个:

class A { }
class B : A { }

class Program {
    static void Main() {
        A a;
        a = Ret();  // no error, ok
        Ref(ref a); // compiler error, ok...
        Out(out a); // compiler error, lolwut?!
    }
    static B Ret() { return null; }
    static void Ref(ref B b) { }
    static void Out(out B b) { b = null; }
}
Run Code Online (Sandbox Code Playgroud)

为什么我在最后一次调用中收到编译器错误?

编辑:好的,据我从答案中了解到,“out”是变相的“ref”,因此它可以由其他函数或线程共享和更改。但实际上,“out”不应该是从函数返回多个值的一种方式吗?因为如果是这样的话,那就显得不太擅长了。如果共享会产生问题,那就不要共享。只需在函数的开头创建一个隐藏变量并使用它即可。我是说:

static void Out(out B b) {
    B bHidden; // compiler generated;
        // all references to b are replaced with bHidden;
    b = bHidden;
}
Run Code Online (Sandbox Code Playgroud)

有什么理由不能这样做吗?现在对我来说似乎很安全......

k.m*_*k.m 2

C# 规范指示类型必须完全匹配

\n\n
\n

17.5.1.3 输出参数

\n\n

当形式参数是输出参数时,方法调用中的相应参数应由关键字 out 后跟与形式参数类型相同的变量引用 (\xc2\xa7 12.3.3.27) 组成。

\n
\n\n

如果允许的话,你可以这样做:

\n\n
class A { }\nclass B : A { public void BOnlyMethod() { } }\nclass C : A { }\n\npublic class Violations\n{\n    private A a;\n\n    public void DoIt()\n    {\n        Violate(out this.a);\n    }\n\n    void Violate(out B b)\n    {\n        b = new B();\n        InnocentModification();\n        // what we think is B, is now C in fact, yet we still can do this:\n        b.BOnlyMethod();\n        // which is bound to fail, as BOnlyMethod is not present on type C\n    }\n\n    void InnocentModification()\n    {\n        this.a = new C();\n    }\n}\n
Run Code Online (Sandbox Code Playgroud)\n\n

如果不存在这样的限制,那么像上面这样的类型系统的违反将很容易实现。我想你不希望你的语言有这种“可能性”。

\n

  • 但为什么?我明白为什么它必须与 ref 参数匹配,但背后的原因是什么? (2认同)