none
Перегруженные методы и null RRS feed

  • Вопрос

    1. class Application
    2.     {
    3.         public class A { }
    4.         public class B : A { }
    5.         public class C : B { }
    6.         public static class Hey
    7.         {
    8.             public static void Handle(A a)
    9.             {
    10.                 Console.WriteLine("a");
    11.             }
    12.             public static void Handle(B b)
    13.             {
    14.                 Console.WriteLine("b");
    15.             }
    16.             public static void Handle(C c)
    17.             {
    18.                 Console.WriteLine("c");
    19.             }
    20.         }
    21.         public static void Main()
    22.         {
    23.             Hey.Handle(null);
    24.             Console.Read();
    25.         }
    26.     }

    Что выведет, и, главное, почему.

    9 июля 2013 г. 22:23

Ответы

  • Привожу текст из спецификации языка:

    1.1.1.1 Более подходящая функция-член

    Для целей определения наиболее подходящей функции-члена формируется укороченный список аргументов А, содержащий только сами выражения аргументов в том порядке, в каком они присутствуют в исходном списке аргументов.

    Списки параметров для каждого кандидата функции-члена формируется следующим способом:

    • Расширенная форма используется в случае, если функция-член была применима только в расширенной форме.
    • Необязательные параметры без соответствующих аргументов удаляются из списка параметров
    • Порядок параметров изменяется таким образом, что они встречаются в той же позиции, что и соответствующий аргумент в списке аргументов.

    При наличии списка аргументов A с набором выражений аргументов { E<sub>1</sub>, E<sub>2</sub>, ..., E<sub>N</sub> } и двух применимых функций-членов M<sub>P</sub> и M<sub>Q</sub> с типами параметров { P<sub>1</sub>, P<sub>2</sub>, ..., P<sub>N</sub> } и { Q<sub>1</sub>, Q<sub>2</sub>, ..., Q<sub>N</sub> } MP считается более подходящей функцией-членом, чем M<sub>Q</sub>, если

    • для каждого аргумента неявное преобразование из EX в QX не лучше неявного преобразования из E<sub>X</sub> в P<sub>X</sub> и
    • по крайней мере для одного аргумента преобразование из E<sub>X</sub> в P<sub>X</sub> лучше преобразования из E<sub>X</sub> в Q<sub>X</sub>.

    При проведении этой оценки если M<sub>P</sub> или M<sub>Q</sub> применима в расширенной форме, то P<sub>X</sub> или Q<sub>X</sub> относится к параметру в расширенной форме списка параметров.

    Если последовательности типов параметров { P<sub>1</sub>, P<sub>2</sub>, …, P<sub>N</sub>} и { Q<sub>1</sub>, Q<sub>2</sub>, …, Q<sub>N</sub>} идентичны, то для определения более подходящей функции-члена применяются следующие правила разрешения.

    • Если M<sub>P</sub> не является универсальным методом, а M<sub>Q</sub> — универсальный метод, то M<sub>P</sub> является более подходящей, чем M<sub>Q</sub>.

    Иначе, если M<sub>P</sub> применима в нормальной форме, а M<sub>Q</sub> имеет массив params и применима только в расширенной форме, то M<sub>P</sub> является более подходящей, чем M<sub>Q</sub>.

    • Иначе, если у M<sub>P</sub> больше объявленных параметров, чем у M<sub>Q</sub>, то M<sub>P</sub> является более подходящей, чем M<sub>Q</sub>. Это может просходить, когда у обеих функций-членов есть массивы params, применимые только в расширенных формах.
    • Иначе, если у всех параметров M<sub>P</sub> есть соответствующий аргумент, тогда как аргументы по умолчанию должны быть заменены на по меньшей мере один необязательный параметр в M<sub>Q</sub>, то M<sub>P</sub> является более подходящей, чем M<sub>Q</sub>.
    • Иначе, если у M<sub>P</sub> более конкретные типы параметров, чем у M<sub>Q</sub>, то M<sub>P</sub> является более подходящей, чем M<sub>Q</sub>. Пусть наборы {R<sub>1</sub>, R<sub>2</sub>, …, R<sub>N</sub>} и {S<sub>1</sub>, S<sub>2</sub>, …, S<sub>N</sub>} представляют неинициализированные и нерасширенные типы параметров функций-членов M<sub>P</sub> и M<sub>Q</sub>. Типы параметров M<sub>P</sub> являются более конкретными, чем у M<sub>Q</sub>, если для любого параметра R<sub>X</sub> является не менее конкретным, чем S<sub>X</sub>, и по крайней мере один параметр R<sub>X</sub> является более конкретным, чем S<sub>X</sub>.
      • Параметр типа является менее конкретным, чем не параметр типа.
      • Один сформированный тип является более конкретным, чем другой (с таким же числом аргументов типа), если у первого типа по крайней мере один аргумент типа является более конкретным по сравнению с соответствующим аргументом типа второго типа и нет аргументов типа менее конкретных по сравнению с соответствующими аргументами типа другого сформированного типа.
      • Тип массива является более конкретным, чем другой тип массива (с таким же числом измерений), если тип элементов первого является более конкретным, чем тип элементов второго.
    • Иначе, если один член не является оператором с нулификацией, а другой является, то оператор без нулификации считается более подходящим.
    Иначе определить более подходящую функцию-член нельзя.

    А теперь, если своими словами, то: компилятору трудно определить, а точнее невозможно в данном случае, подходящий вызов. И поэтому существует определённый набор правил (который привёл выше), согласно которому он должен действовать в подобных ситуациях. Выходом из данной ситуации является явный вызов с указанием типа:

    public class Sample
    {
    
      class Application
      {
        public class A { }
        public class B : A { }
        public class C : B { }
        public static class Hey
        {
          public static void Handle(A a)
          {
            Console.WriteLine("a");
          }
          public static void Handle(B b)
          {
            Console.WriteLine("b");
          }
          public static void Handle(C c)
          {
            Console.WriteLine("c");
          }
        }
        public static void Main()
        {
          Hey.Handle((B)null); //Указываете тип явно.
          Console.Read();
        }
      }
    
    }


    Сделаем содержимое сообщества лучше, вместе!

    10 июля 2013 г. 5:53
    Модератор