Представляется разумным, чтобы методы, реализующие один и тот же алгоритм для различного количества параметров или различных типов данных, имели одно и то же имя. Использование таких методов называется перегрузкой методов. Компилятор определяет, какой именно метод требуется вызвать, по типу и количеству фактических параметров.
Рассмотрим следующий пример:
class Program
{
//первая версия метода Max – возвращает значение наибольшей цифры
static int Max(int a) //заданного числа
{
int b = 0;
while (a > 0)
{
if (a % 10 > b) b = a % 10;
a /= 10;
}
return b;
}
//вторая версия метода Max – возвращает значение наибольшего из двух чисел
static int Max(int a, int b)
{
if (a > b) return a;
else return b;
}
//третья версия метода Max – возвращает значение наибольшего из трех чисел
static int Max(int a, int b, int c)
{
if (a > b && a > c) return a;
else if (b > c) return b;
else return c;
}
static void Main()
{
int a = 1283, b = 45, c = 35740;
Console.WriteLine(Max(a));
Console.WriteLine(Max(a, b));
Console.WriteLine(Max(a, b, c));
}
}
|
При вызове метода Max выбирается вариант, соответствующий типу и количеству передаваемых в метод аргументов. Если точного соответствия не найдено, выполняются неявные преобразования типов в соответствии с общими правилами. Если преобразование невозможно, выдается сообщение об ошибке. Если выбор перегруженного метода возможен более чем одним способом, то выбирается «лучший» из вариантов (вариант, содержащий меньшее количество и длину преобразований в соответствии с правилами преобразования типов). Если существует несколько вариантов, из которых невозможно выбрать подходящий, выдается сообщение об ошибке.
Замечание. В С# существует другой способ создания методов с переменным количеством параметров, он основывается на использовании массивов.
Если нужно реализовать один и тот же метод для различных типов (например, наш метод Max нужно было бы реализовать для int, double и float), то совсем не обязательно записывать несколько одинаковых методов. В .NET 2.0 можно использовать сокращенную запись перегруженных методов, сообщая компилятору только общие сведения о типе, используются обобщенные типы (Generic). Они отчасти напоминают шаблоны языка C++.
При объявлении обобщенного типа мы используем некоторый формальный (не существующий тип) - его мы можем использовать как тип переменных и методов, как тип параметров и т. п. Когда же мы создаем экземпляр Generic, то мы указываем уже конкретный тип. При этом формальный тип для данного экземпляра Generic заменяется на этот конкретный тип.
Рассмотрим небольшой пример:
using System;
// для работы с Generic мы подключаем специальный класс
using System.Collections.Generic;
using System.Text;
namespace Example
{
class Program
{
// Данный метод меняет значения двух переменных типа <T>. Тип Т пока не конкретизирован
static void Swap<T>(ref T a, ref T b)
{
Console.WriteLine("Передаем в Swap() метод {0}", typeof(T));
T temp;
temp = a;
a = b;
b = temp;
}
static void Main(string[] args)
{
int a = 1, b = 2;
Console.WriteLine("Перед swap: {0}, {1}", a, b);
Swap<int>(ref a, ref b); //передаем в Swap целый тип
Console.WriteLine("После swap: {0}, {1}", a, b);
Console.WriteLine();
double x = 3.2, y = -123.27;
Console.WriteLine("Перед swap: {0} {1}", x, y);
Swap<double>(ref x, ref y);
Console.WriteLine("После swap: {0} {1}", x, y);
Console.ReadLine();
}
}
}
|
Замечание. Перегрузка методов является проявлением полиморфизма, одного из основных принципов объектно-ориентированного программирования. Программисту гораздо удобнее помнить одно имя метода и использовать его для работы с различными типами данных, а решение о том, какой вариант метода вызвать, возложить на компилятор. Этот принцип широко используется в классах библиотеки .NET. Например, в стандартном классе Console метод WriteLine перегружен 19 раз для вывода величин разных типов.
|