§8.1
List views 129
u.Sort(...)
and
u.Shuffle(...)
where
u
is a list or list view, affect another
view
w
of the same underlying list as follows:
 If
w
contains
u
,then the offset and length of
w
are unchanged.
 Otherwise, if
u
contains
w
(but not vice versa), then
w
is invalidated.
It follows that when
u
is a proper list, then all views of
u
except zero-item
views at its ends are invalidated.
 Otherwise, if
u
and
w
do not overlap, then
w
is unchanged.
In particular, any zero-item views at the ends of
u
are unchanged.
 Otherwise, if
u
and
w
overlap but none is contained in the other, then
w
is
invalidated.
These cases are exhaustive. Also, when
u
is a zero-item or one-item view, then
u.Sort(...)
and
u.Shuffle(...)
affect no other view.
8.1.7 List views and event handlers
One cannot attach an event handler (section 8.8) to a view, only to the underlying
list. Consequently, the item positions reported via the event arguments when an
event is raised are the absolute positions in the underlying list, even if the event
was raised as a consequence of calling a method on some view.
An attempt to add or remove an event handler on a view will throw InvalidOp-
erationException.
One can determine whether an event such as
ItemInserted(coll, args)
has af-
fected a given view
u
by examining
args
which is an object of class
ItemAtEventArgs
;
see section 8.8.6. Let
uo
be the
Offset
and
uc
the
Count
of view
u
before the event.
Then the event affected the view if
uo <= args.Index && args.Index < uo + uc
.
Also, when an operation such as
Clear
is applied to a view
u
,it raises a Collec-
tionCleared event (and no ItemsRemoved events) on the underlying list. The event
argument will be a
ClearedRangeEventArgs
object whose
Full
eld is false, whose
Start
eld is
uo
and whose
Count
eld is
uc
,where
uo
is the
Offset
and
uc
the
Count
of view
u
before the
Clear
operation.
8.1.8 Views of a guarded list, and guarded views of a list
One can create a view
vg
of a GuardedList<T> (section 8.2). Clearly, such a view
does not permit updates of the underlying list, but one can slide the view, and one
can obtain and inspect (but not update) the underlying list
vg.Underlying
. Hence
one cannot use a view of a guarded list to hide parts of that list from a client.
Conversely one can put a GuardedList<T> wrapper around a list view to obtain
aguarded view
gv
of a list. A guarded view does not permit updating nor sliding,
but one can still use it to obtain and inspect (but not update) the underlying list
gv.Underlying
.Hence one cannot use a guarded view of a list to hide parts of that
list from a client.
Pdf to tiff file conversion - control Library system:C# PDF Convert to Tiff SDK: Convert PDF to tiff images in C#.net, ASP.NET MVC, Ajax, WinForms, WPF
Online C# Tutorial for How to Convert PDF File to Tiff Image File
www.rasteredge.com
Pdf to tiff file conversion - control Library system:VB.NET PDF Convert to Tiff SDK: Convert PDF to tiff images in vb.net, ASP.NET MVC, Ajax, WinForms, WPF
Free VB.NET Guide to Render and Convert PDF Document to TIFF
www.rasteredge.com
130 Read-only wrappers
§8.2
8.2 Read-only wrappers
To provide read-only access to a collection, wrap it as a guarded collection. The
IsReadOnly
property of a guarded collection is true. Structural modications such
as adding, inserting, updating or removing items will throw ReadOnlyCollectionEx-
ception. However, a guarded collection cannot itself prevent modications inside
each of the collection’s items. A guarded collection is not a copy of the underlying
collection
coll
,just a view of it, so modications to the underlying collection will be
visible through the guarded-collection wrapper.
Typically the guarded collection will be passed to a method
DoWork
or some other
consumer that must be prevented from modifying the collection. For instance, for
aHashSet<T> collection the appropriate wrapper class is GuardedCollection<T>,
and the wrapper could be created and used like this:
HashSet<T> coll = ...;
DoWork(new GuardedCollection<T>(coll));
The method
DoWork
can be declared to take as argument an ICollection<T>; that
interface describes all the members of the GuardedCollection<T> class:
void DoWork<T>(ICollection<T> gcoll) { ... }
Similar read-only wrappers exist for the other collection classes and for the dictio-
nary classes. For each class the relevant read-only wrapper and the corresponding
interface are shown in gure 8.2. To create a read-only list view (section 8.1) use
the GuardedList<T> wrapper; the resulting view cannot be slid and its
Underlying
property returns a read-only list.
Class
Read-only wrapper classes
Interface
HashSet<T>
GuardedCollection<T>
ICollection<T>
HashBag<T>
GuardedCollection<T>
ICollection<T>
TreeSet<T>
GuardedIndexedSorted<T>
IIndexedSorted<T>
TreeBag<T>
GuardedIndexedSorted<T>
IIndexedSorted<T>
SortedArray<T>
GuardedIndexedSorted<T>
IIndexedSorted<T>
ArrayList<T>
GuardedList<T>
IList<T>
HashedArrayList<T>
GuardedList<T>
IList<T>
LinkedList<T>
GuardedList<T>
IList<T>
HashedLinkedList<T>
GuardedList<T>
IList<T>
CircularQueue<T>
GuardedQueue<T>
IQueue<T>
HashDictionary<K,V>
GuardedDictionary<K,V>
IDictionary<K,V>
TreeDictionary<K,V>
GuardedSortedDictionary<K,V>
ISortedDictionary<K,V>
Figure 8.2: Read-only wrappers for collection and dictionary classes.
There is no wrapper class for priority queues; a read-only priority queue is not
very useful. A read-only FIFO queue, on the other hand, can at least be indexed
control Library system:Online Convert PDF file to Word. Best free online PDF Conversion
area. Then just wait until the conversion from Tiff/Tif to PDF is complete and download the file. The perfect conversion tool. Your
www.rasteredge.com
control Library system:Online Convert PDF file to Tiff. Best free online PDF Tif
area. Then just wait until the conversion from PDF to Tiff is complete and download the file. The perfect conversion tool. Your Tiff
www.rasteredge.com
§8.2
Read-only wrappers 131
into. Some additional read-only wrapper classes are used when developing custom
collection classes as described in section 14.1.
You may wonder why weuseguarded collection wrappers, which detect modica-
tion attempts only at run-time, instead of ‘read-only’ interfaces, which could detect
modication attempts at compile-time simply by omitting operations that modify
the collection. The reason is that the ‘read-only’ interface approach does not work.
Namely, consider a hypothetical read-only interface IReadonlyList<T> that is
like IList<T> except that it does not expose operations that can modify the list.
Then we would expect that e.g. ArrayList<T> implements IReadonlyList<T>, and
we could pass an array list as an IReadonlyList<T> object
readonlyList
whenever
we want to guard it. However, the recipient could perform a run-time type test and
cast
readonlyList
down to LinkedList<T>, thus subverting all protection ofthe list.
This particular problem could be avoided by having distinct implementation
classes ArrayList<T> : IList<T> and GuardedList<T> : IReadonlyList<T>, and pre-
sumably IList<T> : IReadonlyList<T> so that a read-write list can be used every-
where a read-only list is expected. One problem with this is that a list view taken
off an IList<T> should implement IList<T>, whereas one taken off an IReadon-
lyList<T> should be a GuardedList<T> that implements IReadonlyList<T>. Hence
the return types of the
ViewOf(T)
and
View
and
Slide
methods would have to be
different in the two interfaces, which is currently not possible in the C# language,
although the CLI/.NET intermediate language does support co-variant return types.
control Library system:C# TIFF: C#.NET Code to Convert TIFF Image File
Online C# tutorial for high-fidelity Tiff image file conversion from MS Office Word, Excel, and PowerPoint document. Convert PDF to Tiff Using C#.
www.rasteredge.com
control Library system:C# Create PDF from Tiff Library to convert tif images to PDF in C#
a quick evaluation of our XDoc.PDF file conversion functionality tif"; String outputFilePath = Program.RootPath + "\\" Output.pdf"; // Load a TIFF file.
www.rasteredge.com
132 Collections of collections
§8.3
8.3 Collections of collections
Sometimes it is useful to create a collection whose items are themselves collec-
tions. For instance, one may use a dictionary whose keys are bags of characters
(section 11.4), or a dictionary whose keys are sets of integers (section 11.5). The
collection that contains other collections as items will be called the outer collection
and the collections that appear as items in the outer collection will be called inner
collections.
It is important that the inner collections have appropriate comparers or equality
comparers, including hash functions. Assume that the inner collection type is S and
that its item type is W; for instance, S may be HashSet<W> or ISorted<W>:
 When the outer collection is hash-based, an item equality comparer of type
