一、约束
约束类型包括基类约束、构造函数约束、接口约束、参数约束等。如:
public class FateherTest
{
}
//where的用法 接口约束IComparable 和构造函数约束new(), 基类约束 FatherTest
public class TestA<T> where T : FateherTest, IComparable, new()
{
}
public class TestB
{
//限制传递参数的类型必须继承IComparable 参数类型约束
public int Caculate<T>(T t) where T : IComparable
{
throw new NotImplementedException();
}
}
二、集合条件查询
1.使用方法
List<InstanceB> list = new List<InstanceB>();
//返回b.value的值 ==2的 IEnumerable对象
list.Where((b) => b.value == 2).ToList();
Dictionary<int, InstanceB> dic = new Dictionary<int, InstanceB>();
//TSource是 KeyValuePair<TKey, TValue>
dic.Where((b) => b.Value.value== 2);
2.如何实现的
在System.linq命名空间下的Enumerable类里面实现了IEnumerable的扩展方法.如下:
//返回值是IEnumerable<T>迭代器对象
public static IEnumerable<TSource> Where<TSource>(
this IEnumerable<TSource> source,
Func<TSource, bool> predicate)
{
if (source == null)
throw Error.ArgumentNull(nameof (source));
if (predicate == null)
throw Error.ArgumentNull(nameof (predicate));
switch (source)
{
case Enumerable.Iterator<TSource> _:
return ((Enumerable.Iterator<TSource>) source).Where(predicate);
case TSource[] _:
return (IEnumerable<TSource>) new Enumerable.WhereArrayIterator<TSource>((TSource[]) source, predicate);
case List<TSource> _:
return (IEnumerable<TSource>) new Enumerable.WhereListIterator<TSource>((List<TSource>) source, predicate);
default:
return (IEnumerable<TSource>) new Enumerable.WhereEnumerableIterator<TSource>(source, predicate);
}
}
当我们调用List.Where扩展方法时返回了一个WhereListIterator对象:
reurn (IEnumerable<TSource>) new Enumerable.WhereListIterator<TSource>((TSource[]) source, predicate) 返回一个whereListIterator对象。其中 TSource就是InstanceB类型
我们可查看 WhereListIterator 这个类,它继承了:Enumerable.Iterator<TResult>:IEnumerable<TSource> .其本身实现了迭代器的功能,查看MoveNext方法:
public override bool MoveNext()
{
if (this.state == 1)
{
while (this.index < this.source.Length)
{
TSource source = this.source[this.index];
++this.index;
if (this.predicate(source))
{
this.current = source;
return true;
}
}
this.Dispose();
}
return false;
}
只有通过predictate的检测之后MoveNext才会返回true.调用Tolist的时候回调用 IEnumrable的扩展方法Tolist 调用创建一个List<T>对象返回。只不过构造函数是使用集合做的初始化,如下:
[__DynamicallyInvokable]
public List(IEnumerable<T> collection)
{
if (collection == null)
ThrowHelper.ThrowArgumentNullException(ExceptionArgument.collection);
if (collection is ICollection<T> objs)
{
int count = objs.Count;
if (count == 0)
{
this._items = List<T>._emptyArray;
}
else
{
this._items = new T[count];
objs.CopyTo(this._items, 0);
this._size = count;
}
}
else
{
this._size = 0;
this._items = List<T>._emptyArray;
foreach (T obj in collection)
this.Add(obj);
}
}
上面使用foreach会调用WhereListIterator 的MoveNext.直到返回false结束。而上面的MoveNext用来Func委托函数做筛选。
我们还可以做如下操作:
var whereListIt = list.Where((b) => b.value >1)
Func<InstanceB,InstanceB> func = delegate (InstanceB b)
{
b.value = 3;
return b;
};
newList = whereListIt.Select(func).ToList();
筛选出第一次b.value >1的独享 第二次将筛选对象的value都设置为3.
public override bool MoveNext()
{
if (this.state == 1)
{
while (this.index < this.source.Length)
{
TSource source = this.source[this.index];
++this.index;
if (this.predicate == null || this.predicate(source))
{
//这里可以看出Selector是对source进行操作,并不是筛选。
this.current = this.selector(source);
return true;
}
}
this.Dispose();
}
return false;
}
几个类结构如下:
- WhereListIterator:Enumerable.Iterator<TResult>:IEnumerable<TSource>
- WhereListIterator:Enumerable.Iterator<TResult>:IEnumerable<TSource>
所以有连续的操作如:
list.Where((b) => b.value == 2).where((b) => b.value == 2)
Func<InstanceB,InstanceB> func = delegate (InstanceB b)
{
b.value = 3;
return b;
};
list.Select(t).Select(t)
也可以有组合的操作
list.Where((b) => b.value == 2).Select(t)
原因是连续操作内部做了 Combine操作:下面是Selector调用Selector即:Selector.Selector
public override IEnumerable<TResult2> Select<TResult2>(
Func<TResult, TResult2> selector) {
return (IEnumerable<TResult2>) new Enumerable.SelectEnumerableIterator<TSource, TResult2>(this._source, Enumerable.CombineSelectors<TSource, TResult, TResult2>(this._selector, selector));
}
组合操作做了组合:下面是Selector.Where的组合操作
public override IEnumerable<TResult> Where(Func<TResult, bool> predicate) => (IEnumerable<TResult>) new Enumerable.WhereEnumerableIterator<TResult>((IEnumerable<TResult>) this, predicate);
/组合操作时会把This当前对象传递到下个对象WhereEnumerableIterator。而WhereEnumerableIterator在MoveNext中的操作如下:
- 取了上个对象的迭代器,先做处理。
- 调用了上个对象的MoveNext对Selector的Func进行了调用,之后再调用this.predicate做筛选。
3.从设计模式的角度
对于List、Dictionary和Array
- 使用扩展方法扩展扩展IEnumrable的功能,而不修改IEnurable接口内容。
- 实现新的类对象,持有IEnumrable对象做迭代处理,使用的是组合的方式而不是继承的方式。
- 新创建的对象分别代表不同的操作,继承同一个父类,因此不同对象之间使用组合模式可以相互组合,实现复杂的操作。
现在又要给这些数据集合添加功能是筛选.实现方法有以下两种:
1.新写一个接口让这些集合实现,利用迭代的功能实现筛选。坏处是某个对象都需要实现这个方法。破坏了原有类的结构。
2.由于筛选功能只是用到了迭代器,因此可以:
- 使用扩展方法扩展扩展IEnumrable的功能,而不修改IEnurable接口内容。
- 实现新的类对象,持有IEnumrable对象做迭代处理,使用的是组合的方式而不是继承的方式。
- 新创建的对象分别代表不同的操作,继承同一个父类,因此不同对象之间使用组合模式可以相互组合,实现复杂的操作。