difference between IEnumerable<T>.Reverse & List<T>.Reverse [duplicate] - c#

This question already has answers here:
Why there is two completely different version of Reverse for List and IEnumerable?
(3 answers)
Closed 7 years ago.
Why IEnumerable<T>.Reverse() returns the reversed collection with the original collection and List<T> reverses the original collection itself? This is somewhat confusing to me since List<T> inherits from IEnumerable<T>.

Because they're two different methods.
List<T>.Reverse is an instance method on List<T>. This modifies the List in place.
Enumerable.Reverse<T> is an extension method on IEnumerable<T>. This creates a new sequence that enumerates the source sequence in reverse order.
You can use the latter on a List<T> by calling as a static method:
var list = new List<string>{"1","2"};
var reversed = Enumerable.Reverse(list)
Or by casting to IEnumerable<T>:
IEnumerable<string> list = new List<string>{"1","2"};
var reversed = list.Reverse();
In both these cases, list remains unchanged and reversed when enumerated returns {"2","1"}.

Conceptually, this may be because IEnumerable is used when you want to represent an immutable collection of items. That is, you only want to read the items in the list, but not add/insert/delete or otherwise change the collection. In this view of the data, returning a new IEnumerable in a different order is the expected result. When you use a List, you expected to be able to add/insert/delete or otherwise mutate the collection, so a Reverse method that changes the order of the original list would be expected in that context.
As others have noted IEnumerable is an interface and List is a class. List implements IEnumerable.
So,
IEnumerable<String> names = new List<String>();
var reversedNames = names.Reverse();
gets you a second list, reversed.
Whereas,
List<String> names = new List<String>();
names.Reverse();
Reverses your original list. I hope this makes sense.

Reverse on IEnumerable<T> is part of Linq and is added as extension method (Enumerable.Reverse<T>). It was added after Reverse was implemented for List<T>.
IEnumerable<T> isn't a collection of objects either. It just tells the consumer how to get at those items.

These are different methods, remember. Essentially different, with nothing common but a name.
void List.Reverse is a method of List instance only, and it does in place reversal of list or part of it.
IEnumerable Enumerable.Reverse is an extension method (btw IList also has it!) creates a new enumerable with order reversed.

There is no such thing as IEnumerable<T>.Reverse() It's Enumerable.Reverse<T>(this IEnumerable<T>) and it's extension method from Linq applied to all IEnumerable<>.
Now that we've established when they come from, it's easy to understand why they are so different. Linq adds methods for creating "processing streams", and it's achieved by creating new instance every time.
List<T>.Reverse() is a method of List and like all it's methods (eg Add) directly modifies the instance.

IEnumerable<T> has an underlying implementation, which could be List<T>, Hashtable<T> or something else that implements IEnumerable.
List<T> itself is the implementation, so you can directly modify that instance.
And as everyone else has mentioned, one is an extension method and part of Linq, and one is implemented directly on the type.

Related

Why do I need to cast a List<T> of a declared List<T> when passing through a Lambda OrderBy expression? [duplicate]

This question already has answers here:
OrderBy and List vs. IOrderedEnumerable
(6 answers)
Closed 2 years ago.
So I'm trying to sort a list of my objects using lambda like so:
List<DirectoryObjects> sort = dirObjList.OrderBy(ms => ms.name);
Visual Studio though says that is wrong and it says this is correct:
List<DirectoryObjects> sort = (List<DirectoryObjects>)dirObjList.OrderBy(ms => ms.name);
I've been exposed to lambda before but I've never really understood it. My way of doing it seems correct to me because I'm under the impression lambda is just sorting my list for me but still retaining it's type. Is it wrong to think that? The second instance looks...redundant to me. Why would I need to cast a sorted List when it already is that? Or should I think of lambdas as something that converts Enum's to a different type?
The lambda in itself is irrelevant here, the key is LINQ behavior.
The OrderBy extension method does NOT order your list as you think. Instead, it creates a new, independent IEnumerable<T> with the result of the sorting, leaving the original untouched. So it's not a List<T>, but a completely different type, whose only capability is to be enumerated, following the order you asked for.
A List is that and also a couple more things (irrelevant for now), but the important thing is that the return value of OrderBy is not a list. The proposed cast is also wrong just because of that, as you're trying to cast an IEnumerable<T> to List<T>. In general, those casts may or may not work, depending on the real underling type (as IEnumerable<T> is an interface, compared to List<T> being a concrete class), so the compiler allows it. In the particular case of LINQ's OrderBy it'll certainly fail, as it doesn't returns a list at all.
To actually get a list, you can use yet another LINQ method, ToList:
List<DirectoryObjects> sort = dirObjList.OrderBy(ms => ms.name).ToList();
This will iterate the original collection, sort it as you want, and store the result in a new List<T> object.

