简体   繁体   中英

Add extension method to List

Here is my code

class Student
{
    some code 
}

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

when I use this extension method like

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

List a was not filtered, List should be a reference type, then why a didn't change, did I do anything wrong ?

Here's why you;re not seeing the results:

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

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

Parameters by defualt are passed by value. result is now a local variable that references a list. When you call FindAll - you get back a new reference - the original list that result (and a ) reference is unchanged.

When you reassign the result bask to result , result now references the new object, and the link back to a is broken. a is unchanged through all of this.

Most Linq methods return a new object instead of modifying the passed in object. If you followed that pattern your method would be

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

and the usage would be:

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

You could use RemoveAll :

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

You cant assign it this way try this:

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

Use it like this:

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

A is a reference type but a new List was created when FindAll was called. FindAll is a function that returns a new List. It is equivalent to the foolow method:

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;
}

If you want to use the return value then you need to capture a reference to the return value by creating a variable:

var filteredStudents = students.TypeFilter("someFilter");

You cannot assign to the this pointer in a reference method, and any method taking a parameter cannot assign to it without making it a ref parameter, thus the List produced by your code can't be assigned to result the way you've described.

Since it is a List , you could iterate through and remove items instead of replacing the pointer.

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); }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM