views:

2259

answers:

3

hey guys.

Firstly I can't get my head around the functional / Lambda aspects of .NET 3.5. I use these features everyday in LINQ, but my problem is understanding the implementation, and what they really mean (Lambda? System.Func? etc etc)

With this in mind, how would the following be achieved:

As an example, I'd like to have an Extension method for List(Of T) which sets the properties of all the objects in the List to a certain value, and returns the updated List(Of T). It would be called like this:

VB:

 Dim someList As List(Of TextBox) =  (New List(Of TextBox)).UpdateExtension(Function(txtb) txtb.Text = "something")

C#:

List<TextBox> someList = (new List<TextBox>()).UpdateExtension(txtb => txtb.Text = "something");

What would the Extension method look like, in both VB and C#?

i.e:

 <Extension()> _
 Public Function UpdateExtension(Of T)(ByVal source As List(Of T), ByVal predicate As ??) As List(Of T)
        '??
 End Function

cheers!

EDIT

As many have pointed out, the above can be achieved, more or less, with .ForEach(). But my interest is in understading how something like .ForEach() is implemented, i.e. I'm interested in the implementation of the solution for the above problem.

+2  A: 

With the exception that you would modify the list in place rather than returning a new one, this is just a .ForEach() call.

To really understand how this works, think more in terms of IEnumerables than Lists. Think about why the two expressions below have the same result and why the latter is generally preferable:

MyEnumerable.Count() > 2
MyEnumerable.Skip(2).Any()

To help accomplish this, re-implement some standard IEnumerable extensions using C#'s yield keyword. Once you really get why the 2nd performs better you should be in good shape.

As for the different basic delegate types, you just need to learn them. Think of Func as your basic common delegate, where you specify the argument type and return type for the generic type parameters. Then think of Action as a special case of Func where the return type is void and Predicate as a special case where the return type is bool.

Joel Coehoorn
+ 1 hey Joel, thanks for the heads up on the different delegates types. Its useful to just have it explained in plain english. I see what you mean with .ForEach(), but anyway you could show me how exactly its implemented? I kinda just need to see it to begin to understand it you know, cheers
andy
+1  A: 

Really you're miking and matching extension methods here. It's almost a combination of Select and ForEach. It appears you want a method that will allow you to both modify elements of a list and return the original enumeration. The following should do the trick for you.

VB.Net

<Extension()> _
Public Function UpdateExtension(Of T)(ByVal source As IEnumerable(Of T), ByVal del As Action(Of T)) As IEnumerable(Of T)
  For Each cur in source
    del(cur)
  Next
  Return source
End Function

C#

public static IEnumerable<T> UpdateExtension<T>(this IEnumerable<T> source, Action<T> del) {
  foreach ( var cur in source ) {
    del(cur);
  }
  return source;
}
JaredPar
+ 1 hmm...interesting. Excuse my ignorance, so you're saying, by expressing a lambda expression i.e. "obj=>obj.date = Now" in the Method call, all I have to do in the implementation is just execute that delegate/action/func?
andy
@andy yes. This version will execute it once per object in the collection.
JaredPar
Shouldn't that be "yield return" for an IEnumerable?
Benjol
@Benjol, no. To do so would create a return of a group of IEnumerable. I wanted to return a single IEnumerable
JaredPar
+1  A: 

Extensions are implemented in a static class by static methods that take the target of the extension as the first parameter preceded by the this keyword. To implement your example I would do:

public static class ListBoxExtensions
{
  public static List<TextBox> SetToValue(this List<TextBox> txtBoxes, string sValue)
  {
    txtBoxes.ForEach(txtBox => txtBox.Text = sValue);
    return txtBoxes;
  }
}

and to use this on a Windows form with 3 textboxes:

private void Form1_Load(object sender, EventArgs e)
{
  List<TextBox> boxes = new List<TextBox>
                        {
                          textBox1,
                          textBox2,
                          textBox3
                        }.SetToValue("Hello");
}

Sorry - don't speak VB.

Hope this helps.

haha, no problem, I've only just started C#. Cool, I wasn't aware of ForEach, but I was kinda more interested in how, as an exmaple, something like ForEach is implemented
andy