, IEnumerable <T> . , , .., , . , , IEnumerable <T> .
, .
, , :
static class Enumerable {
public static IEnumerable<T> MoveDown<T>(this IEnumerable<T> source, int index) {
if (source == null) {
throw new ArgumentNullException("source");
}
T[] array = source.ToArray();
if (index == array.Length - 1) {
return source;
}
return Swap<T>(array, index, index + 1);
}
public static IEnumerable<T> MoveDown<T>(this IEnumerable<T> source, T item) {
if (source == null) {
throw new ArgumentNullException("source");
}
T[] array = source.ToArray();
int index = Array.FindIndex(array, i => i.Equals(item));
if (index == -1) {
throw new InvalidOperationException();
}
if (index == array.Length - 1) {
return source;
}
return Swap<T>(array, index, index + 1);
}
public static IEnumerable<T> MoveUp<T>(this IEnumerable<T> source, int index) {
if (source == null) {
throw new ArgumentNullException("source");
}
T[] array = source.ToArray();
if (index == 0) {
return source;
}
return Swap<T>(array, index - 1, index);
}
public static IEnumerable<T> MoveUp<T>(this IEnumerable<T> source, T item) {
if (source == null) {
throw new ArgumentNullException("source");
}
T[] array = source.ToArray();
int index = Array.FindIndex(array, i => i.Equals(item));
if (index == -1) {
throw new InvalidOperationException();
}
if (index == 0) {
return source;
}
return Swap<T>(array, index - 1, index);
}
public static IEnumerable<T> Swap<T>(this IEnumerable<T> source, int firstIndex, int secondIndex) {
if (source == null) {
throw new ArgumentNullException("source");
}
T[] array = source.ToArray();
return Swap<T>(array, firstIndex, secondIndex);
}
private static IEnumerable<T> Swap<T>(T[] array, int firstIndex, int secondIndex) {
if (firstIndex < 0 || firstIndex >= array.Length) {
throw new ArgumentOutOfRangeException("firstIndex");
}
if (secondIndex < 0 || secondIndex >= array.Length) {
throw new ArgumentOutOfRangeException("secondIndex");
}
T tmp = array[firstIndex];
array[firstIndex] = array[secondIndex];
array[secondIndex] = tmp;
return array;
}
public static IEnumerable<T> Swap<T>(this IEnumerable<T> source, T firstItem, T secondItem) {
if (source == null) {
throw new ArgumentNullException("source");
}
T[] array = source.ToArray();
int firstIndex = Array.FindIndex(array, i => i.Equals(firstItem));
int secondIndex = Array.FindIndex(array, i => i.Equals(secondItem));
return Swap(array, firstIndex, secondIndex);
}
}
As you can see, MoveUp and MoveDown are basically Swap operations. With MoveUp, you change positions with the previous element, and with MoveDown you change positions with the next element. Of course, this does not apply to moving the first element or moving through the last element.
Performing a quick test using the code below ...
class Program {
static void Main(string[] args) {
int[] a = { 0, 2, 1, 3, 4 };
string[] z = { "Zero", "Two", "One", "Three", "Four" };
IEnumerable<int> b = Enumerable.Swap(a, 1, 2);
WriteAll(b);
IEnumerable<int> c = Enumerable.MoveDown(a, 1);
WriteAll(c);
IEnumerable<int> d = Enumerable.MoveUp(a, 2);
WriteAll(d);
IEnumerable<int> f = Enumerable.MoveUp(a, 0);
WriteAll(f);
IEnumerable<int> g = Enumerable.MoveDown(a, 4);
WriteAll(g);
IEnumerable<string> h = Enumerable.Swap(z, "Two", "One");
WriteAll(h);
var i = z.MoveDown("Two");
WriteAll(i);
var j = z.MoveUp("One");
WriteAll(j);
Console.WriteLine("Press any key to continue...");
Console.Read();
}
private static void WriteAll<T>(IEnumerable<T> b) {
foreach (var item in b) {
Console.WriteLine(item);
}
}
... everything seems to be working fine.
I hope this at least serves as a starting point for you.