2015-01-13 2 views
0

Вот мой кодДобавить метод расширения в список

class Student 
{ 
    some code 
} 

static class Filter 
{ 
    static void TypeFilter(this List<Student> result, string type) 
    { 
     result = result.FindAll(x=>x.type == type); 
    } 
} 

, когда я использую этот метод расширения, как

List<Student> a = some code; 
    a.TypeFilter("someType"); 

Список не фильтруется, список должен быть ссылочного типа, то почему a не изменился, я сделал что-то неправильно?

+2

Вы должны передать его.Он не изменяет исходную коллекцию, а создает новый. –

+0

@JeroenVannevel Я думаю, вы имеете в виду «Вы переназначили это», а не «Вы должны переназначить его». Переназначение внутри 'TypeFilter' является именно тем, что вызывает проблему здесь. – hvd

+0

@ hvd: правый, это тоже. Я имел в виду код вызова, где был применен только «a.TypeFilter()», но не переназначен на 'a'. –

ответ

2

Вы можете использовать RemoveAll:

static void TypeFilter(this List<Student> result, string type) 
{ 
    result.RemoveAll(x=>x.type != type); 
} 
+0

спасибо, это умно! – pita

2

Вы не можете назначить его таким образом, попробуйте следующее:

static List<Student> TypeFilter(this List<Student> result, string type) 
    { 
     return result.FindAll(x=>x.type == type); 
    } 

Используйте это так:

List<Student> a = some code; 
List<Student> filteredStudentList = a.TypeFilter("someType"); 
0

А ссылочный тип, но новый список был создан при вызове FindAll. FindAll - это функция, которая возвращает новый список. Это эквивалентно методу foolow:

List<Student> FindAll (List<Student> students, string filter){ 
    List<Student> newList = new List<Student>(); 

    foreach(var student in students){ 
     if(filter == student.type) 
      newList.Add(student); 
    } 
    return newList; 
} 

Если вы хотите использовать возвращаемое значение, то вам нужно, чтобы захватить ссылку на возвращаемое значение, создав переменную:

вар filteredStudents = students.TypeFilter ("someFilter");

0

Вы не можете назначить this указателя в опорном методе, и любой метод, принимающий параметр не может присвоить ему без его параметр ref, таким образом List производства кода не могут быть назначены result так, как вы - описал он.

Поскольку это List, вы можете перебирать и удалять элементы вместо замены указателя.

static void TypeFilter(this List<Student> result, string type) 
{ 
    foreach(var s in result 
     .Except(result.FindAll(x => x.type == type)) 
     .ToArray()) // VERY Important - modifying a list while iterating through it will throw an exception! 
    { result.remove(s); } 
} 
4

Вот почему ты, снова не видя результаты:

static void TypeFilter(this List<Student> result, string type) 
{ 
    result = result.FindAll(x=>x.type == type); 
} 

List<Student> a = some code; 
a.TypeFilter("someType"); 

Параметры по DEFUALT передаются по значению. result теперь является локальной переменной, которая ссылается на список. Когда вы звоните FindAll - вы возвращаетесь обратно ссылка - первоначальный список, который resulta) ссылка не изменилась.

При переназначении результата bask на result, result теперь ссылается на новый объект, а ссылка на a не работает. a не изменяется во всем этом.

Большинство методов Linq возвращают новый объект вместо изменения переданного объекта. Если вы следовали этому шаблону ваш метод будет

static List<Student> TypeFilter(this List<Student> result, string type) 
{ 
    return result.FindAll(x=>x.type == type); 
} 

и использование будет:

List<Student> a = some code; 
a = a.TypeFilter("someType"); 
Смежные вопросы