C# 4.0 полное руководство - 2011
Шрифт:
struct XY<T> where Т : struct {
// ...
Создание обобщенного метода
Как следует из приведенных выше примеров, в методах, объявляемых в обобщенных классах, может использоваться параметр типа из данного класса, а следовательно, такие методы автоматически становятся обобщенными по отношению к параметру типа. Но помимо этого имеется возможность объявить обобщенный метод со своими собственными параметрами типа и даже создать обобщенный метод, заключенный в необобщенном классе.
Рассмотрим
// Продемонстрировать применение обобщенного метода, using System;
// Класс обработки массивов. Этот класс не является обобщенным, class ArrayUtils {
// Копировать массив, вводя по ходу дела новый элемент.
// Этот метод является обобщенным.
public static bool CopyInsert<T> (Т e, uint idx,
T[] src, T[] target) {
// Проверить, насколько велик массив, if(target.Length < src.Length+1) return false;
// Скопировать содержимое массива src в целевой массив,
// попутно введя значение е по- индексу idx. for(int i=0, j=0; i < src.Length; i++, j++) { if(i == idx) { target[j] = e; j++;
}
target[j] = src[i];
}
return true;
}
}
class GenMethDemo { static void Main {
int[] nums = { 1, 2, 3 }; int[] nums2 = new int [4];
// Вывести содержимое массива nums.
Console.Write("Содержимое массива nums: ") ; foreach(int x in nums)
Console.Write(х + " ") ;
Console.WriteLine ;
// Обработать массив типа int.
ArrayUtils.Copylnsert(99, 2, nums, nums2);
// Вывести содержимое массива nums2.
Console.Write("Содержимое массива nums2: "); foreach(int x in nums2)
Console.Write(x + " ") ;
Console.WriteLine;
//А теперь обработать массив строк, используя метод copylnsert. string[] strs = {"Обобщения", "весьма", "эффективны."}; string[] strs2 = new string[4];
// Вывести содержимое массива strs.
Console.Write("Содержимое массива strs: "); foreach(string s in strs)
Console.Write(s + " ");
Console.WriteLine;
// Ввести элемент в массив строк.
ArrayUtils.Copylnsert("в
// Вывести содержимое массива strs2.
Console.Write("Содержимое массива strs2: "); foreach(string s in strs2)
Console.Write(s + " ");
Console.WriteLine;
// Этот вызов недопустим, поскольку первый аргумент // относится к типу double, а третий и четвертый // аргументы обозначают элементы массивов типа int.
// ArrayUtils.Copylnsert(0.01, 2, nums, nums2);
}
}
Вот к какому результату приводит выполнение этой программы.
Содержимое массива nums: 1 2 3 Содержимое массива nums2: 1 2 99.3
Содержимое массива strs: Обобщения весьма эффективны.
Содержимое массива strs2: Обобщения в C# весьма эффективны.
Внимательно проанализируем метод CopyInsert. Прежде всего обратите внимание на объявление этого метода в следующей строке кода.
public static bool CopyInsert<T>(Т e, uint idx,
T[] src, T[] target) {
Параметр типа объявляется после имени метода, но перед списком его параметров. Обратите также внимание на то, что метод Copylnsert является статическим, что позволяет вызывать его независимо от любого объекта. Следует, однако, иметь в виду, что обобщенные методы могут быть либо статическими, либо нестатическими. В этом отношении для тшх не существует никаких ограничений.
Далее обратите внимание на то, что метод Copylnsert вызывается в методе Main с помощью обычного синтаксиса и без указания аргументов типа. Дело в том, что типы аргументов различаются автоматически, а тип Т соответственно подстраивается. Этот процесс называется выводимостью типов. Например, в первом вызове данного метода
ArrayUtils.Copylnsert (99, 2, nums, nums2);
тип T становится типом int, поскольку числовое значение 99 и элементы массивов nums и num&2 относятся к типу int. А во втором вызове данного метода используются строковые типы, и поэтому тип Т заменяется типом string.