什么是Enumerable.ElementAt&LT点; TSource>? [英] What's the point of Enumerable.ElementAt<TSource>?

查看:157
本文介绍了什么是Enumerable.ElementAt&LT点; TSource>?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

的IEnumerable< T> 公开枚举,所以对象可以被列举。没有任何关于这个接口暴露指标。 的IList< T> 约指标,因为它暴露了的IndexOf 方法

IEnumerable<T> exposes an enumerator, so the object can be enumerated. There is nothing about indexes exposed by this interface. IList<T> is about indexes, as it exposes the IndexOf method.

那么,有什么Enumerable.ElementAt的地步?我刚才读的这个文档 LINQ扩展方法:

So what's the point of Enumerable.ElementAt? I just read the doc of this LINQ extension method:

返回序列中指定索引处的元素。

Returns the element at a specified index in a sequence.

嗯,是的,它是关于一个,不只是一个的IEnumerable 。阅读上述表示的:

Well, yes, it's about a sequence, not just an IEnumerable. Reading the remarks:

如果源类型实现IList,即实现使用   获得该元素的指定索引处。否则,该方法   获得指定的元素。

If the type of source implements IList, that implementation is used to obtain the element at the specified index. Otherwise, this method obtains the specified element.

好了,所以如果具体类型实现的东西,继承的IList&LT; T&GT; (这是一个实际的序列),那么它的同的IndexOf()。如果不是,它迭代直到索引被达到。

Okay, so if the concrete type implements something that inherits from IList<T> (which is an actual sequence), then it's the same as IndexOf(). If not, it iterates until the index is reached.

下面是一个示例场景:

// Some extension method exposed by a lib
// I know it's not a good piece of code, but let's say it's coded this way:
public static class EnumerableExtensions
{
    // Returns true if all elements are ordered
    public static bool IsEnumerableOrdered(this IEnumerable<int> value)
    {
        // Iterates over elements using an index
        for (int i = 0; i < value.Count() - 1; i++)
        {
            if (value.ElementAt(i) > value.ElementAt(i + 1))
            {
                return false;
            }
        }

        return true;
    }
}

// Here's a collection that is enumerable, but doesn't always returns
// its objects in the same order
public class RandomAccessEnumerable<T> : IEnumerable<T>
{
    private List<T> innerList;
    private static Random rnd = new Random();

    public RandomAccessEnumerable(IEnumerable<T> list)
    {
        innerList = list.ToList();
    }

    public IEnumerator<T> GetEnumerator()
    {
        var listCount = this.innerList.Count;
        List<int> enumeratedIndexes = new List<int>();

        for (int i = 0; i < listCount; i++)
        {
            int randomIndex = -1;
            while (randomIndex < 0 || enumeratedIndexes.Contains(randomIndex))
            {
                randomIndex = rnd.Next(listCount);
            }

            enumeratedIndexes.Add(randomIndex);
            yield return this.innerList[randomIndex];
        }
    }

    IEnumerator IEnumerable.GetEnumerator()
    {
        return this.GetEnumerator();
    }
}

// Here's some test program
internal class Program
{
    private static void Main()
    {
        var test0 = new List<int> { 0, 1, 2, 3 };
        var test1 = new RandomAccessEnumerable<int>(test0);

        Console.WriteLine("With List");
        Console.WriteLine(test0.IsEnumerableOrdered()); // true
        Console.WriteLine(test0.IsEnumerableOrdered()); // true
        Console.WriteLine(test0.IsEnumerableOrdered()); // true
        Console.WriteLine(test0.IsEnumerableOrdered()); // true
        Console.WriteLine(test0.IsEnumerableOrdered()); // true

        Console.WriteLine("With RandomAccessEnumerable");
        Console.WriteLine(test1.IsEnumerableOrdered()); // might be true or false
        Console.WriteLine(test1.IsEnumerableOrdered()); // might be true or false
        Console.WriteLine(test1.IsEnumerableOrdered()); // might be true or false
        Console.WriteLine(test1.IsEnumerableOrdered()); // might be true or false
        Console.WriteLine(test1.IsEnumerableOrdered()); // might be true or false

        Console.Read();
    }
}

所以,作为 RandomAccessEnumerable 可能以随机顺序返回枚举的对象,你就不能依靠简单的的IEnumerable&LT; T&GT; 接口,假设你的元素被索引。所以,你不希望使用的ElementAt 的IEnumerable

So, as RandomAccessEnumerable might return enumerated objects in a random order, you just can't rely on the simple IEnumerable<T> interface to assume your elements are indexed. So you don't want to use ElementAt for an IEnumerable.

在上面的例子中,我觉得 IsEnumerableOrdered 应要求的IList&LT; T&GT; 参数,因为它意味着元素的序列。我居然找不到一个方案,其中的的ElementAt 方法是有用的,而不是容易出错的。

In the above example, I think IsEnumerableOrdered should require a IList<T> parameter as it implies elements are a sequence. I actually can't find a scenario where the ElementAt method is useful, and not bug-prone.

推荐答案

有许多的IEnumerable 类型,如数组或列表。所有的IList 种(其中 阵列 还实现)具有的 索引 ,您可以使用在特定的索引来访问元素。

There are many IEnumerable types like array or list. All IList types(which Array also implements) have an indexer which you can use to access elements at a specific index.

这将使用 Enumerable.ElementAt 如果序列能够成功地铸造为 IList中。否则,将被一一列举。

This will be used by Enumerable.ElementAt if the sequence can be casted to IList successfully. Otherwise it will be enumerated.

所以,这只是一个方便的方式来访问元素指定索引所有类型的的IEnumerable 类型。

So it's just a convenient way to access elements at a given index for all kind of IEnumerable types.

该做的好处是,你可以在以后更改类型,而无需更改所有出现的ARR [指数]

This has the advantage that you can change the type later without needing to change all occurences of arr[index].

有关它的价值,这里的反映(ILSpy)方法来证明我说的话:

For what it's worth, here's the reflected(ILSpy) method to demonstrate what i've said:

public static TSource ElementAt<TSource>(this IEnumerable<TSource> source, int index)
{
    if (source == null)
    {
        throw Error.ArgumentNull("source");
    }
    IList<TSource> list = source as IList<TSource>;
    if (list != null)
    {
        return list[index];
    }
    if (index < 0)
    {
        throw Error.ArgumentOutOfRange("index");
    }
    TSource current;
    using (IEnumerator<TSource> enumerator = source.GetEnumerator())
    {
        while (enumerator.MoveNext())
        {
            if (index == 0)
            {
                current = enumerator.Current;
                return current;
            }
            index--;
        }
        throw Error.ArgumentOutOfRange("index");
    }
    return current;
}

这篇关于什么是Enumerable.ElementAt&LT点; TSource&GT;?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