What difference between the Queryable.Contains method and the List<T>.Contains method in C#?

List<A> list=new List<A>();
var a=new A();
list.Add(a);
list.Contains(a);
list.Contains<A>(a);
What difference between this two cases?
Why exists two method?
There is no difference in this case between List.Contains (which is the implementation of ICollection.Contains) and Enumerable.Contains - in the case where the enumerable is a collection, IEnumerable.Contains simply invokes ICollection.Contains.
The reasoning there is that some collections - such as SortedSet - can implement a Contains method that operates at better than O(n) time. For non-collection types of Enumerable, IEnumerable.Contains will do a linear search over the enumeration.
There is also Queryable.Contains, but that's different - List isn't a queryable. Queryable.Contains can build this into a query expression which can be translated (for example, into SQL). Queryable and Enumerable extension methods are very different under the hood.
If you ask about difference in its functionality, then there is actually none.
List.Contains() is a part of ICollection interface and exists since .NET Framework 2.0. Developers have always used this method before LINQ to check if List or another ICollection contains an item.
.Contains<T> is a part of LINQ. It is a query language which allows you to use this method with all IEnumerable collections, even arrays or custom; data sources likes databases; data formats like JSON or XML etc.
Actually, when you call LINQ .Contains<T> on IEnumerable collection which is ICollection (for example, List<T>), it does call its own ICollection.Contains method.
public static bool Contains<TSource>(this IEnumerable<TSource> source, TSource value)
{
ICollection<TSource> collection = source as ICollection<TSource>;
if (collection != null)
return collection.Contains(value);
return Enumerable.Contains<TSource>(source, value, (IEqualityComparer<TSource>) null);
}
The algorithmic complexity of "LIST.contains" is O(n) always.
Where as "Queryable.contains" complexity depends on the collection implemented. For example, if underlying collection is "Hashset", then the algorithmic complexity is O(1).

Does usage of contains on IEnumerable cast it to a List?

I'm using Linq to filter Data I get from the database. Due to design choices made 1 method returns me an IEnumerable<int> which I then use for a linq statement to see which IDs are permitted to be returned (code follows below). My question here is as I'm not seeing anything there in the documentation: Does the Contains method implicitly cast the IEnumerable to a List for the statement to be executed? (If so the question is if using List in the first place instead of IEnumerable is better).
Code Example
private List<MyData> GetAllPermittedData()
{
IEnumerable<int> permitteddIds = GetPermittedIDs();
return (from a in MyDataHandler.GetAllData() where permittedIds.Contains(a.Id)
select a);
}
Like I asked above I'm not sure if the Contains part implicitly converts permittedIds into a List<int> (for/inside the use of the Contains statement). If this is the case then a followup question would be if it is not better to already use the following statement instead (performance-wise):
private List<MyData> GetAllPermittedData()
{
List<int> permitteddIds = GetPermittedIDs().ToList();
return (from a in MyDataHandler.GetAllData() where permittedIds.Contains(a.Id)
select a);
}
The LINQ operator will attempt to cast it to ICollection<T> first. If the cast succeeds, it uses that method. Since List<T> implements this interface, it will use the list's contain method.
Note that if you use the overload that accepts an IEqualityComparer, it must iterate over the enumerable and the ICollection shortcut is not taken.
You can see this implementation in the .NET Framework reference source:
public static bool Contains<TSource>(this IEnumerable<TSource> source, TSource value) {
ICollection<TSource> collection = source as ICollection<TSource>;
if (collection != null) return collection.Contains(value);
return Contains<TSource>(source, value, null);
}
Jon Skeet also has a good (and lengthy) blog series called "Reimplementing LINQ" where he discusses the implementation in depth. He specifically covers Contains in part 32 of his blog.
The Contains method may try to cast the passed IEnumerable<T> to IList<T> or to ICollection<T>. If the cast succeeds, it may directly use the methods of IList<T>, otherwise it will enumerate over the full sequence.
Note that I am writing may because this is implementation-specific and it is not specified in the docs. As such, it could be different across .NET versions and also in alternative implementations such as Mono.
Your advantage by providing only an IEnumerable<T> is that you have more freedom to exchange the object returned from that property without changing the public interface. The performance cost of the attempted cast to IList<T> or similar should be negligible.
In any case, this way is more performant than your suggestion of calling ToList, as that will actually create a new List<T> and copy all items from the enumeration into it.
Contains exists as an extension method for IEnumerable<T>. But you con't need to convert your IEnumerable to a List<T> with ToList(), you could simply use that IEnumerable<T> to fill a HashSet<T>:
var permitteddIds = new HashSet<int>(GetPermittedIDs());

