使用值和引用参数类型重载的方法

时间:2013-11-01 15:29:31

标签: c# overloading

我有以下代码:

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 个答案:

答案 0 :(得分:11)

out parameter modifier (C# Reference)

  

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

另见:ref (C# Reference

  

类的成员不能只有ref和   out。如果两者之间只有差异,则会发生编译器错误   一个类型的成员是其中一个有一个ref参数和   其他人有一个out参数。

答案 1 :(得分:9)

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

  

虽然outref参数修饰符被视为签名的一部分,但在单一类型中声明的成员只能通过ref和out在签名上有所不同。如果在具有out修饰符的两个方法中的所有参数都更改为ref修饰符的情况下,如果两个成员在同一类型中声明具有相同签名的成员,则会发生编译时错误。对于签名匹配的其他目的(例如,隐藏或覆盖),refout被视为签名的一部分,并且彼此不匹配。 (此限制是为了允许C#程序轻松转换为在公共语言基础结构(CLI)上运行,这不提供定义仅在refout中不同的方法的方法。)< / p>

请注意,参数类型dynamic在这里略有相似 - 就CLR而言,这只是object类型的参数,所以这是无效的:

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

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

答案 2 :(得分:1)

这是按规格说明的。根据MSDN页面out parameter modifier (C# Reference)

  

虽然ref和out关键字会导致不同的运行时行为,   它们在编译时不被视为方法签名的一部分。   因此,如果唯一的区别是,方法不能超载   一个方法接受一个ref参数,另一个接受一个out参数。   例如,以下代码将无法编译:

答案 3 :(得分:-1)

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