Полное руководство. С# 4.0 - Шилдт Герберт
Шрифт:
Интервал:
Закладка:
При выполнении этой программы получается следующий результат.Множители числа 1000:2 4 5 8 10 20 25 40 50 100 125 200 250 500
В классе Factor метод FindFactors() объявляется следующим образом.public int[] FindFactors(int num, out int numfactors) {
Обратите внимание на то, как указывается возвращаемый массив типа int. Этотсинтаксис можно обобщить. Всякий раз, когда метод возвращает массив, он указывается аналогичным образом, но с учетом его типа и размерности. Например, в следующей строке кода объявляется метод someMeth(), возвращающий двумерный массивтипа double.public double[,] someMeth() { // ...Перегрузка методов
В C# допускается совместное использование одного и того же имени двумя или более методами одного и того же класса, при условии, что их параметры объявляютсяпо-разному. В этом случае говорят, что методы перегружаются, а сам процесс называется перегрузкой методов. Перегрузка методов относится к одному из способов реализации полиморфизма в С#.
В общем, для перегрузки метода достаточно объявить разные его варианты, а обостальном позаботится компилятор. Но при этом необходимо соблюсти следующееважное условие: тип или число параметров у каждого метода должны быть разными.Совершенно недостаточно, чтобы два метода отличались только типами возвращаемых значений. Они должны также отличаться типами или числом своих параметров.(Во всяком случае, типы возвращаемых значений дают недостаточно сведений компилятору С#, чтобы решить, какой именно метод следует использовать.) Разумеется,перегружаемые методы могут отличаться и типами возвращаемых значений. Когдавызывается перегружаемый метод, то выполняется тот его вариант, параметры которого соответствуют (по типу и числу) передаваемым аргументам.
Ниже приведен простой пример, демонстрирующий перегрузку методов.// Продемонстрировать перегрузку методов.using System;class Overload { public void OvlDemo() { Console.WriteLine("Без параметров"); } // Перегрузка метода OvlDemo с одним целочисленным параметром. public void OvlDemo(int a) { Console.WriteLine("Один параметр: " + a); } // Перегрузка метода OvlDemo с двумя целочисленными параметрами. public int OvlDemo(int a, int b) { Console.WriteLine("Два параметра: " + a + " " + b); return a + b; } // Перегрузка метода OvlDemo с двумя параметрами типа double. public double OvlDemo(double a, double b) { Console.WriteLine("Два параметра типа double: " + a + " "+ b); return a + b; }}class OverloadDemo { static void Main() { Overload ob = new Overload(); int resI; double resD; // Вызвать все варианты метода OvlDemo(). ob.OvlDemo(); Console.WriteLine(); ob.OvlDemo(2); Console.WriteLine(); resI = ob.OvlDemo(4, 6); Console.WriteLine("Результат вызова метода ob.OvlDemo(4, 6): " + resI Console.WriteLine (); resD = ob.OvlDemo(1.1, 2.32); Console.WriteLine("Результат вызова метода ob.OvlDemo(1.1, 2.32): " + resD); }}
Вот к какому результату приводит выполнение приведенного выше кода.Без параметровОдин параметр: 2Два параметра: 4 6Результат вызова метода ob.OvlDemo(4, 6): 10Два параметра типа double: 1.1 2.32Результат вызова метода ob.OvlDemo(1.1, 2.32): 3.42
Как видите, метод OvlDemo() перегружается четыре раза. Первый его вариант неполучает параметров, второй получает один целочисленный параметр, третий — двацелочисленных параметра, а четвертый — два параметра типа double. Обратите также внимание на то, что два первых варианта метода OvlDemo() возвращают значениетипа void, а по существу, не возвращают никакого значения, а два других — возвращают конкретное значение. И это совершенно допустимо, но, как пояснялось выше,тип возвращаемого значения не играет никакой роли для перегрузки метода. Следовательно, попытка использовать два разных (по типу возвращаемого значения) вариантаметода OvlDemo() в приведенном ниже фрагменте кода приведет к ошибке.// Одно объявление метода OvlDemo(int) вполне допустимо.public void OvlDemo(int a) { Console.WriteLine("Один параметр: " + a);}/* Ошибка! Два объявления метода OvlDemo(int) не допускаются,хотя они и возвращают разнотипные значения. */public int OvlDemo(int a) { Console.WriteLine("Один параметр: " + a); return a * a;}
Как следует из комментариев к приведенному выше коду, отличий в типах значений, возвращаемых обоими вариантами метода OvlDemo(), оказывается недостаточнодля перегрузки данного метода.
И как пояснялось в главе 3, в C# предусмотрен ряд неявных (т.е. автоматических)преобразований типов. Эти преобразования распространяются также на параметрыперегружаемых методов. В качестве примера рассмотрим следующую программу.// Неявные преобразования типов могут повлиять на// решение перегружать метод.using System;class Overload2 { public void MyMeth(int x) { Console.WriteLine("В методе MyMeth(int): " + x); } public void MyMeth(double x) { Console.WriteLine("В методе MyMeth(double): " + x); }}class TypeConv { static void Main() { Overload2 ob = new Overload2(); int i = 10; double d = 10.1; byte b = 99; short s = 10; float f = 11.5F; ob.MyMeth(i); // вызвать метод ob.MyMeth(int) ob.MyMeth(d); // вызвать метод ob.MyMeth(double) ob.MyMeth(b); // вызвать метод ob.MyMeth(int) -- с преобразованием типа ob.MyMeth(s); // вызвать метод ob.MyMeth(int) -- с преобразованием типа ob.MyMeth(f); // вызвать метод ob.MyMeth(double) -- с преобразованием типа }}
При выполнении этой программы получается следующий результат.В методе MyMeth(int): 10В методе MyMeth(double): 10.1В методе MyMeth(int): 99В методе MyMeth(int): 10В методе MyMeth(double): 11.5
В данном примере определены только два варианта метода MyMeth(): с параметром типа int и с параметром типа double. Тем не менее методу MyMeth() можнопередать значение типа byte, short или float. Так, если этому методу передается значение типа byte или short, то компилятор C# автоматически преобразует это значение в тип int и в итоге вызывается вариант MyMeth(int) данного метода. А еслиему передается значение типа float, то оно преобразуется в тип double и в результатевызывается вариант MyMeth(double) данного метода.
Следует, однако, иметь в виду, что неявные преобразования типов выполняютсялишь в том случае, если отсутствует точное соответствие типов параметра и аргумента.В качестве примера ниже приведена чуть измененная версия предыдущей программы,в которую добавлен вариант метода MyMeth(), где указывается параметр типа byte.// Добавить метод MyMeth(byte).using System;class Overload2 { public void MyMeth(byte x) { Console.WriteLine("В методе MyMeth(byte): " + x); } public void MyMeth(int x) { Console.WriteLine("В методе MyMeth(int): " + x); } public void MyMeth(double x) { Console.WriteLine("В методе MyMeth(double): " + x); }}class TypeConv { static void Main() { Overload2 ob = new Overload2(); int i = 10; double d = 10.1; byte b = 99; short s = 10; float f = 11.5F; ob.MyMeth(i); // вызвать метод ob.MyMeth(int) ob.MyMeth(d); // вызвать метод ob.MyMeth(double) ob.MyMeth(b); // вызвать метод ob.MyMeth(byte) -- // на этот раз без преобразования типа ob.MyMeth(s); // вызвать метод ob.MyMeth(int) -- с преобразованием типа ob.MyMeth(f); // вызвать метод ob.MyMeth(double) -- с преобразованием типа }}
Выполнение этой программы приводит к следующему результату.В методе MyMeth(int): 10В методе MyMeth(double): 10.1В методе MyMeth(byte): 99В методе MyMeth(int): 10В методе MyMeth(double): 11.5
В этой программе присутствует вариант метода MyMeth(), принимающий аргумент типа byte, поэтому при вызове данного метода с аргументом типа byte выбирается его вариант MyMeth(byte) без автоматического преобразования в тип int.Оба модификатора параметров, ref и out, также учитываются, когда принимаетсярешение о перегрузке метода. В качестве примера ниже приведен фрагмент кода, в котором определяются два совершенно разных метода.public void MyMeth(int x) { Console.WriteLine("В методе MyMeth(int): " + x);}public void MyMeth(ref int x) { Console.WriteLine("В методе MyMeth(ref int): " + x);}