Почему ref и out недостаточно для устранения неоднозначности в C #? - PullRequest
4 голосов
/ 13 июня 2011

Например, почему этот метод Max(ref int x, ref int y) не считается перегрузкой Max(int x, int y)? Почему то же самое с out?

Ответы [ 5 ]

14 голосов
/ 13 июня 2011

Этот вопрос предполагает ложную предпосылку.

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

- все перегрузки метода с именем Max.Тем не менее, обратите внимание, что только один из двух последних может присутствовать в любом заданном определении класса.Из спецификации §3.6:

Подпись метода состоит из имени метода, числа параметров типа и типа и вида (значения,ссылка или вывод) каждого из его формальных параметров , рассматриваемых в порядке слева направо.Для этих целей любой параметр типа метода, который встречается в типе формального параметра, идентифицируется не по его имени, а по порядковой позиции в списке аргументов типа метода.Сигнатура метода, в частности, не включает тип возвращаемого значения, модификатор params, который может быть указан для самого правого параметра, а также необязательные ограничения параметров типа.

[...]

Хотя модификаторы параметров out и ref считаются частью подписи, члены, объявленные в одном типе, не могут отличаться в подписи только на ref и out.Ошибка времени компиляции происходит, если два члена объявлены в одном и том же типе с подписями, которые были бы одинаковыми, если бы все параметры в обоих методах с модификаторами out были изменены на модификаторы ref.Для других целей сопоставления подписи (например, скрытие или переопределение) ref и out считаются частью подписи и не соответствуют друг другу.(Это ограничение позволяет легко переводить программы на C # в общую языковую инфраструктуру (CLI), которая не позволяет определять методы, отличающиеся только ref и out.)

3 голосов
/ 13 июня 2011

ref и out - это одно и то же, по своей сути. CLR не делает различий между ними. Язык C # делает различие. Для CLR есть только ref.

1 голос
/ 13 июня 2011

Давайте напишем некоторый код:

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);

}

Существует только конфликт между версиями ref и out. Закомментируйте метод параметра out, и он скомпилируется и будет работать так, как ожидается: выходные данные равны val и ref.

1 голос
/ 13 июня 2011

Дизайнеры языка решили создать его таким образом.

Я подозреваю (и это только мое мнение), что это произошло из-за того, что ref и out должны быть указаны для уменьшения путаницы. Язык можно легко спроектировать так, чтобы он не требовал явного указания ref / out, и чтобы компилятор делал это неявно, но это могло бы вызвать путаницу. Аналогичным образом, выполнение этих перегрузок будет препятствовать тому, чтобы другие языки писались таким образом (поскольку CLR - это не просто C #), а просто добавило бы к общей путанице многих пользователей, и было бы менее понятно, какой метод вызывается. *

0 голосов
/ 15 июня 2019
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'

Первый и второй метод могут быть перегружены. Но второй и третий метод не могут быть перегружены, потому что и ref, и out обрабатываются по-разному во время выполнения, но они одинаковы во время компиляции .

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...