第二十二章 数据访问(In .net4.5) 之 集合

1. 概述

  本章内容包括 .net平台中的集合、如何选择集合 以及 如何实现自定义集合。

2. 主要内容

  2.1 使用数组(Array)

int[] arrayOfInt = new int[10]; 
 
for (int x = 0; x < arrayOfInt.Length; x++) 
{ 
    arrayOfInt[x] = x; 
} 
 
foreach (int i in arrayOfInt) //实现了IEnumerable
{ 
    Console.Write(i); // Displays 0123456789 
}

    .net中还支持多维数组和锯齿(jagged)数组

string[,] array2D = new string[32] { { “one”, “two” }, { “three”, “four” }, 
                        { “five”, “six” } }; 
 
int[][] jaggedArray =  
   { 
        new int[] {1,3,5,7,9}, 
        new int[] {0,2,4,6}, 
        new int[] {42,21} 
    };

  2.2 理解泛型和非泛型版本

    *使用值类型作为泛型参数的时候,要注意可能会发生的装箱情况。比如值类型未实现IEquatable<T>或IComparable<T>的时候。

  2.3 使用列表(List)

    List<T>的定义:

public class List<T> : IList<T>, ICollection<T>, IList, ICollection,  
       IReadOnlyList<T>, IReadOnlyCollection<T>, IEnumerable<T>, IEnumerable

    其中IList<T> 和 ICollection<T> 的定义如下:

public interface IList<T> : ICollection<T>, IEnumerable<T>, IEnumerable 
{ 
        T this[int index] { getset; } 
        int IndexOf(T item); 
        void Insert(int index, T item);     
        void RemoveAt(int index); 
}
public interface ICollection<T> : IEnumerable<T>, IEnumerable 
{ 
        int Count { get; }     
        bool IsReadOnly { get; } 
        void Add(T item);     
        void Clear();     
        bool Contains(T item);     
        void CopyTo(T[] array, int arrayIndex);     
        bool Remove(T item); 
}

    下面是使用List<T>操作数据项的示例:

List<string> listOfStrings = 
    new List<string> { “A”, “B”, “C”, “D”, “E” }; 
 
for (int x = 0; x < listOfStrings.Count; x++) 
    Console.Write(listOfStrings[x]); // Displays: ABCDE 
 
listOfStrings.Remove(“A”); 
 
Console.WriteLine(listOfStrings[0]); // Displays: B 
 
listOfStrings.Add(“F”); 

Console.WriteLine(listOfStrings.Count); // Displays: 5 
 
bool hasC = listOfStrings.Contains(“C”); 
 
Console.WriteLine(hasC); // Displays: true

  2.4 使用字典(Dictionary)

    字典由键值对组成,可以根据键获取值。不允许重复的键。字典的定义:

public class Dictionary<TKey, TValue> : IDictionary<TKey, TValue>,          
    ICollection<KeyValuePair<TKey, TValue>>, IDictionary, ICollection,     
    IReadOnlyDictionary<TKey, TValue>, IReadOnlyCollection<KeyValuePair<TKey, TValue>>,          
    IEnumerable<KeyValuePair<TKey, TValue>>, IEnumerable, ISerializable, 
    IDeserializationCallback

    字典的使用示例:

Person p1 = new Person { Id = 1, Name = “Name1” }; 
Person p2 new Person { Id = 2, Name = “Name2” }; 
Person p3 new Person { Id = 3, Name = “Name3” }; 
 
var dict = new Dictionary<int, Person>(); 
dict.Add(p1.Id, p1); 
dict.Add(p2.Id, p2); 
dict.Add(p3.Id, p3); 
 
foreach (KeyValuePair<int, Person> v in dict) 
{ 
    Console.WriteLine(“{0}: {1}”, v.Key, v.Value.Name); 
} 
 
dict[0] = new Person { Id = 4, Name = “Name4” }; 
 
Person result; 
if (!dict.TryGetValue(5out result)) 
{ 
    Console.WriteLine(“No person with a key of 5 can be found”); 
}

  2.5 使用集(sets)

    sets是一个非重复的,无序集合。C#中set是系统保留关键字,可以使用HastSet<T>,它实现了ISet<T>。

public interface ISet<T> : ICollection<T>, IEnumerable<T>, IEnumerable 
{ 
        bool Add(T item); 
        void ExceptWith(IEnumerable<T> other); 
        void IntersectWith(IEnumerable<T> other); 
        bool IsProperSubsetOf(IEnumerable<T> other); 
        bool IsProperSupersetOf(IEnumerable<T> other); 
        bool IsSubsetOf(IEnumerable<T> other); 
        bool IsSupersetOf(IEnumerable<T> other); 
        bool Overlaps(IEnumerable<T> other); 
        bool SetEquals(IEnumerable<T> other); 
        void SymmetricExceptWith(IEnumerable<T> other); 
        void UnionWith(IEnumerable<T> other); 
}

    使用HashSet<T>的示例:

public void UseHashSet() 
{ 
    HashSet<int> oddSet = new HashSet<int>(); 
    HashSet<int> evenSet = new HashSet<int>(); 
 
    for (int x = 1; x <= 10; x++) 
    { 
        if (x % 2 == 0) 
            evenSet.Add(x); 
        else 
            oddSet.Add(x); 
    } 
 
    DisplaySet(oddSet); 
    DisplaySet(evenSet); 
 
    oddSet.UnionWith(evenSet); 
    DisplaySet(oddSet); 
} 
 
private void DisplaySet(HashSet<intset) 
{ 
    Console.Write(“{“); 
    foreach (int i in set) 
    { 
        Console.Write(“ {0}”, i); 
    } 
    Console.WriteLine(“ }”); 
}

  2.6 使用队列(queue)和堆栈(stack)

    队列主要用于临时存储数据,遵循先进先出的原则。三个重要的方法是:Enqueue、Dequeue、Peek。

Queue<string> myQueue = new Queue<string>(); 
myQueue.Enqueue(“Hello”); 
myQueue.Enqueue(“World”); 
myQueue.Enqueue(“From”); 
myQueue.Enqueue(“A”); 
myQueue.Enqueue(“Queue”); 
 
foreach (string s in myQueue) 
    Console.Write(s + “ “); 
// Displays: Hello World From A Queue

    堆栈 遵循先进后出的原则。也具有跟队列类似的三个方法:Push、Pop、Peek。

Stack<string> myStack = new Stack<string>(); 
myStack.Push(“Hello”); 
myStack.Push(“World”); 
myStack.Push(“From”); 
myStack.Push(“A”); 
myStack.Push(“Queue”); 
 
foreach (string s in myStack) 
    Console.Write(s + “ “); 
// Displays: Queue A From World Hello

  2.7 选择合适的集合

    各个集合间最大的不同是 元素的访问方式:

    ① 列表和字典都支持元素的随机访问。字典提供了更快的元素读取速度,但是不能存储重复的数据项。

    ② 队列和堆栈提供了特定顺序的元素访问方式。元素取出后就自动从集合删除了。

    ③ 基于Set的集合,在元素比较方面有一些特性。但是不提供元素的随机访问。

  2.8 创建自定义集合

    .net提供的集合相关的接口包括: IEnumerable、IEnumerable<T>、IList<T>、ICollection<T>、IDictionary<TKey,TValue>、

    ICollection<TKey,TValue>、ISet<T>。

    也可以继承现有的集合对象来添加自定义的方法:

public class PeopleCollection : List<Person> 
{ 
    public void RemoveByAge(int age) 
    { 
        for (int index = this.Count - 1; index >= 0; index--) 
        { 
            if (this[index].Age == age) 
            { 
                this.RemoveAt(index); 
            } 
        } 
    } 
 
    public override string ToString() 
    { 
        StringBuilder sb new StringBuilder(); 
        foreach (Person p in this) 
        { 
            sb.AppendFormat(“{0} {1is {2}”, p.FirstName, p.LastName, p.Age); 
        } 
        return sb.ToString(); 
    } 
}

3. 总结

  ① .net提供了泛型和非泛型的集合版本,使用的时候,优先选择泛型版本。

  ② 数组(Array)是最基础的集合,是定长的。

  ③ 列表(List)是使用最多的集合,是变长的。

  ④ 字典(Dictionary)是存取键值对的集合。

  ⑤ HashSet保存唯一项并提供相应的操作。

  ⑥ 队列是先进先出的集合。

  ⑦ 堆栈是先进后出的集合。

  ⑧ 可以通过实现指定的接口或者继承现有的集合来自定义集合类型。

原文地址:https://www.cnblogs.com/stone_lv/p/4444471.html