Using iList to process items failing - c#

It would be great to have shorthand for processing every item in a list, in this case saving.
SO intead of
var people = MakePeople();
foreach (var person in people)
{
session.Save(person);
}
we could use
var cards = MakeCards(deck);
cards.Select(session.Save);
But, that doesn't work.. Suggestions? Aggregate?

Select uses lazy evaluation, so it won't work.
You're looking for List<T>.ForEach, or its non-existent LINQ version.

It looks like Save() has no return value. To use the method with Select(), it needs to have a return value.
In general, it's a bad idea to use LINQ with methods that have side effects (like Save()). When there are side-effects, the first method is certainly preferred. If MakePeople returns a concrete List, you could also try:
var people = MakePeople();
people.ForEach((p) => { session.Save(p); });

List has a ForEach(Action<T> action) method.

You tried to create a Card -> Void mapping. Select is meant to convert one item to another type so you can convert a card collection to e.g. a cardnumber collection.
As the others have already mentioned List has a ForEach overload. But the general theme of the C# language designers (see Eric Lipperts blog) was to not provide such an extension method since foreach is clearer. It does not safe you an awful amount of typing so the benefit here is minmal.
For refernce you can create an extension method like that does what you want with 3 lines of code.
public static void ForEach<T>(this IEnumerable<T> sequence, Action<T> action)
{ // argument null checking omitted
foreach(T item in sequence) action(item);
}
Nitpick Corner: I did mean and write that (at least one influental) C# language designer did not want to introduce this extension method. Once it exists in the BCL it can be used by any .NET language.
Yours,
Alois Kraus

Related

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());

Should I cast in my lambda or cast the IEnumerable?

