19

I've been busy diving into lambda expressions recently, and there's some specific functionality that I've been meaning to learn but just couldn't seem to make heads or tails of.

Suppose that I have the following logic in my code:

List<A> foo; // assuming this is populated
string[] bar = foo.Select<A,string>(x => x.StringProperty).ToArray<string>();

Now, I want to perhaps abstract that whole operation into a handler method so that I can do this instead:

string[] bar = MakeArray<A,string>(foo, x => x.StringProperty);
int[] foobar = MakeArray<A,int>(foo, x => x.IntegerProperty);

How would I go about with writing that method's body? I foresee declaring the signature as something like:

U[] MakeArray<T,U>( /* some lambda magic? */ ) where T : IEntity {}

but I don't know how to specify that I'm expecting a lambda expression as the method argument, and how that translates exactly into the body of the method.

Can anybody show me how to create the MakeArray() function above? I'm pretty sure that once I see how it's done, that I can pick it up from there.

EDIT

As pointed out in the comments, MakeArray() needed a reference to the IEnumerable<>. Updated to reflect that.

Richard Neil Ilagan
  • 14,627
  • 5
  • 48
  • 66
  • 5
    FWIW the implicit nature of the generics can add a readable value to your code by not having to explicitly state the type with each statement, this could be subjective though. The following statement is equal to your first select.. `string[] bar = foo.Select(x => x.StringProperty).ToArray();` – Quintin Robinson Mar 22 '11 at 19:36
  • If you find yourself using arrays all over your code, you may want to consider refactoring them into `IEnumerable` or `IList`. Then none of this will be necessary. Also, doesn't `MakeArray` need a reference to foo? – BlueRaja - Danny Pflughoeft Mar 22 '11 at 19:44
  • @Quintin ~ Yeah, I kind of just like the generics explicitly stated (when applicable) just so it's clear what I'm pulling out. You're correct though. – Richard Neil Ilagan Mar 22 '11 at 19:45
  • @BlueRaja ~ nah, the array thing is just to illustrate. But, I see your point though! – Richard Neil Ilagan Mar 22 '11 at 19:47

5 Answers5

16
public static U[] MakeArray<T, U>(this IEnumerable<T> @enum, Func<T, U> rule)
{
    return @enum.Select(rule).ToArray();
}
Yuriy Faktorovich
  • 67,283
  • 14
  • 105
  • 142
13

Try the following

U[] MakeArray<T,U>(Func<T, U> projection) where T : IEntity {
  ...
}

When passing lambdas as arguments you generally want the matching parameter to be a delegate. In most cases you should just use the appropriate Action<> or Func<> value. The former for void returning lambdas and the latter for ones that return values.

JaredPar
  • 733,204
  • 149
  • 1,241
  • 1,454
2

You're looking for Action<> and Func<>.

devoured elysium
  • 101,373
  • 131
  • 340
  • 557
2

You can use the Func and Action classes. Check out the LINQ Where function's signature for an example: http://msdn.microsoft.com/en-us/library/bb534803.aspx

David V
  • 11,531
  • 5
  • 42
  • 66
1

You can create extension

public static class MakeArrayExtension
{
    public static U[] MakeArray<T, U>(this IEnumerable<T> collection, Func<T,U> func)
    {
        return collection.Select(func).ToArray();
    }
}

And then use it like this

List<A> foo; // assuming this is populated
string[] bar = foo.MakeArray<A,string>(x => x.StringProperty);
Stecya
  • 22,896
  • 10
  • 72
  • 102