var lstStr = new List<string> { "a", "b" };
foreach (var str in lstStr)
{
Console.WriteLine(str);
}
//这是foreach的使用
//实际上内部是这样的
var lstStr = new List<string> {"a", "b"};
IEnumerator<string> enumeratorLst = lstStr.GetEnumerator();
while (enumeratorLst.MoveNext())
{
Console.WriteLine(enumeratorLst.Current);
}
原本的话我们是需要先用一个实现IEnumerator 然后一个类实现IEnumerable(里面有GetEnumerator方法) 这样就可以对实现了IEnumerable的类使用foreach。 现在有一个很简单的方法,不需要一个类实现IEnumerator,直接使用一个实现了IEnumerable的类来使用foreach。要用到yield return。因为yield return 会自动将返回值当做Enumerator来处理,所有它直接返回了一个经过处理得IEnumerator。
好下面上我的代码
using System.Collections;
using System.Collections.Generic;
/// <summary>
/// 双列表。即有两个一对一关系的列表需要维护时使用此类。
/// </summary>
/// <typeparam name="A"></typeparam>
/// <typeparam name="B"></typeparam>
public class DoubleList<A, B>:IEnumerable<KeyValuePair<A,B>> {
List<A> listA;
List<B> listB;
/// <summary>
/// 包含的对称双列表中,一条列表所含有的元素个数
/// </summary>
int Count
{
get { return listA.Count; }
}
int Capacity
{
get { return listA.Capacity; }
}
#region 构造函数
/// <summary>
/// 空参数的构造函数
/// </summary>
public DoubleList()
{
listA = new List<A>();
listB = new List<B>();
}
/// <summary>
/// 带有初始值的构造函数
/// </summary>
/// <param name="a"></param>
/// <param name="b"></param>
public DoubleList(A a,B b)
{
listA = new List<A>();
listB = new List<B>();
listA.Add(a);
listB.Add(b);
}
public DoubleList(List<A> a , List<B> B)
{
if(a.Count == B.Count)
{
listA = a;
listB = B;
}
else
{
listA = new List<A>();
listB = new List<B>();
}
}
#endregion
#region 迭代器
public KeyValuePair<A,B> this[int i]
{
get {
KeyValuePair<A, B> kv = new KeyValuePair<A, B>(listA[i],listB[i]);
return kv;
}
}
#endregion
public void Add(A a , B b)
{
listA.Add(a);
listB.Add(b);
}
/// <summary>
/// 传进来两个列表,加到本双列表中。%%注意两个列表的长度要相等。
/// </summary>
/// <param name="listOfA"></param>
/// <param name="listOfB"></param>
public void AddRange(List<A> listOfA, List<B> listOfB)
{
//如果传进来的两个数组的长度不对称,那么这次操作无效。
if (listOfA.Count != listOfB.Count) return;
//传进来的两个数组长度对称,那么这次操作有效。
foreach (var ss in listOfA)
{
listA.Add(ss);
}
foreach (var ss in listOfB)
{
listB.Add(ss);
}
}
public void Remove(A a, B b)
{
listA.Remove(a);
listB.Remove(b);
}
public void RemoveRange(List<A> listOfA,List<B> listOfB)
{
//如果传进来的两个数组的长度不对称,那么这次操作无效。
if (listOfA.Count != listOfB.Count) return;
//传进来的两个数组长度对称,那么这次操作有效。
foreach (var ss in listOfA)
{
listA.Remove(ss);
}
foreach (var ss in listOfB)
{
listB.Remove(ss);
}
}
public void RemoveAt(int index)
{
listA.RemoveAt(index);
listB.RemoveAt(index);
}
public bool ContainsFirst(A a)
{
return listA.Contains(a);
}
public bool ContainsSecond(B b)
{
return listB.Contains(b);
}
public void Clear()
{
listA.Clear();
listB.Clear();
}
public IEnumerator<KeyValuePair<A, B>> GetEnumerator()
{
for (int i = 0; i < listA.Count; i++)
{
yield return new KeyValuePair<A, B>(listA[i], listB[i]);
}
}
IEnumerator IEnumerable.GetEnumerator()
{
for (int i = 0; i < listA.Count; i++)
{
yield return new KeyValuePair<A, B>(listA[i], listB[i]);
}
}
}
注意,这里我使用了泛型接口IEnumerable<KeyValuePair<A,B>> ,这个就是影响你GetEnumerator() 的返回。
形象点说哈
1、如果我使用了非泛型的接口IEnumerable 然后正常实现了GetEnumerator()
现在我对这个类的对象使用foreach你会看到
这里会自动将其当做默认的object类型来处理,而后面我需要强转,看到没有,这样很麻烦。
2、但是我使用了泛型的接口IEnumerable<KeyValuePair<A,B>>
接下来神奇的事情发生了 当当当当~~
扫描二维码关注公众号,回复:
5069236 查看本文章
%%:哈哈 它说强转是多余的,我可以直接将item当做我设置的keyvaluepair类型来使用。
好了,结束。