In my project I have a MyClass which implements IMyClass. I need to return a list of IMyClass by transforming a list of other items. For simplicity's sake, assume that I can create a MyClass just by passing another item into its constructor, i.e. new MyClass(item).
Consider the following two lines, which (as far as I know) produce the same result:
var option1 = items.Select(item => new MyClass(item)).Cast<IMyClass>().ToList()
var option2 = items.Select(item => new MyClass(item) as IMyClass).ToList()
It seems to me that option #1 would require a double enumeration, once to cast all the items to my interface and once to generate the list. If I'm right then option #2 would be smarter. However, I've never seen any code using something like option #2, and I tend to assume that I'm not smart enough to come up with something clever that the rest of the C# community did not.
On a side note, I think option #2 is more aesthetically pleasing, but that's just me.
My question is: is my option #2 a better idea like I think it is? Are there are any gotchas I'm missing or other reasons why I'd want to stick with option #1? Or am I perhaps comparing two stupid ideas when there is a smarter third one that I'm missing completely?
I'd go for option 3:
var option3 = items.Select<Foo, IMyClass>(item => new MyClass(item))
.ToList()
Alternatively, don't use as but just cast normally:
var option4 = items.Select(item => (IMyClass) new MyClass(item))
.ToList()
Both of these seem cleaner than using Cast.
Oh, and as of C# 4 with .NET 4 (due to covariance), you could put a type argument on the ToList call instead:
var option5 = items.Select(item => new MyClass(item))
.ToList<IMyClass>()
It seems to me that option #1 would require a double enumeration
This is not true. In both cases, the items collection is only enumerated when you get to ToList().
The line
var option1 = items.Select(item => new MyClass(item)).Cast<IMyClass>().ToList()
is equivalent to
var option1 = items.Select(item => new MyClass(item)).Select(x => (IMyClass)x).ToList()
The only difference between the two is that the first one requires two function calls per item (unless C# inlines the lambdas somehow, which I don't believe is the case) while the second option requires only one.
Personally, I'd go with the second one as a matter of style.
Which one you use is a matter of preference, something we really cannot answer for you.
But your intuition if sort-of correct that Cast adds a second layer of iteration to your loop. It's very minor, and I doubt it will produce any measurable difference in performance, but the Cast method returns a new IEnumerable object that basically does this:
foreach (object obj in source) yield return (TResult)obj;
The effect is mostly another level on the call stack; since it uses yield it will only iterate on demand, like most other IEnumerable methods. But it will have to return though two levels of iterator state instead of one. Whether that matters for you is something you'll need to measure for your own applications.
(Also note that, at least according to the reference source, it does an unsafe cast, which might throw an exception if the cast is invalid. That's another reason to prefer your option #2.)
You can always provide explicit type arguments to your Select
var option2 = items.Select<IItem,IMyClass>(item => new MyClass(item)).ToList();
where IItem is a type or interface to which items could be cast.

IEnumerable Extensions with No-Throw Guarantee

Personally, I'm a fan of the fluent interface syntax of the IEnumerable/List extension methods in C#, as a client. That is, I prefer syntax like this:
public void AddTheseGuysToSomeLocal(IEnumerable<int> values)
{
values.ToList().ForEach(v => _someLocal += v);
}
as opposed to a control structure like a foreach loop. I find that easier to process mentally, at a glance. Problem with this is that my code here is going to generate null reference exceptions if clients pass me a null argument.
Let's assume that I don't want to consider a null enumeration to be exceptional -- I want that to result in leaving some local as-is -- I would add a null guard. But, that's a little syntactically noisy for my taste, and that noise adds up in cases where you're chaining these together in a fluent interface and the interim results can be null as well.
So, I created a class called SafeEnumerableExtensions that offers a no-throw guarantee by treating nulls as empty enumerables (lists). Example methods include:
//null.ToList() returns empty list
public static List<T> SafeToList<T>(this IEnumerable<T> source)
{
return (source ?? new List<T>()).ToList();
}
//x.SafeForEach(y) is a no-op for null x or null y
//This is a shortcut that should probably go in a class called SafeListExtensions later
public static void SafeForEach<T>(this List<T> source, Action<T> action)
{
var myAction = action ?? new Action<T>(t => { });
var mySource = source ?? new List<T>();
mySource.ForEach(myAction);
}
public static void SafeForEach<T>(this IEnumerable<T> source, Action<T> action)
{
SafeToList(source).SafeForEach(action);
}
Now, my original method is prettier than if there were a null guard, but just as safe, since null result in a no-op:
public void AddTheseGuysToSomeLocal(IEnumerable<int> values)
{
values.ForEach(v => _someLocal += v);
}
So, my question is twofold. (1) I'm assuming that I'm not so original as to be the first person ever to have thought of this -- does anyone know if there is an existing library that does this or something similar? And (2) has anyone used said library or implemented a scheme like this and experienced unpleasant consequences or else can anyone foresee unpleasant consequences for doing something like this? Is this even a good idea?
(I did find this question when checking for duplicates, but I don't want to explicitly do this check in clients - I want the extension class to do this implicitly and not bother clients with that extra method call)
And (2) has anyone used said library or implemented a scheme like this
and experienced unpleasant consequences or else can anyone foresee
unpleasant consequences for doing something like this? Is this even a
good idea?
Personally I would consider this a bad idea. In most cases passing a null enumeration or null Func is probably not intended.
You are "fixing" the problem which might lead to seemingly unrelated problems later down the road. Instead I would rather throw an exception in this case so that you find this problem in your code early on ("Fail fast").

IEnumerable<T> null coalescing Extension

I frequently face the problem to check whether an IEnumerable<T> is null before iterating over it through foreach or LINQ queries, then I often come into codes like this:
var myProjection = (myList ?? Enumerable.Empty<T>()).Select(x => x.Foo)...
Hence, I thought to add this extension-method to an Extensions class:
public static class MyExtensions
{
public static IEnumerable<T> AsEmptyIfNull<T>(this IEnumerable<T> source)
{
return source ?? Enumerable.Empty<T>();
}
}
A little issue comes immediately in my mind looking at this code, i.e., given the "instance-methods aspect" of extension-methods, it should be implemented as a mere static method, otherwise something like this would be perfectly legal:
IEnumerable<int> list = null;
list.AsEmptyIfNull();
Do you see any other drawback in using it ?
Can such extension leading to some kind of bad-trend in the developer(s), if massively used?
Bonus question:
Can you suggest a better name to it ? :)
(English is not my first language, then I'm not so good in naming...)
Thanks in advance.
Methods that return an IEnumerable<T> should return an empty one, instead of null. So you wouldn't need this.
See this question : Is it better to return null or empty collection?
Otherwise, your code seems ok.
It's generally a bad idea to return a null instead of an empty sequence if you can control it. This is self-explanatory if you consider that when someone is asked to produce a collection, returning null is not like saying "the collection is empty" but "there is no such collection at all".
If you own the methods returning the enumerables, then returning an empty IEnumerable (which can even be a special purpose readonly static object if it might be returned a lot) is the way to go, period.
If you are forced to use a bad-mannered library that has the habit of returning null in such cases, then this an extension method might be a solution, but again I wouldn't prefer it. It's probably better to wrap the bad-mannered methods in your own versions that do the coalescing where people won't see it. This way you get both the convenience of always having an enumerable instead of null and the correctness of not supporting the "return null" paradigm.

Visual studio 2005: List<T>.First() List<T>.Last() methods in C#?

I used List<T>.First() as well as List<T>.Last() in my VS 2008 C# project, but when I've downgraded to 2005 I got errors like this:
'System.Collections.Generic.List' does not contain a definition for 'First'
As far as I understand, if still there are Find() and FindLast() methods there MUST be a very very simple way to get iterators to the first and last values, am I right? But I'm stuck with this and can't find anything useful :(
First() and Last() are part of LINQ which is why they're not being found in your VS 2005 project.
If you're using a List<T> it's really, really easy to find the first and last values, assuming the list is non-empty:
T first = list[0];
T last = list[list.Count-1];
If you really need to use iterators you can implement the LINQ methods really easily:
public static T First<T>(IEnumerable<T> source)
{
foreach (T element in source)
{
return element;
}
throw new InvalidOperationException("Empty list");
}
public static T Last<T>(IEnumerable<T> source)
{
T last = default(T);
bool gotAny = false;
foreach (T element in source)
{
last = element;
gotAny = true;
}
if (!gotAny)
{
throw new InvalidOperationException("Empty list");
}
return last;
}
(I suspect the real implementation of Last checks whether source is an IList<T> or not and returns list[list.Count-1] if so, to avoid having to iterate through the whole collection.)
As pointed out in the comments, these aren't extension methods - you'd write:
// Assuming the method is in a CollectionHelpers class.
Foo first = CollectionHelpers.First(list);
instead of
Foo first = list.First();
but the effect is the same.
There are 2 problems here
Both First and Last are extension methods. The compiler included in VS2005 do not support extension methods so there is no way to bind to them
The First and Last methods are included in the 3.5 framework which is not usable from VS2005.
First is not a method of List<T>. First is a static method on System.Linq.Enumerable in .net 3.5 .
Those are extension methods. You are bringing up a typical case against extension methods whereas they can be confusing since they seem to belong to the class, but are actually defined elsewhere entirely. For the first/last for a List, you can still use list[0] and list[list.Count-1] (with added error handling, of course).

Categories

Resources