2012-05-04 2 views
0

1.First я определил метод расширения для IEnumerable.Add() как код нижеПосле повышения IEnumerable.OrderBy() исходный список не был отсортирован, почему?

public static IEnumerable<T> Add<T, TKey>(this IEnumerable<T> enumerable, T value, Func<T, TKey> orderBy) 
    { 
     if (enumerable == null) 
      return null; 

     if (enumerable is IList<T>) 
     { 
      var list = enumerable as IList<T>; 
      if (!enumerable.Contains(value)) 
      { 
       list.Add(value); 
       enumerable = enumerable.OrderBy(orderBy); 
      } 
     } 
    } 

2.Then, я поднял метод расширения, как это для сортировки ITEMLIST согласно свойству «Дата» когда новый пункт был добавлен в список:

itemList.Add(item, o => o.Date); 

3.После все, оказывается, что «ITEMLIST» не был отсортирован.

4.I следовал за методом расширения и обнаружил, что «enumerable» был новым экземпляром после «enumerable = enumerable.OrderBy (orderBy)», и он был отсортирован, но «список» не был.

5. Затем я попытался перечислить отсортированные перечислимые как «list = enumerable.ToList()», оба из них («перечисляемые» и «список») были отсортированы.

6. После этого, когда стек вызовов вернулся к «itemList.Add (item, o => o.Date);», «itemList» не был отсортирован вообще !!!

Любой может дать мне несколько советов? Спасибо loooooooooooooooooooooooooooooooooot !!

ответ

2

Я считаю, что ваша проблема в том, что ссылка на перечислимую передается по значению, а не по ссылке. См. Jon Skeet's article о передаче параметров по значению или ссылке для получения дополнительной информации о том, что это означает. Короче говоря, C# передает копию ссылки параметра, поэтому присвоение нового значения параметру не изменяет ссылку на объект, который был передан. Чтобы передать параметр по ссылке, вы указываете ключевое слово ref, но я не думаю, что будет работать с методом расширения. Если вы настроены на выполнение этой работы, я бы предложил вставить элементы в свой список в отсортированном порядке, возможно, потребовав, чтобы T реализовал IComparable.

Update:

Во-первых, см статью в Скита это действительно очень информативен, и я, вероятно, будет только наполовину ясно, как он есть. Во-вторых, когда вы передаете объект в качестве параметра методу, вы передаете копию копии ссылки. Это означает, что вы все равно можете обращаться к членам объекта, но так же, как тип значения передается копией, если вы изменяете ссылку (то есть присваиваете ей новое значение), вы не будете изменять исходную ссылку. Указание ref означает, что вы передаете ссылку на ссылку и изменяете ссылку (присваивая ей значение), будет влиять на исходный объект.

+0

Спасибо за ваше время! Вы имеете в виду, что «перечислимый» был передан как «значение», а не «Ref»? Но мне учили, что все типы классов являются типами «Ref» ... Не могли бы вы дать мне дополнительную информацию? 't open ... – Claw

+0

Полная ссылка: http://www.yoda.arachsys.com/csharp/parameters.html –

+0

Спасибо большое! Теперь я понял. Метод (T t) и метод (ref T t) различны. В первом случае мы можем изменить t.Property, но не t, когда я создаю новый экземпляр в t, исходный источник не изменится.В другом случае все изменения, включая свойство или новый экземпляр, будут влиять на исходный источник. Спасибо снова! Это действительно полезно! – Claw

1

Ни OrderBy, ни ToList не повлияют на список источников. Когда вы это сделали: list=enumerable.ToList(), вы изменили свою переменную, чтобы указать на весь новый экземпляр списка.

Мне кажется, что этот метод делает слишком много. Я бы продолжал добавлять и сортировать как отдельные операции. Тот факт, что это расширяет IEnumerable, но молча делает ничего, если цель не является IList, является запахом кода.

+0

Большое спасибо! Метод расширения был определен для сортировки при добавлении нового элемента, но, похоже, он не работает хорошо ... – Claw

Смежные вопросы