Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/260.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 扩展ienumerable方法C_C# - Fatal编程技术网

C# 扩展ienumerable方法C

C# 扩展ienumerable方法C,c#,C#,我写了跳过最后一个方法。当我用int数组调用它时,我希望只返回2个元素,而不是4个 怎么了 谢谢 public static class myclass { public static IEnumerable<T> SkipLast<T>(this IEnumerable<T> source, int n) { return source.Reverse().Skip(n).Reverse(); } } class

我写了跳过最后一个方法。当我用int数组调用它时,我希望只返回2个元素,而不是4个

怎么了

谢谢

public static class myclass
{
    public static IEnumerable<T> SkipLast<T>(this IEnumerable<T> source, int n)
    {
        return source.Reverse().Skip(n).Reverse();
    }

}

class Program
{
    static void Main(string[] args)
    {
        int [] a = new int[] {5, 6, 7, 8};
        ArrayList a1 = new ArrayList();

        a.SkipLast(2);
        for( int i = 0; i <a.Length; i++)
        {
            Console.Write(a[i]);
        }

    }
}
你需要打电话给我

var newlist = a.SkipLast(2);
for( int i = 0; i <newlist.Count; i++)
{
    Console.Write(newlist[i]);
}
您的方法将返回跳过的列表,但原始列表将不会更新

如果要分配或更新相同的列表,可以将返回的列表设置回原始状态,即a=a.SkipLast2.ToArray

您应该分配结果,而不仅仅是放置a.SkipLast2:

将代码更改为

foreach (var r in a.SkipLast(2))
{
    Console.Write(r);
}
原因有三,

SkipLast函数返回变异序列,它不会直接更改它。 将索引器与IEnumerable一起使用有什么意义?它强加了一个不必要的计数。 此代码易于阅读、易于键入并显示意图。 有关更有效的通用SkipLast,请参见

您的示例可以使用更专业的SkipLast


其他回答已经回答了您的问题,但更有效的实现不是这样的吗?它不需要制作两个数组副本以将其反转两次。它会迭代集合两次,或者更确切地说,一次,然后计数n次访问:

public static IEnumerable<T> SkipLast<T>(this IEnumerable<T> source, int n)
{
    n = source.Count() - n;
    return source.TakeWhile(_ => n-- > 0);
}

您应该添加.ToArray。您不应该访问该for循环中的newList吗?如果我不想用任何其他int数组调用它怎么办。@user1048791:use-foreach;我写了a=a.SkipLast2.ToArray;只是为了保持你的for循环完好无损。通常的方法是在使用LINQ时放置foreach循环-请参阅ASN中我的建议,ArrayList的作用是什么?这里不使用它,这是一件好事。唯一的问题是,IEnumerable不需要证明它可以被枚举两次。在给出的具体示例中,数组显然可以被多次枚举,但这并不是IEnumerable的每个实现都是如此。@Jodrell是的,但这样的枚举总是需要特殊处理。您不希望将其用于Directory.EnumerateDirectory,例如:@JeppeStigNielsen是的,正如我上面所说的,其他回答就是答案。这个回复只是一个注释,但显然我不能用普通的注释编写格式化代码!我的答案是尽量避免复制潜在的大数据,所以按照您的建议执行source.ToArray是我明确希望避免的事情!顺便说一句,我喜欢你最新添加的n长度缓冲区@我的另一个建议避免了你提出的问题。
foreach (var r in a.SkipLast(2))
{
    Console.Write(r);
}
public static IEnumerable<T> SkipLast<T>(this IList<T> source, int n = 1)
{
    for (var i = 0; i < (source.Count - n); i++)
    {
        yield return source[i];
    }
}
public static IEnumerable<T> SkipLast<T>(this IEnumerable<T> source, int n)
{
    n = source.Count() - n;
    return source.TakeWhile(_ => n-- > 0);
}
public static IEnumerable<T> SkipLast<T>(this IEnumerable<T> source, int n)
{
    int count = 0;
    T[] buffer = new T[n];

    var iter = source.GetEnumerator();

    while (iter.MoveNext())
    {
        if (count >= n)
            yield return buffer[count%n];

        buffer[count++%n] = iter.Current;
    }
}