Передача объекта в метод, а затем вызов метода расширения для этого объекта - PullRequest
0 голосов
/ 02 декабря 2010

Вчера я работал над методом и столкнулся с чем-то странным, вот глупая версия кода: в основном проблема в том, что OrderBy, примененный в методе Bar.PopulateList, не сохраняется.


class Foo
{
    List MyObjects;

    public void PopulateMyObjects()
    {
        //Items are added to my list but the OrderBy is not persisting.
        Bar.PopulateList(MyObjects);
    }
}

class Bar
{
   public static int PopulateList(List theList)
   {
       foreach(var in WebSerbiceCall)
       {
            theList.Add(var);
       }
       // the OrderBy call only sorts 'theList' in the context of this method.
       // When I return from this method theList has been populated but the Ordering has 
       // reverted back to the order that the items were added to the list.
       theList.OrderBy(obj => obj.ID);
       return theList.Count;
   }
}

Теперь, если я обновлю код и добавлю ключевое слово ref, как указано ниже, все будет работать: например public static int PopulateList (ref List theList) и Bar.PopulateList (ref MyObjects);

Может ли кто-нибудь просветить меня? Я думал, что объекты всегда передавались по ссылке? Это тот факт, что OrderBy является методом расширения?

Спасибо, Цянь

Ответы [ 5 ]

4 голосов
/ 02 декабря 2010

Проблема здесь в том, что вызов OrderBy на самом деле не изменяет theList.Вместо этого он возвращает новый IEnumerable<object>, который заказан.Следовательно, именно поэтому вы не видите влияния вызова вне метода, он просто не меняет объект.

Использование метода OrderBy создает новое значение и, следовательно, если вы хотите, чтобы вызывающая функция знала об этом новом значении, оно должно быть возвращено некоторым способом.Наиболее распространенные места находятся в возвращаемом значении или в параметре ref / out.

public static int PopulateList(ref List<object> theList) {
  ...
  theList = theList.OrderBy(obj => obj.ID).ToList();
}
1 голос
/ 02 декабря 2010

Метод расширения Enumerable.OrderBy не сортирует список на месте.Он возвращает IEnumerable , который возвращает элементы списка в отсортированном порядке.

Используйте метод List .Sort для сортировки Список на месте.

1 голос
/ 02 декабря 2010

C # передает аргументы по значению, просто значение ссылочного типа является указателем на его область памяти. Проблема, с которой вы столкнулись, заключается в следующем:

theList.OrderBy(obj => obj.ID);

Вы не назначаете результат:

theList = thisList.OrderBy(obj => obj.ID).ToList();
1 голос
/ 02 декабря 2010

Попробуйте:

return theList.OrderBy(obj => obj.ID).Count;

(я собирался добавить объяснение, но @jaredPar объяснил это)

0 голосов
/ 02 декабря 2010

Если вы не используете ключевое слово ref, то передаваемый параметр является новой ссылкой на тот же объект. В некотором смысле он «передается по ссылке», но вы должны думать об этом немного по-другому.

Другие ответы верны, OrderBy не работает на месте и вместо этого возвращает упорядоченную коллекцию. Но если вы установите свой параметр на результат, то вы измените значение параметра (ссылку), чтобы оно указывало на новую коллекцию, а не изменило сам базовый объект.

Например,

theList = thisList.OrderBy(obj => obj.ID).ToList();

принимает theList, заказывает его, а затем создает новый список. Затем значение theList, которое является ссылкой на список, изменяется, чтобы указывать на вновь созданный (упорядоченный) список. Исходная ссылка, созданная вне этого метода, по-прежнему указывает на исходный неупорядоченный список.

Причина в том, что всякий раз, когда вы звоните .ToList(), вы фактически создаете новый список. Когда вы используете ключевое слово ref, вы передаете фактическую переменную, содержащую ссылку, в список, а не создаете новую ссылку на этот же список.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...