SCG.IEqualityComparer<S> for the inner collections is created automatically;
see section 2.3. Usually this default equality comparer is appropriate.
For instance, when the inner collection type S implements ISequenced<W>,
thedefault equality comparerisa SequencedCollectionEqualityComparer<S,W>
whoseequality andhash function take intoaccount theorder of items in the in-
ner collections. A sequenced equality comparer will be used when inner collec-
tions of type LinkedList<W>, ArrayList<W>, SortedArray<W>, TreeSet<W>,
or TreeBag<W> are used as items in a hash-based outer collection.
When the inner collection type S is unsequenced, that is, implements ICollec-
tionValue<W> but not ISequenced<W>, the default equality comparer will be
an UnsequencedCollectionEqualityComparer<T,W> whose equality and hash
function ignore the order of items in the inner collections. An unsequenced
equality comparer will be used when inner collections of type HashSet<W> or
HashBag<W> are used as items in a hash-based outer collection.
 Correctness Warning: Modications to an inner collection after it has been
inserted as an item in an outer collection should be avoided. If the inner
collection’s equality function, hash function or comparer are affected by the
modication, the inner collection may be lost and no longer retrievable from
the outer collection, which will most likely cause strange errors; see antipat-
tern 132. A safe way to avoid such problems is make a read-only copy of the
inner collection before storing it in the outer collection. Tree snapshots are
ideal for this purpose; see pattern 86 and section 8.5.
 Correctness Warning: It is possible for a collection to be a member of itself,
