Не можете сделать так, как вы изначально написали, вы берете ссылочную переменную (source
) и заставляете ее ссылаться на новый экземпляр. Это изменяет локальную ссылку source
, а не исходный аргумент, переданный.
Имейте в виду, что для ссылочных типов в C # схема передачи параметров по умолчанию передается по значению (где передаваемое значение является ссылкой).
Допустим, вы передаете переменную x
этому методу, который ссылается на исходный список и этот список находится в теоретическом местоположении 1000, это означает, что источник является новой ссылкой на исходный список, проживающий в местоположении 1000.
Теперь, когда вы говорите:
source = source.Where(....);
Вы назначаете source
новому списку (скажем, в местоположении 2000), но это влияет только на то, на что указывает source
, а не на x
, который вы передали.
Чтобы исправить это как метод расширения, вы действительно хотите вместо этого return
новую последовательность:
public static IEnumerable<T> Remove<T>(this IEnumerable<T> source, Func<T, bool> predicate)
{
if (source == null) throw new ArgumentNullException("source");
if (predicate == null) throw new ArgumentNullException("predicate");
// you can also collapse your logic to returning the opposite result of your predicate
return source.Where(x => !predicate(x));
}
Все это предполагает, что вы хотите, чтобы оно было полностью общим для IEnumerable<T>
, как вы задали в своем вопросе. Очевидно, как и в других примерах, если вам небезразлично List<T>
, существует запеченный RemoveAll()
метод.