Книга: C# 2008 Programmer
System.Collections.ObjectModel
System.Collections.ObjectModel
The System.Collections.ObjectModel
namespace in the .NET class library contains several generic classes that deal with collections. These classes are described in the following table.
Generic Class | Description |
---|---|
Collection<T> |
Provides the base class for a generic collection. |
KeyedCollection<TKey, TItem> |
Provides the abstract base class for a collection whose keys are embedded in the values. |
ObservableCollection<T> |
Represents a dynamic data collection that provides notifications when items get added, removed, or when the whole list is refreshed. |
ReadOnlyCollection<T> |
Provides the base class for a generic read-only collection. |
ReadOnlyObservableCollection<T> |
Represents a read-only ObservableCollection<T> . |
Let's take a look at Collection<T>
, one of the classes available. It is similar to the generic List<T>
class. Both Collection<T>
and List<T>
implement the IList<T>
and ICollection<T>
interfaces. The main difference between the two is that Collection<T>
contains virtual methods that can be overridden, whereas List<T>
does not have any.
The List<T>
generic class is discussed in details in Chapter 13.
The following code example shows how to use the generic Collection<T>
class:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Collections.ObjectModel;
namespace CollectionEg1 {
class Program {
static void Main(string[] args) {
Collection<string> names = new Collection<string>();
names.Add("Johnny");
names.Add("Michael");
names.Add("Wellington");
foreach (string name in names) {
Console.WriteLine(name);
}
Console.ReadLine();
}
}
}
Here's the example's output:
Johnny
Michael
Wellington
To understand the usefulness of the generic Collection<T>
class, consider the following example where you need to write a class to contain the names of all the branches a company has:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Collections.ObjectModel;
namespace CollectionEg2 {
class Program {
static void Main(string[] args) {}
}
public class Branch {
private List<string> _branchNames = new List<string>();
public List<string> BranchNames {
get {
return _branchNames;
}
}
}
}
In this example, the Branch
class exposes a public read-only property called BranchNames
of type List<T>
. To add branch names to a Branch
object, you first create an instance of the Branch
class and then add individual branch names to the BranchNames
property by using the Add()
method of the List<T>
class:
static void Main(string[] args) {
Branch b = new Branch();
b.BranchNames.Add("ABC");
b.BranchNames.Add("XYZ");
}
Suppose now that your customers request an event for the Branch
class so that every time a branch name is deleted, the event fires so that the client of Branch
class can be notified. The problem with the generic List<T>
class is that there is no way you can be informed when an item is removed.
A better way to resolve this issue is to expose BranchName
as a property of type Collection<T>
instead of List<T>
. That's because the generic Collection<T>
type provides four overridable methods — ClearItems()
, InsertItem()
, RemoveItem()
, and SetItem()
— which allow a derived class to be notified when a collection has been modified.
Here's how rewriting the Branch
class, using the generic Collection<T>
type, looks:
public class Branch {
public Branch() {
_branchNames = new BranchNamesCollection(this);
}
private BranchNamesCollection _branchNames;
public Collection<string> BranchNames {
get {
return _branchNames;
}
}
//---event raised when an item is removed---
public event EventHandler ItemRemoved;
//---called from within the BranchNamesCollection class---
protected virtual void RaiseItemRemovedEvent(EventArgs e) {
if (ItemRemoved != null) {
ItemRemoved(this, e);
}
}
private class BranchNamesCollection : Collection<string> {
private Branch _b;
public BranchNamesCollection(Branch b) _b = b;
//---fired when an item is removed---
protected override void RemoveItem(int index) {
base.RemoveItem(index);
_b.RaiseItemRemovedEvent(EventArgs.Empty);
}
}
}
There is now a class named BranchNamesCollection
within the Branch
class. The BranchNamesCollection
class is of type Collection<string>
. It overrides the RemoveItem()
method present in the Collection<T>
class. When an item is deleted from the collection, it proceeds to remove the item by calling the base RemoveItem()
method and then invoking a function defined in the Branch
class: RaiseItemRemovedEvent()
. The RaiseItemRemovedEvent()
function then raises the ItemRemoved event to notify the client that an item has been removed.
To service the ItemRemoved
event in the Branch
class, modify the code as follows:
static void Main(string[] args) {
Branch b = new Branch();
b.ItemRemoved += new EventHandler(b_ItemRemoved);
b.BranchNames.Add("ABC");
b.BranchNames.Add("XYZ");
b.BranchNames.Remove("XYZ");
foreach (string branchName in b.BranchNames) {
Console.WriteLine(branchName);
}
Console.ReadLine();
}
static void b_ItemRemoved(object sender, EventArgs e) {
Console.WriteLine("Item removed!");
}
And here's the code's output:
Item removed!
As a rule of thumb, use the generic Collection<T>
class (because it is more extensible) as a return type from a public method, and use the generic List<T>
class for internal implementation.
- The System.String Class
- System tools used for debugging
- Integrated Secure Communications System
- 6. COLLECTIONS OF DOCUMENTS
- Когда включаю компьютер, при загрузке пишется Insert system disk and press enter. Что нужно делать?
- На всех дисках моего компьютера есть папка System Volume Information. Для чего она нужна?
- 14.5.1. Open Systems Interconnection
- 5.3. TRENDS IN DISTRIBUTED FILE SYSTEMS
- Абстрактный базовый класс FileSystemInfo
- 1. Basic microprocessor systems
- CHAPTER 12 System-Monitoring Tools
- Navigating Through the File System