Я перечитал ваш вопрос, особенно последнюю часть, где вы сказали, что у вас уже есть .Ancestors
, и теперь это имеет больше смысла.
Сделайте это, чтобы получить список элементов для удаления:
List<MyClass> itemsToDelete = myItems
.Where(i => i.Id == myItemId)
.SelectMany(i => i.Ancestors)
.Concat(myItems) // Want to delete these too, not just the ancestors
.ToList()
;
Затем вы можете foreach
просмотреть результаты и удалить их из исходного списка.
Я бы предложил оставить их в Dictionary<int, MyClass>
или HashSet<MyClass>
.списка, поскольку удаление будет в порядке быстрее.
Для HashSet
вам придется реализовать Equals
и GetHashCode
или создать реализацию IEqualityComparer<MyClass>
чтобы предоставить эти методы.
Перед редактированием:
Я бы не написал свой код таким образом.Я бы просто создал Dictionary<int, MyClass>
вместо списка.Он будет выполнять поиск намного быстрее, чем все, что связано с обходом предков / деревьев.
Но вот как выполнить то, что вы пытаетесь выполнить:
Если вы используете Linq to Objects (в отличие от Linq для SQL или Linq для сущностей), создайте свойство с именем Parent
для MyClass
правильного типа, вместо того, чтобы пытаться связать их с помощью Id
.
Затем вы можете сделатьсвойство Ancestors
довольно легко:
public IEnumerable<MyClass> Ancestors
{
get
{
MyClass current = this;
while(current != null)
{
current = current.Parent;
yield return current;
}
}
}
Если вы не можете редактировать класс, создайте метод расширения с именем GetAncestors
.
Тогда вы можете использовать что-то очень похожее накод, который вы написали в своем вопросе:
List<MyClass> itemsToDelete = myItems
.Where(i => i.Ancestors.Any(a => a.Id == myItemId))
.ToList();
Linq to Entities
Если вы используете Linq to Entities, создайте свойство навигации типа MyClass
дляперейдите к родителю и сделайте то же самое.Обратите внимание, что это может вызвать повторные запросы.Не уверен, что Linq может или будет переведен в иерархический запрос.