but equality functions, hash functions and comparers are likely to go into an
innite loop or overow the call stack when applied to such a collection.
control Library system:Online Convert Excel to PDF file. Best free online export xlsx
The perfect conversion tool. Your Excel file is converted to look just the same as it does in your office software. Creating a PDF from xlsx/xls has never been
www.rasteredge.com
control Library system:C# TIFF: TIFF Editor SDK to Read & Manipulate TIFF File Using C#.
1. Tiff to PDF/Jpeg conversion. 2. Word/Excel/PPT/PDF/Jpeg to Tiff conversion. Tiff File Processing in C#. Refer to this online tutorial page, you will see:
www.rasteredge.com
§8.4
Generic bulk methods 133
8.4 Generic bulk methods
You may wonder why some methods take a generic type parameter where one does
not seem to be needed. For instance, interface IExtensible<T> describes this generic
method that takes a type parameter U:
void AddAll<U>(SCG.IEnumerable<U> xs) where U : T;
One might think that this simpler non-generic method would sufce:
void AddAll(SCG.IEnumerable<T> xs);
However, the version with the additional generic type parameter is more generally
applicable. To see this, consider a class Vehicle with a subclass Car, and assume you
have two variables
vehicles
and
cars
,bound to lists of vehicles and cars, respec-
tively:
IList<Vehicle> vehicles = ...;
IList<Car> cars = ...;
Further suppose you want to add all items from
cars
to the
vehicles
list. Clearly
you could use
vehicles.Add(car)
to adda single Car to the
vehicles
list. However, if
only the second, non-generic version of
AddAll
is available, you cannot apply
AddAll
to the
cars
list like this:
vehicles.AddAll(cars);
// Illegal: cars not of type SCG.IEnumerable<Vehicle>
The problem is that although Car is a subtype of Vehicle, IList<Car> is not asubtype
of IList<Vehicle> and does not implement SCG.IEnumerable<Vehicle>.
The rst, generic version of
AddAll
solves the problem by introducing some extra
exibility. Namely, the additional type parameter U may be instantiated to Car.
First, this satises the type parameter constraint
U : T
since Car is a subclass of
Vehicle, and secondly, it makes
cars
alegal rst argument for
AddAll<Car>
:
vehicles.AddAll<Car>(cars);
// Legal: cars has type SCG.IEnumerable<Car>
The extra type parameter U on
AddAll
partially compensates for the fact that the
IList<T> type is neither covariant nor contravariant in the type parameter T.
The following generic bulk methods are described by interfaces IExtensible<T>,
ICollection<T>, IList<T> and ISorted<T>:
void AddAll<U>(SCG.IEnumerable<U> xs) where U : T
void AddSorted<U>(SCG.IEnumerable<U> xs) where U : T
bool ContainsAll<U>(SCG.IEnumerable<U> xs) where U : T
bool ContainsAny<U>(SCG.IEnumerable<U> xs) where U : T
void InsertAll<U>(int i, SCG.IEnumerable<U> xs) where U : T
void RemoveAll<U>(SCG.IEnumerable<U> xs) where U : T
void RetainAll<U>(SCG.IEnumerable<U> xs) where U : T
control Library system:.NET PDF Document Viewing, Annotation, Conversion & Processing
Convert PDF to Word (.docx). Convert PDF to images, like Tiff. Convert image files to PDF. File & Page Process. Create new file, load PDF from existing files.
www.rasteredge.com
control Library system:C# PDF Converter Library SDK to convert PDF to other file formats
in C#, you can easily perform file conversion from PDF document to image or document, or from PDF document to other file formats, like multi-page TIFF file.
www.rasteredge.com
134 Sorting arrays
§8.6
8.5 Snapshots of tree-based collections
Tree-based sets and tree-based bags in C5 support efcient snapshots. In constant
time, regardless of the size of the set or bag, one can obtain a persistent (read-only)
copy the set or bag. Subsequent modication ofthe original set or bag will be slightly
slower and will use slightly more space; see sections 12.6 and 13.10.
Nevertheless, constant-time snapshots offer several advantages:
 One can iterate (using
foreach
)over a snapshot of a set or bag while updat-
ing the set or bag. Recall that usually one cannot update a collection while
iterating over it.
 Snapshots can be used to easily implement rather advanced and very efcient
