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

我有以下代码:

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方法签名的一部分?

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

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

另见: ref(C#参考 )

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

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

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

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

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

但是,在这种情况下,对于参数类型为dynamic ,可以使用参数类型的object覆盖一个方法,反之亦然 – 重要的一点是,它们等同于调用者 ,而这不是真的。 out / ref

这是规范。 根据MSDN页面输出参数修饰符(C#参考)

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

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