ВниМание
Вызов.метода,.принимающего.переменное.число.аргументов,.снижает.производи-
тельность,.если,.конечно,.не.передавать.в.явном.виде.значение.null .В.любом.случае.
всем.объектам.массива.нужно.выделить.место.в.куче.и.инициализировать.элементы.
массива,.а.по.завершении.работы.занятая.массивом.память.должна.быть.очищена.
сборщиком.мусора .Чтобы.уменьшить.негативное.влияние.этих.операций.на.про-
изводительность,.можно.определить.несколько.перегруженных.методов,.в.которых.
не.используется.ключевое.слово.params .За.примерами.обратитесь.к.методу.Concat.
класса.System String,.который.перегружен.следующим.образом:
public sealed class String : Object, ... {
public static string Concat(object arg0);
public static string Concat(object arg0, object arg1);
public static string Concat(object arg0, object arg1, object arg2);
public static string Concat(params object[] args);
public static string Concat(string str0, string str1);
public static string Concat(string str0, string str1, string str2);
public static string Concat(string str0, string str1, string str2, string
str3);
public static string Concat(params string[] values);
}
Как.видите,.для.метода.Concat.определены.несколько.вариантов.перегрузки,.в.ко-
торых.ключевое.слово.params.не.используется .Здесь.представлены.наиболее.рас-
пространенные.варианты.перегрузки,.которые,.собственно,.и.предназначены.для.
повышения.эффективности.работы.в.стандартных.ситуациях .Варианты.перегрузки.
с.ключевым.словом.params.предназначены.для.более.редких.ситуаций,.поскольку.
при.этом.страдает.производительность .К.счастью,.такие.ситуации.возникают.не.
так.уж.часто
типы параметров
и возвращаемых значений
Объявляя тип параметров метода, нужно по возможности указывать «минимальные»
типы, предпочитая интерфейсы базовым классам. Например, при написании метода,
работающего с набором элементов, лучше всего объявить параметр метода, исполь-
зуя интерфейс
IEnumerable
вместо сильного типа данных, например
List
,
или еще более сильного интерфейсного типа
ICollection
или
IList
:
260
Глава.9 .Параметры
// Рекомендуется в этом методе использовать параметр слабого типа
public void ManipulateItems(IEnumerable collection) { ... }
// Не рекомендуется в этом методе использовать параметр сильного типа
public void ManipulateItems(List collection) { ... }
Причина, конечно же, в том, что первый метод можно вызывать, передав в него
массив, объект
List
, объект
String
и т. п., то есть любой объект, тип которого
реализует интерфейс
IEnumerable
. Второй метод принимает только объекты
List
, с массивами или объектами
String
он работать уже не может. Ясно, что
первый метод предпочтительнее, так как он гибче и может использоваться в более
разнообразных ситуациях.
Естественно, при создании метода, получающего список (а не просто любой
перечислимый объект), нужно объявлять тип параметра как
IList
, в то время
как типа
List
лучше избегать. Именно такой подход позволит вызывающему
коду передавать массивы и другие объекты, тип которых реализует
IList
.
Обратите внимание, что в приводимых примерах речь идет о коллекциях, соз-
данных с использованием архитектуры интерфейсов. Этот же подход применим
к классам, опирающимся на архитектуру базовых классов. Потому, к примеру, при
реализации метода, обрабатывающего байты из потока, пишем следующее:
// Рекомендуется в этом методе использовать параметр мягкого типа
public void ProcessBytes(Stream someStream) { ... }
// Не рекомендуется в этом методе использовать параметр сильного типа
public void ProcessBytes(FileStream fileStream) { ... }
Первый метод может обрабатывать байты из потока любого вида:
FileStream
,
NetworkStream
,
MemoryStream
и т. п. Второй поддерживает только
FileStream
,
то есть область его применения ограничена.
В то же время, объявляя тип возвращаемого методом объекта, желательно
выбирать самый сильный из доступных вариантов (пытаясь не ограничиваться
конкретным типом). Например, лучше объявлять метод, возвращающий объект
FileStream
, а не
Stream
:
// Рекомендуется в этом методе использовать
// сильный тип возвращаемого объекта
public FileStream OpenFile() { ... }
// Не рекомендуется в этом методе использовать
// слабый тип возвращаемого объекта
public Stream OpenFile() { ... }
Здесь предпочтительнее первый метод, так как он позволяет вызывающему коду
обращаться с возвращаемым объектом как с объектом
FileStream
или
Stream
. А вот
второму методу требуется, чтобы вызывающий код рассчитывал только на объект
Stream
, то есть область его применения более ограничена.
Иногда требуется сохранить возможность изменять внутреннюю реализацию
метода, не влияя на вызывающий код. В приведенном ранее примере изменение
реализации метода
OpenFile
в будущем маловероятно, он вряд ли будет возвра-
261
Константность
щать что-либо отличное от объекта типа
FileStream
(или типа, производного от
FileStream
). Однако для метода, возвращающего объект
List
, вполне воз-
можно изменение реализации, после которого он начнет возвращать тип
String[]
.
В подобных случаях следует выбирать более слабый тип возвращаемого объекта.
Например:
// Гибкий вариант: в этом методе используется
// мягкий тип возвращаемого объекта
public IList GetStringCollection() { ... }
// Негибкий вариант: в этом методе используется
// сильный тип возвращаемого объекта
public List GetStringCollection() { ... }
Хотя в коде метода
GetStringCollection
используется и возвращается объ-
ект
List
, в прототипе метода лучше указать в качестве возвращаемого
объекта
IList
. Даже если в будущем указанная в коде метода коллекция
изменит свой тип на
String[]
, вызывающий код не потребуется ни редактировать,
ни даже перекомпилировать. Обратите внимание, что в этом примере я выбрал са-
мый «сильный» из самых «слабых» типов. К примеру, я не воспользовался типом
IEnumerable
или
ICollection
.
Do'stlaringiz bilan baham: |