开发者

Why ref and out are not sufficient to disambiguate overloaded in C#?

For example, why this method Max(ref int x, ref int y) is开发者_StackOverflow社区 not considered overload of Max(int x, int y)? Why is the same with out?


This question presupposes a false premise.

 Max(int x, int y)
 Max(ref int x, ref int y) 
 Max(out int x, out int y)

are all overloads of a method named Max. However, note that only one of the last two may be present in any given class definition. From the specification §3.6:

The signature of a method consists of the name of the method, the number of type parameters and the type and kind (value, reference, or output) of each of its formal parameters, considered in the order left to right. For these purposes, any type parameter of the method that occurs in the type of a formal parameter is identified not by its name, but by its ordinal position in the type argument list of the method. The signature of a method specifically does not include the return type, the params modifier that may be specified for the right-most parameter, nor the optional type parameter constraints.

[...]

Although out and ref parameter modifiers are considered part of a signature, members declared in a single type cannot differ in signature solely by ref and out. A compile-time error occurs if two members are declared in the same type with signatures that would be the same if all parameters in both methods with out modifiers were changed to ref modifiers. For other purposes of signature matching (e.g., hiding or overriding), ref and out are considered part of the signature and do not match each other. (This restriction is to allow C# programs to be easily translated to run on the Common Language Infrastructure (CLI), which does not provide a way to define methods that differ solely in ref and out.)


ref and out are the same thing, symantically. The CLR does not differentiate between the two. The C# language is making the distinction. For the CLR, there is only ref.


The language designers decided to create it that way.

I suspect (and this is just my opinion) that it was due to the fact that ref and out must be specified to reduce confusion. The language could have easily be designed to not require explicitly specifying ref/out, and have the compiler do it implicitly, but that would cause confusion. Similiarly, making these overloads would prevent other languages from being written that way (since the CLR is not just C#), and would just add to the overall confusion by many users, and it would be less clear which method is being called.


Let's write some code:

static void M1(int y)
{
    Console.WriteLine("val");
}

static void M1(ref int y)
{
    Console.WriteLine("ref");
}

//static void M1(out int y)  // compile error
//{
//    Console.WriteLine("out");
//}

static void Main2()
{
    int a = 3;

    M1(a);
    M1(ref a);
//    M1(out a);

}

Ther only is a conflict between the ref and out versions. Comment out the out parameter method and it compiles and runs as expected: Output is val and ref .


public void Max(int x, int y)          
//No Error
public void Max(ref int x, ref int y)  
//No Error
public void Max(out int x, out int y)  
//cannot define an overloaded method that differs only on parameter modifiers 'out' and 'ref'

First and second method can be overloaded. But the second and third method cannot be overloaded because both ref and out are treated differently at run time but they are treated the same at compile time.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