C# 如何使用反向(数组、Int32、Int32)或列表<;T>;::IList上的反向方法(Int32,Int32)?
我的程序大量使用C# 如何使用反向(数组、Int32、Int32)或列表<;T>;::IList上的反向方法(Int32,Int32)?,c#,C#,我的程序大量使用Reverse,例如Array.Reverse(myArray,3,5) 我希望我的程序可以同时接受数组和列表作为输入,所以我选择IList 但是,我找不到与Reverse相同的IList方法 有一个扩展方法名为Reverse,但是它会生成IEnumerable流,但不会就地重新排列。(我认为这需要更多的复制时间) 我曾想过使用cast,但担心cast也会效率低下 那么,我该怎么办 最坏的情况是,我制作2个程序,1个takes数组,另一个takes列表,然后重载?Reverse(
Reverse
,例如Array.Reverse(myArray,3,5)
我希望我的程序可以同时接受数组
和列表
作为输入,所以我选择IList
但是,我找不到与Reverse
相同的IList
方法
有一个扩展方法名为Reverse
,但是它会生成IEnumerable
流,但不会就地重新排列。(我认为这需要更多的复制时间)
我曾想过使用cast
,但担心cast
也会效率低下
那么,我该怎么办
最坏的情况是,我制作2个程序,1个takes数组,另一个takes列表,然后重载?Reverse()
将直接基于列表生成一个IEnumerable
;不涉及复制。试一试,如果只进行迭代,可能效率更高。Array.Reverse()
是静态的:
T[] arr = ...
Array.Reverse(arr); // in-place
列表。反向
不是:
List<T> list = ...
list.Reverse(); // in-place too
List=。。。
list.Reverse();//也到位了
还有一种LINQ扩展方法:
IList<T> ilist = ...
IEnumerable<T> e = ilist.AsEnumerable();
IEnumerable<T> result = e.Reverse(); // not in-place
IList IList=。。。
IEnumerable e=ilist.AsEnumerable();
IEnumerable result=e.Reverse();//不到位
如果您想要一个采用IList的就地反向方法,而不仅仅是一个列表或数组,那么您必须自己编写它。这不是一个特别复杂的算法,所以我想你自己也可以编写这样一个方法。OOP-way-制作一个包装器,将其重载十几次:
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);
}
只需添加范围检查/前提条件/不变量等。此外,列表可能效率低下,因为它需要随机访问列表的内容,但我认为您无法使用“常规武器”(即不使用反射和直接内存操作)来解决此问题
因此,我的建议是:重载是一种方法。Linq Reverse()扩展方法忽略了一个明显的优化,它总是创建一个临时数组来存储元素以反转它们。这对于列表或数组来说太昂贵了
如果需要在位反转,则可以编写一个扩展方法来选择适当的reverse()方法:
公共静态类MyExtensions{
公共静态无效反向(此IList源){
如果(来源是列表){
((List)source.Reverse();
}
else if(源为T[]){
Array.Reverse((T[])源;
}
否则抛出新的ArgumentException();
}
}
可以用相同的方法修复Linq反转方法:
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;
}
}
}
}
公共静态类MyExtensions{
公共静态IEnumerable反向(此IEnumerable源){
如果(源为IList){
变量列表=(IList)源;
for(int ix=list.Count-1;ix>=0;--ix){
收益回报表[ix];
}
}
否则{
foreach(可枚举中的var项。反向(源)){
收益回报项目;
}
}
}
}
这可能会帮助您解决IList
问题。也许放弃使用像Array和List这样的具体类,转而使用它们的接口是个好主意?也许IEnumerable适合您的需要?总之,您始终可以从IEnumerable中取回列表或数组。@J0HN不,使用IEnumerable时,您无法取回列表
或数组
。您可以创建一个新列表或一个新数组,但这非常简单different@Servy我从来没有想过它会是完全相同的数组。是的,它肯定会构建新的阵列,但是,避免这种阵列重构不是一种过早的优化吗?只有OP知道:)@J0HN当你说取回“你的数组”而不是“一个数组”时,它确实暗示了相同的一个,是的。此外,OP确实指出,在适当的位置进行反向操作非常重要。这部分是因为他引用了反向重载,该重载使用两个int
参数,只允许反转数组的一部分而不是整个数组。除了优化之外,还可能有其他原因希望在适当的位置执行此操作(因为影响您可能无法控制的对对象的其他引用很重要)。
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();
}
}
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;
}
}
}
}