ICollection
Интерфейс
ICollection определяется производным от IEnumerable; он дополняет этот интерфейс
тремя свойствами, доступными только для чтения, и одним новым методом. Класс
ICollection редко реализуется самостоятельно. Как правило, он образует базу
для интерфейсов IList и IDictionary (см. ниже). Члены этого интерфейса перечислены
в табл. 5.2.
Таблица
5.2. Члены интерфейса ICollection
Метод/свойство |
Описание |
Count (свойство) | Возвращает количество элементов в коллекции |
IsSynchronized (свойство) | Используется в многопоточных приложениях (см. главу 12). Свойство возвращает True, если доступ к коллекции синхронизируется с учетом многопоточного доступа |
SyncRoot (свойство) | Также используется в многопоточных приложениях (см. главу 12). Свойство возвращает объект для синхронизации доступа к коллекции |
СоруТо (метод) | Копирует элементы из коллекции в массив, начиная с заданной позиции |
Интерфейс
ICollection реализуется классом System.Collections.CollectionBase.
Интерфейс
IList обеспечивает выборку элементов коллекции по индексу. Разумеется, поскольку
этот интерфейс определяется производным от I Enumerable, при этом сохраняется
возможность использования For-Each. Иерархия наследования IList выглядит следующим
образом:
IEnumerable->ICollection->IList
Интерфейс
IList относительно сложен — он состоит из трех свойств и семи методов (табл.
5.3). Напомним, что некоторые из методов могут быть пустыми, если в каком-то
конкретном классе их реализация не имеет смысла.
Таблица
5.3. Члены интерфейса IList
Метод/свойство |
Описание |
IsFixedSize (свойство) | Логическое свойство. Показывает, имеет ли коллекция фиксированный размер |
IsReadOnly (свойство) | Логическое свойство. Показывает, доступна ли коллекция только для чтения |
Item (свойство) | Свойство доступно для чтения и записи. Используется для получения и присваивания значения объекта с заданным индексом |
Add (ByVal value As Object) As Integer (метод) |
Включает объект в текущую позицию списка. Метод должен возвращать индекс, присвоенный добавленному элементу |
Clear (метод) |
Удаляет все элементы из списка |
Contains (ByVal
value As Object) As Boolean (метод) |
Метод предназначен
для проверки наличия в списке заданного значения. Эффективная реализация
этого метода иногда бывает весьма нетривиальной задачей. Если элемент
присутствует в списке, метод возвращает True; в противном случае возвращается
False |
IndexOf (ByVal
value As Object) As Integer (метод) |
Возвращает индекс
заданного объекта в списке (программист также должен учитывать эффективность
реализации этого метода) |
Insert(ByVal
index As Integer, ByVal value As Object) (метод) |
Вставляет объект
в заданную позицию списка |
Remove(ByVal
value As Object) (метод) |
Удаляет первое
вхождение заданного объекта в списке |
Remove(ByVal
index As Integer) (метод) |
Удаляет элемент,
находящийся в заданной позиции |
Интерфейс
IList реализуется классом System.Collections.CollectionBase.
Интерфейс
IDictionary представляет коллекцию, в которой доступ к данным осуществляется
по ключу — как в хэш-таблицах, описанных в предыдущей главе. Более того, класс
хэш-таблиц в числе прочих реализует интерфейсы IDictionary, ICollection, Enumerable
и ICloneable!
Хотя интерфейс
IDictionary объявляется производным от Enumerable и переход к следующему элементу
может осуществляться методом MoveNext, обычно такая возможность не используется
— коллекции, реализующие IDictionary, ориентируются в первую очередь на обращение
по ключу, а не на последовательный перебор элементов. По этой причине интерфейс
IDictionary зависит от интерфейса IDic-tionaryEnumerator, который расширяет
Enumerator и дополняет его тремя новыми свойствами:
В
.NET Framework входит класс DictionaryBase. Определяя класс производным от DictionaryBase,
вы получаете в свое распоряжение всю функциональность интерфейса IDictionary.
Члены класса
IDictionary перечислены в табл. 5.4.
Поскольку
ключи в ассоциативных коллекциях должны быть уникальными, при реали-зации большинства
методов необходимо сначала проверить, не был ли заданный ключ использован ранее.
Свойство Keys возвращает объект, реализующий ICollection; уникальность ключа
проверяется методом,Соп1а1п5 интерфейса ICollection.
Таблица
5.4. Члены интерфейса IDictionary
Метод/свойство |
Описание |
IsFixedSize
(свойство) |
Логическое свойство.
Показывает, имеет ли коллекция фиксированный размер |
IsReadOnly (свойство) |
Логическое свойство.
Показывает, доступна ли коллекция только для чтения |
Item (свойство) |
Свойство доступно
для чтения и записи. Используется для получения и присваивания значения
объекта с заданным индексом |
Keys (свойство) |
Возвращает объект,
реализующий интерфейс ICollection и содержащий все ключи ассоциативной
коллекции |
Values (свойство) |
Возвращает объект,
реализующий интерфейс ICollection и содержащий все значения ассоциативной
коллекции |
Add(ByVal key
As Object, ByVal value As Object) (метод) |
Добавляет объект
с заданным ключом (ключ должен быть уникальным) |
Clear (метод) |
Удаляет все
элементы из ассоциативной коллекции |
Contains (ByVal
key As Object) As Boolean (метод) |
Ищет значение
с заданным ключом |
GetEnumerator
(метод) |
Возвращает объект
IDictionaryEnumerator для работы с ключами и значениями |
Remove(ByVal
key As Object) (метод) |
Удаляет элемент
с заданным ключом |
Предположим,
коллекцию объектов Employee потребовалось отсортировать по заработной плате.
Конечно, операцию сортировки было бы удобно реализовать непосредственно в классе
Emplоуее, чтобы сортировка простого или динамического массива объектов этого
класса выполнялась так же просто, как сортировка строковых массивов. Оказывается,
порядок сортировки элементов, используемый методом Sort классов Array и ArrayList,
определяется интерфейсом IComparable (строковые массивы интерфейс IComparabl
e сортирует в порядке ASCII-кодов). Интерфейс состоит из единственного метода
CompareTo: Function CompareTo(ByValobj As Object) As Integer Метод возвращает
следующие значения:
Следующая
версия класса Employee реализует интерфейсы lEnumerable и IComparable и сортирует
массив по убыванию заработной платы:
Public Class
Employee
Implements IComparable
Private m_Name
As String
Private m_Salary
As Decimal
Private Const
LIMIT As Decimal =0.10
Public Sub New(ByVal theName As String,ByVal curSalary As Decimal)
m_Name = theName
m_Salary = curSalary
End Sub
Public Function
CompareTo(ByVal anEmployee As Object) As Integer _
Implements IComparable.CompareTo
If CType(anEmployee,Employee).Salany
< Me.Salary Then Return -1
El self CTypetanEmployee.Employee).Salary
= Me.Salary Then
Return 0
Elself CTypeCanEmployee,Employee).Salary
> Me.Salary Then
Return 1
End If
End Function
Public Readonly
Property TheName() As String Get
Return m_Name
End Get End Property
Public Readonly
Property Salary() As Decimal Get
Return MyClass.m_Salary
End Get End
Property
Public Overridable Overloads Sub RaiseSalary(ByVal Percent As Decimal)
If Percent >
LIMIT Then
' Операция запрещена - необходим пароль
Console.WriteLine("NEED PASSWORD TO RAISE SALARY MORE " & _
"THAN LIMIT!!!!")
Else
m_Salary =(1
+ Percent) * m_Salary
End If
End Sub
Public Overridable
Overloads Sub RaiseSalary(ByVal Percent As Decimal._
ByVal Password
As String) If Password = "special" Then
m_Salary =(1 + Percent) * m_Salary
End If
End Sub
End Class
Для тестирования
новой версии класса можно воспользоваться следующей программой:
Sub Main()
Dim torn As New Employee("Tom". 50000)
Dim sally'As New Employee("Sally", 60000)
Dim joe As New Employee("Joe", 20000)
Dim gary As New Employее("Gary", 1)
Dim theEmployees()
As Employee = _
{torn, sally,
joe. gary}
Array.Sort(theEmployees)
' Порядок сортировки определяется CompareTo!
Dim aEmployee As Employee
For Each aEmployee
In theEmployees
Console.WriteLine(aEmployee.TheName
& "has yearly salary $"
& FormatNumbertaEmployee.Salary))
Next
Console.ReadLine()
End Sub
Результат
показан на рис. 5.9.
Рис.
5.9. Сортировка по нестандартному критерию с использованием IComparable
.NET Framework позволяет выполнять сортировку по нескольким критериям. Например, чтобы упорядочить массив работников сначала по заработной плате, а затем по имени (в группах с одинаковой зарплатой) следует реализовать интерфейс IComparer, содержащий единственный метод СотрагеТо. При этом вы сможете воспользоваться одной из перегруженных версий Array. Sort (или ArrayList. Sort), которая имеет следующую сигнатуру:
Public
Shared Sub Sort(ByVal array As Array. ByVal comparer As IComparer)
Обычно в
программе создается отдельный класс, реализующий IComparer, и экземпляр этого
класса передается методу Sort. Пример такого класса приведен ниже. Обратите
внимание на выделенную строку — в ней имена работников передаются в виде строк
методу Compare класса String:
Public Class
SortByName
Implements IComparer
Public Function
CompareTo(ByVal firstEmp As Object.ByVal
secondEmp=As Object) As Integer Implements IComparer.Compare
Dim temp1 As Employee = CType(firstEmp,Employee)
Dim temp2 As Employee = CType(secondEmp.Employee)
Return
String.Compare(templ.TheName. temp2.TheName)
End Function
End Class
Пример процедуры
Sub Main с использованием этого класса:
SubMain()
Dim torn As
New Employee("Tom", 50000)
Dim sally As
New Employee("Sally". 60000)
Dim sam As New
Employee("Sam". 60000)
Dim ted As New
Employee("Ted". 50000)
Dim theEmployees() As Employee = _
{torn.sally,sam.ted}
Array.Sort(theEmployees)
Dim SortingByName
As SortByName = New SortByName()
Array.Sort(theEmployees,SortingByName)
Dim aEmployee
As Employee
For Each aEmployee
In theEmployees
Console.WriteLine(aEmployee.TheName & "has yearly salary $" &
FormatNumberCaEmployee.Salary))
Next
Console. ReadLine()
End Sub .
Результат
показан на рис. 5.10,
Рис.
5.10. Сортировка по нескольким критериям с использованием IComparer
В
программе можно определить несколько классов, реализующих IComparer. Их последовательное
применение позволяет выполнять многоуровневую сортировку произвольной глубины.