11

我有以下代码:

class Calculator
    {
        public int Sum(int x, int y)
        {
            return x + y;
        }



        public int Sum(out int x, out int y)
        {
            x = y = 10;
            return x + y;
        }


    }

    class Program
    {
        static void Main(string[] args)
        {
            int x = 10, y = 20;
            Calculator calculator = new Calculator();

            Console.WriteLine ( calculator.Sum ( x , y ) );
            Console.WriteLine ( calculator.Sum ( out x , out y ) );

        }
    }

尽管方法签名仅与out关键字不同,但此代码运行良好。

但是以下代码不起作用:

class Calculator
    {

        public int Sum(ref int x, ref int y)
        {
            return x + y;
        }

        public int Sum(out int x, out int y)
        {
            x = y = 10;
            return x + y;
        }

    }


    class Program
    {
        static void Main(string[] args)
        {
            int x = 10, y = 20;
            Calculator calculator = new Calculator();

            Console.WriteLine ( calculator.Sum ( ref x , ref y ) );
            Console.WriteLine ( calculator.Sum ( out x , out y ) );

        }
    }

为什么这段代码不起作用?像 ref 和 out 这样的关键字是方法签名的一部分吗?

4

4 回答 4

11

out 参数修饰符(C# 参考)

尽管 ref 和 out 关键字导致不同的运行时行为, 但它们在编译时不被视为方法签名的一部分。因此,如果唯一的区别是一个方法采用 ref 参数而另一个采用 out 参数,则方法不能重载。

另请参阅:ref(C# 参考

类的成员不能具有仅通过 ref 和 out 不同的签名。如果类型的两个成员之间的唯一区别是其中一个具有 ref 参数而另一个具有 out 参数,则会发生编译器错误。

于 2013-11-01T15:32:20.023 回答
9

引用与其他答案略有不同的内容,这是来自 C# 5 规范的第 3.6 节,我发现它比“参考指南”更清晰、更精确:

尽管outref参数修饰符被认为是签名的一部分,但在单一类型中声明的成员不能仅通过 ref 和 out 在签名上有所不同。如果两个成员在同一类型中声明,并且如果两个方法中的所有参数都带有out修饰符,则将发生编译时错误ref。用于签名匹配的其他目的(例如,隐藏或覆盖),ref并且out被视为签名的一部分并且彼此不匹配。(此限制是为了让 C# 程序可以轻松翻译以在公共语言基础结构 (CLI) 上运行,它不提供定义仅在ref和中不同的方法的方法out。)

请注意,dynamic这里的参数类型稍有相似——就 CLR 而言,这只是类型的参数object,因此这是无效的:

void InvalidOverload(object x) {}
void InvalidOverload(dynamic x) {}

但是,在这种情况下,参数类型为的方法dynamic可以覆盖参数类型为的方法,object反之亦然 - 重要的一点是它们等价于callers,而out/则不是这样ref

于 2013-11-01T15:34:41.520 回答
1

这是按规范。根据 MSDN page out parameter modifier (C# Reference)

尽管 ref 和 out 关键字导致不同的运行时行为,但它们在编译时不被视为方法签名的一部分。因此,如果唯一的区别是一个方法采用 ref 参数而另一个采用 out 参数,则方法不能重载。例如,以下代码将无法编译:

于 2013-11-01T15:32:47.733 回答
-1

这基本上是一个编译错误,因为 ref 和 out 几乎相同。两者几乎相同,但您传递out参数的值不需要初始化。

于 2013-11-01T15:34:48.140 回答