鉴于以下课程:
public class GenClass<T>
{
private List<T> ItemsList {get;set;}
public Predicate<T> SomeCondition {get;set;}
public bool UsePredicate {get;set;}
public List<T> Items
{
get { //CODE Goes here; }
}
}
我需要一种方法让列表使用SomeConditionPredicate
并仅返回与条件匹配的项目,但仅当bool UsePredicate
为真时才返回。我知道我可以只使用LINQ,问题是每次我用LINQ查询时我得到一个IEnumerable的不同实例,这需要是一个属性,因此我需要能够访问List的同一个实例来自课外,因为我将添加和删除它的项目,我不能用。的结果,例如。
我在考虑一个自定义IList<T>
,但我不确定该怎么做。
答案 0 :(得分:2)
这里有一个概念性问题。如果它是同一个实例,它应该如何按条件过滤? LINQ在每次调用时返回新枚举的原因是它运行查询“实时”,并且多个查询必须是独立的。
那就是说,你可能不应该依赖每次返回相同引用的属性。如果您依赖实例是相同的,当/如果有人更改谓词时,您期望发生什么?
如何添加或删除应该在已过滤列表上工作/操作的项目?如果你添加一个可以过滤的项目,会发生什么?
答案 1 :(得分:0)
你的问题有点不清楚,但让我们从这开始:
public class GenClass<T>
{
private List<T> ItemsList {get;set;}
public Predicate<T> SomeCondition {get;set;}
public bool UsePredicate {get;set;}
public List<T> Items
{
get { return UsePredicate
? ItemsList.Where(SomeCondition).ToList()
: ItemsList; }
}
}
那对你的用例怎么样?
答案 2 :(得分:0)
IEnumerable
只能用于读取集合,但不能用于更改集合。如果要对其进行更改,请返回已过滤索引的枚举。
public IEnumerable<int> FilteredIndexes
{
get
{
if (UsePredicate) {
return ItemsList
.Select((item, i) => i)
.Where(i => SomeCondition(ItemsList[i]));
}
return ItemsList.Select((item, i) => i);
}
}
假设您已声明此索引器
public T this[int index]
{
get { return ItemsList[index]; }
set { ItemsList[index] = value; }
}
您现在可以使用这样的集合
GenClass<string> stringCollection = new GenClass<string>();
//TODO: Add items
stringCollection.SomeCondition = s => s.StartsWith("A");
stringCollection.UsePredicate = true;
foreach (int index in stringCollection.FilteredIndexes) {
stringCollection[index] = stringCollection[index] + " starts with 'A'";
}
如果您不想公开索引,可以创建一个用作项目访问者的类来表示您的集合项
public class Item<T>
{
private List<T> _items;
private int _index;
public Item(List<T> items, int index)
{
_items = items;
_index = index;
}
public T Value
{
get { return _items[_index]; }
set { _items[_index] = value; }
}
}
在您的收藏中,您将声明此属性
public IEnumerable<Item<T>> FilteredItems
{
get
{
if (UsePredicate) {
return ItemsList
.Select((item, i) => new Item<T>(ItemsList, i))
.Where(item => SomeCondition(item.Value));
}
return ItemsList.Select((item, i) => new Item<T>(ItemsList, i));
}
}
现在你可以像这样使用
了foreach (Item<string> item in stringCollection.FilteredItems) {
item.Value = item.Value + " starts with 'A'";
}
一般说明:您可以安全地将私有属性转换为字段。属性通常用作公开公开字段值的中间体。