algorithms, such as point location in the plane; see section 11.9.
8.6 Sorting arrays
Class Sorting provides several generic methods for sorting one-dimensional arrays:
static void
IntroSort
<T>(T[] arr, int i, int n, SCG.IComparer<T> cmp)
sorts
arr[i..(i+n-1)]
using introspective quicksort and comparer
cmp
. This
sorting algorithm is not stable but guaranteed efcient, with worst-caseexecu-
tion time
O
(
nlog n
). It must holdthat
0 <= i
and
0 <= n
and
i+n <= arr.Length
.
static void
IntroSort
<T>(T[] arr)
sorts
arr
using introspective quicksort
and the default comparer for type T. This sorting algorithm is not stable but
guaranteed efcient, with execution time
O
(
nlog n
)where
n
is the length of
arr
.
static void
InsertionSort
<T>(T[] arr, int i, int n, SCG.IComparer<T> cmp)
sorts
arr[i..(i+n-1)]
using insertion sort and comparer
cmp
. This method
should be used only on short array segments, when
n
is small; say, less than
20.
static void
HeapSort
<T>(T[] arr, int i, int n, SCG.IComparer<T> cmp)
sorts
arr[i..(i+n-1)]
using heap sort and comparer
cmp
. This sorting algo-
rithm is not stable but guaranteed efcient, with execution time
O
(
nlog n
). In
practice it is somewhat slower than introspective quicksort.
In addition tothe above array sort methods,the library provides an implementation
of merge sort for linked lists, via the
Sort
method; see page 73.
control Library system:C# TIFF: Easy to Convert PDF Document to TIFF Image File
programmers to transform and convert other file formats to Tiff imaging converting SDK, RasterEdge XDoc.Tiff for .NET, can easily convert PDF document to
www.rasteredge.com
§8.8
Formatting of collections and dictionaries 135
8.7 Formatting of collections and dictionaries
For debugging purposes it is convenient to format or print collections and dictio-
naries as strings. However, it is inefcient and inconvenient to print a collection
with 50,000 items to the console. Therefore the collection classes provide facili-
ties for limiting the amount of output, displaying ellipses 
...
 in the resulting