How to convert unioned generic list to generic list?

I have two generic list that have been unioned. Say listA and listB, both of type List<SomeType>.
listA.Union(listB);
The unioned set is of type System.Linq.Enumerable.UnionIterator<string>, which isn't the same as List<SomeType>.
I have tried casting:
listA.Union(listB).ToList<SomeType>();
and
(List<SomeType>)listA.Union(listB);
Both fail. I tried to access ForEach(), thinking I could add the result to a new list. .Foreach() isn't available.
I could use a traditional foreach and add each item to a List<SomeType> variable. However, is there a lambda statement that can do the conversion in one line, assigning to a variable of type List<SomeType>?
You don't have to explicitly cast the List in ToList method. If both the list are of same type, you can simply do ToList in the end to get a List of the same type.
List<MyClass> listA = new List<MyClass>();
List<MyClass> listB = new List<MyClass>();
List<MyClass> temp = listA.Union(listB).ToList(); //Just do ToList at the end.
Explicitly specifying the type in ToList method should work as well. I am not sure why its not working.
Union is an extension method on IEnumerable<T> interface, not on List<T>, so it doesn't know or care that you are trying to connect lists and thus does not create one as a result unless you call ToList explicitly.
If you want to 'attach' one list to another, you might want to use AddRange method instead.

list sorting in c#

i have list of objects i need to sort the list based on object's property1 and i need to sort again the resultant list with object's property2 without loosing the grouping done in first sorting ....
for ex:
obj has 2 property name and location
i need to have a final list of objects which has been sorted with region and objects of same region should be sorted by name...
(Assuming you don't have LINQ available to you, which makes this trivial.)
If you look in MiscUtil, you'll find two useful classes: ProjectionComparer and LinkedComparer (IIRC).
ProjectionComparer basically implements the LINQ "order by" concept - you specify how to convert a source element to a key value, and the comparer will order by those key values.
LinkedComparer takes two comparers and returns a new comparer which uses the "primary" comparer first, and the "secondary" comparer if values are equal with respect to the primary one.
Create two projection comparers (one for each property) and then a linked comparer with the two of them, then pass that to List<T>.Sort. Let me know if you need a full code sample, but it would be something like (using C# 3):
var comparer = new LinkedComparer<Foo>
(ProjectionComparer<Foo>.Create(x => x.FirstProperty),
ProjectionComparer<Foo>.Create(x => x.SecondProperty));
(In C# 2 you could use anonymous methods, they'd just be a bit more long-winded.)
Sounds like you want to use LINQ's orderby and thenby syntax.
A List has a Sort method which takes a Comparision delegate as an argument.
There are also overloads where you can pass in your own comparer.
So, you can write a class which implements IComparer. Then, in the implementation of this class, you write the code where you compare the 2 objects on the properties you want.

Categories

Resources