开发者

How to avoid items order change in container after 'Select' extension method usage?

开发者 https://www.devze.com 2023-02-08 11:07 出处:网络
Here is a piece of code: public class Schema { public Schema(List<CountryParticipantsStages> places)

Here is a piece of code:

public class Schema
{
    public Schema(List<CountryParticipantsStages> places)
    {
        Places = places.Select(participant =>(AbstractGeneralParticipants) new GeneralParticipants(participant)).ToList();
    }
...

Order of element in source and result lists will be the same if source list is iterated in full. But if if 'Schema' constructor is called in the middle of any iteration then order of elements in 'Places' list will be shifted...

To avoid this I see the only way to use not a 'Select' method but a 'for' loop that will go from 0th element:

public class Schema
{
    public Schema(List<CountryParticipantsStages> places)
    {
        Places = new List<AbstractGeneralParticipants>(places.Count);
        for (int i = 0; i < places.Count; i++)
        {
            Places.Add(new GeneralParticipants(places[i]));
        }
    }

The 2nd function looks unpleasantly, but I don't see any better way for that. And also, ReSharper suggests me to replays 'for开发者_如何学JAVA' loop with 'foreach'...

Please advise.

Thanks a lot.


You're wrong to think that if list is being iterated in some place of program, its current position becomes shifted when it is passed as a parameter.

The list does not hold any current index or state. It's the client code that does.

What foreach essentially does is calling GetEnumerator method and uses IEnumerator to move forward and read current value. Once you pass list somewhere else, another foreach gets its own IEnumerator which starts from first element again.

Consider this sample:

void InnerEnumerate (List<int> innerList)
{
    foreach (var innerItem in innerList)
        Console.WriteLine ("- inner item {0}", innerItem);
}

var outerList = new List<int> { 1, 2, 3 };
foreach (var outerItem in outerList) {
    Console.WriteLine ("Outer item {0}", outerItem);
    InnerEnumerate (outerList); // pass list as a parameter
}

This is the output:

Outer item 1
- inner item 1
- inner item 2
- inner item 3
Outer item 2
- inner item 1
- inner item 2
- inner item 3
Outer item 3
- inner item 1
- inner item 2
- inner item 3

As you can see, foreach es are independent and don't know anything about each other. They always start from the beginning.


Guess, the best solution will be to avoid relying on the items order in the list. Instead would be better to add additional parameter into 'CountryParticipantsStages' class that will be used to determining its 'position' in list.


In your second example you can use a foreach loop as Resharper suggested:

Places = new List<AbstractGeneralParticipants>(places.Count);
foreach (Place place in places)
{
    Places.Add(new GeneralParticipants(place));
}

Or you can also do it using LINQ as in your first example, which is a bit more concise.

0

精彩评论

暂无评论...
验证码 换一张
取 消