string to indicate that some items are not shown. They do so by implementing the
C5.IShowable interface (section 3.9), which derives from System.IFormattable.
The results of formatting various kinds of collections and dictionaries are out-
lined in gure 8.3.
Class
Output format
Note
Array list orsorted array
[ 0:x
0
,

, n:x
n
]
Linked list
[ x
0
,

, x
n
]
Circular queue
[ x
0
,

, x
n
]
Priority queue
{ x
0
,

, x
n
}
Hash set or tree set
{ x
0
,

, x
n
}
Hash bag or tree bag
{{ x
0
(*m
0
),

, x
n
(*m
n
) }}
if
x
i
has multiplicity
m
i
Tree dictionary
[ k
0
=> v
0
,

, k
n
=> v
n
]
Hash dictionary
{ k
0
=> v
0
,

, k
n
=> v
n
}
Record
( x
0
,

, x
n
)
Figure 8.3: Formatting of collections with items
x
0
,,
x
n
,and of dictionaries with
(key,value) pairs (
k
0
,
v
0
), , (
k
n
,
v
n
).
In general,
[

]
is a sequenced indexedcollection;
{

}
is an unsequenced collection
with set semantics;
{{

}}
is an unsequenced collection with bag semantics; and
(

)
is a record: a pair, triple or quadruple.
The formatting of a collection or dictionary
coll
as a string can be requested in
several different ways:
String.Format("{0}", coll)
returns aformatted version of
coll
;this is equiv-
alent to
coll.ToString()
.
String.Format("{0:L327}", coll)
returns a formatted version of
coll
using
up to roughly 327 characters. Items omitted from the output because of the
space limit are displayed using an ellipsis .... The formatting specier
"L327"
can beusedalso in calls to the methods
Console.WriteLine
,
String.Format
and
StringBuilder.AppendFormat
.
Both the above formatting methods draw on the same underlying formatting rou-
tines, so the formatted result will be the same. Formatting is applied recursively,
so formatting a linked list of sets of integers may produce a result of the form
[{1,2},{1,3}]
.
All collection classes implement the interfaceSystem.IFormattable to permit the
use of formatting specications as shown above. The actual implementation of out-
put limitation is specied by interface IShowable; see section 3.9.
136 Events: Observing changes to a collection
§8.8
8.8 Events: Observing changes to a collection
Often one part of a system needs to be notied when another part of the system is
modied in some way. For instance, a graphical display may need to be updated
when items are added to or removed from a list of possible choices. To obtain no-
tication about such modications of a collection, one associates an event handler,
which is a delegate, with a particular event on the collection. When the collection is
modied by an insertion, say, the relevant event is raised by calling the associated
event handler (if any).
8.8.1 Design principles for collection events
 The events raised by modifying a collection should permit observers to ef-
ciently discover in what way the collection was modied.
In principle, it would sufce to report that the collection changed somehow
and leave it to the observer to determine what happened by inspection of the
collection. But that may be very inefcient if the change is the removal of
asingle item from a million-item collection. Hence C5 provides events that
report precisely the item(s) affected by the change.
 It should be safe for the event handler to inspect the collection.
Therefore events are raised, and event handlers called, only when the collec-
tion is in a consistent state, and only after an update has been successfully
performed on the collection.
 The sequence of events raised by a collection update should accurately reect
the resulting state of the collection.
This holds even if the update fails by throwing an exception (other than by
acomparer or equality comparer), and it holds even for a bulk update that
partially updates the collection and then throws an exception.
 Events should be precise: an event is raised only if there is an actual changeto
the collection, not just as aconsequenceofcalling amethod such as
AddAll(xs)
.
Such a call will actually cause no change if
xs
is empty, or if the collection has
set semantics and contains all items of
xs
already.
 The use or non-use of events should not change the asymptotic run-time or
space complexity of an operation.
As a consequence of this principle, the
Clear
method does not generate an
ItemsRemoved event for every item removed, only a CollectionCleared event
and a CollectionChanged event. Note that this holds even for a
Clear
opera-
tion on a list view. So
list.View(0,10).Clear()
,which removes the rst 10
items from
list
,will not generate ten ItemsRemoved events, but one Collec-
tionCleared event that carries a description of the range of indexes cleared.
§8.8
Events: Observing changes to a collection 137
Similarly, let
bag
be a bag collection for which
DuplicatesByCounting
is true.
Then
bag.Update(x)
raises the three events ItemsRemoved, ItemsAdded and
CollectionChanged once each with an event argument giving the multiplicity
of
x
in the bag, regardless of that multiplicity, and even though all copies of
x
are updated.
 The
Reverse
,
Shuffle
,and
Sort
operations on a list generate only a Collec-
tionChanged event, no ItemsAdded or ItemsRemoved events. Therefore the
precise effect of such multi-item operations cannot be tracked using events;
one must inspect the collection to establish its state.
 A sequence of descriptive events signaling the concrete changes is always fol-
