首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何在IList上使用Reverse(数组,Int32,Int32)或List<T>::Reverse方法(Int32,Int32)?

如何在IList上使用Reverse(数组,Int32,Int32)或List<T>::Reverse方法(Int32,Int32)?
EN

Stack Overflow用户
提问于 2012-07-02 21:57:44
回答 5查看 340关注 0票数 2

我的程序大量使用Reverse,例如Array.Reverse(myArray,3,5)

我希望我的程序可以接受arrayList作为输入,所以我选择IList

但是,我找不到与Reverse相同的IList方法。

有一个名为Reverse的扩展方法,但是它会生成IEnumerable流,但不会就地重新排列。(我认为这需要更多的复制时间)

我想过使用cast,但又担心cast的效率会很低。

那么,我该怎么做呢?

最坏的情况是,我做了2个程序,一个取数组,另一个取列表,然后重载?

EN

回答 5

Stack Overflow用户

回答已采纳

发布于 2012-07-02 23:11:50

OOP-way -制作一个包装器,重载它十几次:

代码语言:javascript
复制
public void Reverse(Array arr, int index, int count)
{
    Array.Reverse(arr, index, count);
}
public void Reverse<T>(List<T> lst, int index, int count)
{
    lst.Reverse(index, count);
}

每次需要以这种方式反转另一个类似集合的类时,都要添加一个重载。这种方法依赖于系统内部,非常有效和健壮,但如果您愿意反转许多类型的对象,则可能会很冗长。

I-can-do-it-myself better-way:

代码语言:javascript
复制
static class Extensions
{
    public static void Reverse(this IList target, int index, int count)
    {
        int right = index + count - 1;
        int left = index;
        while (right>left)
        {
            var tmp = target[left];
            target[left] = target[right];
            target[right] = tmp;
            right--;
            left++;
        }
    }
}

只需添加范围检查/前置条件/不变量/等。此外,它对于列表可能效率不高,因为它需要随机访问列表的内容,但我认为你不能使用“常规武器”来解决它(即不使用反射和直接内存操作)。

所以,我的建议是-重载是可行的。

票数 1
EN

Stack Overflow用户

发布于 2012-07-03 00:10:15

Linq Reverse()扩展方法缺少一个明显的优化,它总是创建一个临时数组来存储元素来反转它们。在列表或数组上使用它的开销太大了。

如果您想要一个就地反转,那么您可以编写一个扩展方法来选择正确的Reverse()方法:

代码语言:javascript
复制
public static class MyExtensions {
    public static void Reverse<T>(this IList<T> source) {
        if (source is List<T>) {
            ((List<T>)source).Reverse();
        }
        else if (source is T[]) {
            Array.Reverse((T[])source);
        }
        else throw new ArgumentException();
    }
}

您可以用同样的方法修复Linq反向方法:

代码语言:javascript
复制
public static class MyExtensions {
    public static IEnumerable<T> Reverse<T>(this IEnumerable<T> source) {
        if (source is IList<T>) {
            var list = (IList<T>)source;
            for (int ix = list.Count - 1; ix >= 0; --ix) {
                yield return list[ix];
            }
        }
        else {
            foreach (var item in Enumerable.Reverse(source)) {
                yield return item;
            }
        }
    }
}
票数 1
EN

Stack Overflow用户

发布于 2012-07-02 21:59:22

Reverse()将根据列表直接生成一个IEnumerable;不涉及复制。试一试,如果你只是迭代,它可能会更有效率。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/11295184

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档