Skip to content
BigBro222's Blog
LinkedInGitHub

Collections in C# (The basics 3)

C# basics2 min read

5. Commonly used interfaces and method implementation

interface.png
Figure 1 Hierarchy of interfaces in collection

The main interfaces of Collection

IEnumerable<T>

Exposes the enumerator, which supports a simple iteration over a collection of a specified type.

Collections that implement IEnumerable<T> can be enumerated by using the foreachstatement.

The foreach statement is a syntax sugar, it’s actually the MoveNext(), Current() and Reset() in IEnumerator<T> do the job.

ICollection<T>

The ICollection<T> interface extends IEnumerable<T>;IDictionary<TKey,TValue>  and IList<T>are more specialized interfaces that extend ICollection<T>. A IDictionary<TKey,TValue> implementation is a collection of key/value pairs, like the Dictionary<TKey,TValue>class. A IList<T>implementation is a collection of values, and its members can be accessed by index, like the List<T>class.

Methods: Add, Clear,Contains, Copy to, Remove ( Bold represents new methods apart from the parent interface )

Uses IEquatable<T> to determine whether a instance is in the collection, or you can write your own EqualityComparer<T> to determine for a specific collection. An example will be discussed later.

IList<T>

The IList<T> generic interface is a descendant of the ICollection<T> generic interface and is the base interface of all generic lists.

Methods: IndexOf, Insert, RemoveAt ( Bold represents new methods apart from the parent interface )

While deleting a element from the IList<T>, one should use for with a descending order instead of using foreach. Because RemoveAt() method will change the index of other elements.

IDictionary<TKey,TValue>

The IDictionary<TKey,TValue> interface is the base interface for generic collections of key/value pairs. Each element is a key/value pair stored in a KeyValuePair<TKey,TValue> object.

Methods: ContainsKey, TryGetValue ( Bold represents new methods apart from the parent interface )

ISet<T>

This interface provides methods for implementing sets, which are collections that have unique elements and specific operations. The HashSet<T> and SortedSet<T> collections implement this interface.

Implementations can vary in how they determine equality of objects; for example, the List<T> class uses Comparer<T>.Default, whereas the Dictionary<TKey,TValue> class allows the user to specify the IComparer<T> implementation to use for comparing keys.

IComparer<T> and IEqulityComparer<T>

This interface is used with the List<T>.Sort and List<T>.BinarySearch methods. It provides a way to customize the sort order of a collection. Classes that implement this interface include the SortedDictionary<TKey,TValue> and SortedList<TKey,TValue> generic classes.

The default implementation of this interface is the Comparer<T> class. The StringComparer class implements this interface for type String.

This interface supports ordering comparisons. That is, when the Compare method returns 0, it means that two objects sort the same. Implementation of exact equality comparisons is provided by the IEqualityComparer<T> generic interface.

We recommend that you derive from the Comparer<T> class instead of implementing the IComparer<T> interface, because the Comparer<T> class provides an explicit interface implementation of the IComparer.Compare method and the Default property that gets the default comparer for the object.

Comparer is very useful in generic collections, because it’s the core of finding by key, sorting and add value by key.

With these two interface, we can customize the why of sorting data or query data by key.

You can assign a comparer implementing the interface( Icomparer or Iequalitycomparer )in constructors

1//one way of using comparer(Icomparer)
2 static Dictionary<Box, String> boxes;
3
4 static void Main()
5 {
6//Boxes equality by Dimension
7 BoxSameDimensions boxDim = new BoxSameDimensions();
8 boxes = new Dictionary<Box, string>(boxDim);
9 Box redBox = new Box(8, 4, 8);
10 Box greenBox = new Box(8, 6, 8);
11 Box blueBox = new Box(8, 4, 8);
12 Box yellowBox = new Box(8, 8, 8);
13 AddBox(redBox, "red");
14 AddBox(greenBox, "green");
15 AddBox(blueBox, "blue");
16 AddBox(yellowBox, "yellow");
17
18//Boxes equality by volume
19 BoxSameVolume boxVolume = new BoxSameVolume();
20 boxes = new Dictionary<Box, string>(boxVolume);
21 Box pinkBox = new Box(8, 4, 8);
22 Box orangeBox = new Box(8, 6, 8);
23 Box purpleBox = new Box(4, 8, 8);
24 Box brownBox = new Box(8, 8, 4);
25 AddBox(pinkBox, "pink");
26 AddBox(orangeBox, "orange");
27 AddBox(purpleBox, "purple");
28 AddBox(brownBox, "brown");
29 }
30
31public class Box
32{
33 public Box(int h, int l, int w)
34 {
35 this.Height = h;
36 this.Length = l;
37 this.Width = w;
38 }
39 public int Height { get; set; }
40 public int Length { get; set; }
41 public int Width { get; set; }
42}
43
44class BoxSameDimensions : EqualityComparer<Box>
45{
46 public override bool Equals(Box b1, Box b2)
47 {
48 if (b1 == null && b2 == null)
49 return true;
50 else if (b1 == null || b2 == null)
51 return false;
52
53 return (b1.Height == b2.Height &&
54 b1.Length == b2.Length &&
55 b1.Width == b2.Width);
56 }
57
58 public override int GetHashCode(Box bx)
59 {
60 int hCode = bx.Height ^ bx.Length ^ bx.Width;
61 return hCode.GetHashCode();
62 }
63}
64
65class BoxSameVolume : EqualityComparer<Box>
66{
67 public override bool Equals(Box b1, Box b2)
68 {
69 if (b1 == null && b2 == null)
70 return true;
71 else if (b1 == null || b2 == null)
72 return false;
73
74 return (b1.Height * b1.Width * b1.Length ==
75 b2.Height * b2.Width * b2.Length);
76 }
77
78 public override int GetHashCode(Box bx)
79 {
80 int hCode = bx.Height * bx.Length * bx.Width;
81 return hCode.GetHashCode();
82 }
83}

The item class can also derive from comparer (Equalitycomparer)

1Boxes.Sort(new BoxLengthFirst());
2
3public class BoxLengthFirst : Comparer<Box>
4{
5 // Compares by Length, Height, and Width.
6 public override int Compare(Box x, Box y)
7 {
8 if (x.Length.CompareTo(y.Length) != 0)
9 {
10 return x.Length.CompareTo(y.Length);
11 }
12 else if (x.Height.CompareTo(y.Height) != 0)
13 {
14 return x.Height.CompareTo(y.Height);
15 }
16 else if (x.Width.CompareTo(y.Width) != 0)
17 {
18 return x.Width.CompareTo(y.Width);
19 }
20 else
21 {
22 return 0;
23 }
24 }
25}
26
27/***********************or***********************/
28
29Boxes.Sort();
30public class Box: Comparer<Box>
31{
32 // Compares by Length, Height, and Width.
33 public override int Compare(Box x, Box y)
34 {
35 if (x.Length.CompareTo(y.Length) != 0)
36 {
37 return x.Length.CompareTo(y.Length);
38 }
39 else if (x.Height.CompareTo(y.Height) != 0)
40 {
41 return x.Height.CompareTo(y.Height);
42 }
43 else if (x.Width.CompareTo(y.Width) != 0)
44 {
45 return x.Width.CompareTo(y.Width);
46 }
47 else
48 {
49 return 0;
50 }
51 }
52}

Collections in C# (The basics 1)

Collections in C# (The basics 2)

Collections in C# (The basics 3)

Reference

从零开始分析C#所有常用集合类的设计(源码向)

© 2023 by BigBro222's Blog. All rights reserved.