lowed by a CollectionChanged event that signals the end of information about
this update.
 A CollectionChanged event is preceded by one or more descriptive events, ex-
cept in the case of multi-item updates caused by
Reverse
,
Shuffle
or
Sort
,
whereaCollectionChanged event may followanother CollectionChanged event
without any intervening events.
8.8.2 Interfaces, events and event handlers
An event handler for an event X is a delegate of type XHandler. When an event
is raised, the handlers currently associated with that event are called. Figure 8.4
shows the events supported by the C5collection library, as well as the event handler
type (delegate type, see section 8.8.5) and event argument type for each event. All
events are declared in the ICollectionValue<T> interface.
When an event handler is called, the internal stateof the collection is consistent,
so it is safe for the event handler to use the collection, for instance query its size,
or enumerate its items. However, the event handler should not modify the collec-
tion. Such modication may cause confusion at the code that caused the original
modication and may lead to an innite chain of collection changes and event han-
dler calls. Moreover, the collection class implementations do not protect themselves
against such changes, so they may lead to inexplicable failures.
For efciency, an observer should add handlers only for events that are interest-
ing to the observer. Section 9.23 shows some usage patterns for event handlers.
Event
Event handlertype
Page
Event argument type
Page
CollectionChanged
CollectionChangedHandler<T> 139
(none)
CollectionCleared
CollectionClearedHandler<T>
139
ClearedEventArgs
141
ItemsAdded
ItemsAddedHandler<T>
140
ItemCountEventArgs<T> 142
ItemInserted
ItemInsertedHandler<T>
140
ItemAtEventArgs<T>
141
ItemsRemoved
ItemsRemovedHandler<T>
140
ItemCountEventArgs<T> 142
ItemRemovedAt
ItemRemovedAtHandler<T>
140
ItemAtEventArgs<T>
141
Figure 8.4: Events, event handler types, and event argument types.
138 Events: Observing changes to a collection
§8.8
8.8.3 Methods and the event sequences they raise
Figure 8.5shows for each method the sequence of events it may raise. A (+) after an
event sequence means that the event sequence may be repeated one or more times.
Square brackets [...] around an event means that it may be omitted. If a call to
AddAll
,
Clear
,
RemoveAll
,
RemoveAllCopies
,
RetainAll
or
RemoveInterval
does not
modify the collection, then no events are raised, not even CollectionChanged.
Methods
Event sequence
Add
ItemsAdded, CollectionChanged
AddAll
ItemsAdded+, CollectionChanged
Clear
CollectionCleared,CollectionChanged
Insert
,
InsertFirst
,...
ItemInsertedAt, ItemsAdded,CollectionChanged
InsertAll
(ItemInsertedAt, ItemsAdded)+,CollectionChanged
Remove
ItemsRemoved, CollectionChanged
RemoveAt
,
RemoveFirst
,... ItemRemovedAt, ItemsRemoved,CollectionChanged
RemoveAll
,
RetainAll
ItemsRemoved+,CollectionChanged
RemoveInterval
CollectionCleared,CollectionChanged
RemoveAllCopies
ItemsRemoved, CollectionChanged
Update
ItemsRemoved, ItemsAdded,CollectionChanged
UpdateOrAdd
[ItemsRemoved,] ItemsAdded,CollectionChanged
this[i]=x
ItemRemovedAt, ItemsRemoved,
ItemInserted,ItemsAdded, CollectionChanged
Push
,
Enqueue
ItemInserted,ItemsAdded, CollectionChanged
Pop
,
Dequeue
ItemRemovedAt, ItemsRemoved,CollectionChanged
Figure 8.5: Methods and their event sequences. An event sequence followed by (+)
may be raised one or more times. An event within [...] may or may not be raised.
8.8.4 Listenable events
All six events are dened on interface ICollectionValue<T> (section 4.2) but some
collection implementations support only a subset of the events, as shown in g-
ure 8.6. The results are those reported by property
ListenableEvents
(see page 49)
using type EventTypeEnum (section 3.1).
8.8.5 The event handler types
An event handler is a delegate. All event handlers in C5 have return type
void
,
but each event handler takes a specic argument that provides information about
the event. In all cases, the collection that was modied (the so-called sender of the
event) is passed to the event handler as the rst argument. For list collections,
the sender is always the underlying list, even if the modication was performed by
calling a method on a view of that list.
Documents you may be interested
Documents you may be interested