Html.DisplayFor ( or other htmlhelpers ) - asp.net-mvc-3

I have a question that probably is quite basic but I don't really get it. So here it comes.
If I have a view template file ( .cshtml ) and have a codeline like this:
#Html.DisplayFor(m => m.CurrentPage.MainBody)
If I look on the declaration for DisplayFor it looks like this:
public static MvcHtmlString DisplayFor<TModel, TValue>(this HtmlHelper<TModel> html, Expression<Func<TModel, TValue>> expression);
So this is an extension method that takes an Expression parameter but TModel and TValue seems to be generic ( and apparently you can send in a lambda expression to an Expression).
How can the lambda expression here ( m => m.CurrentPage.MainBody ) know what m is?
If I have a lamdba expression like this:
int[] numbers = { 5, 4, 1, 3, 9, 8, 6, 7, 2, 0 };
int oddNumbers = numbers.Count(n => n % 2 == 1);
Then the context for (n => n % 2 == 1) is logic, the lamdba expression is used to evaluate each element in numbers.
But in the case above with #Html.DisplayFor(m => m.CurrentPage.MainBody) what is the context here? What is m referring to? Is that somehow "magically" connected to the #model in this particular view? ( which in this case is#model PageViewModel<ArticlePage> ").
So to sum up, what is m referring to in the expression ( m => m.CurrentPage.MainBody ) ? Is it assumed somehow that it is refering to the model provided in the view via the #model?

How can the lambda expression here ( m => m.CurrentPage.MainBody ) know what m is?
The Html.DisplayFor helper is defined like this:
public static MvcHtmlString DisplayFor<TModel, TValue>(
this HtmlHelper<TModel> html,
Expression<Func<TModel, TValue>> expression
)
{
...
}
Notice how this helper can only be invoked on a strongly typed HtmlHelper<TModel>. If you do not have a strongly typed view with a model you cannot use the Html.DisplayFor helper because Html on which you are invoking this extension method is simply HtmlHelper and not HtmlHelper<TModel>.
So inside your view when you have a model:
#model MyViewModel
The Html property is of type HtmlHelper<MyViewModel> so the DisplayFor helper knows about your model.
Basically when you have a strongly typed view, Html.DisplayFor(m => m.CurrentPage.MainBody) is a shortcut for Html.DisplayFor<MyViewModel, TheTypeOfYourMainBodyProperty>(m => m.CurrentPage.MainBody) where the compiler could infer the generic arguments from the context and you don't need to write them explicitly.

Related

using linq to find if a text field contains any string in a list

im running this in asp.net core v3.1
my question is similar to this question:
How to use Linq to check if a list of strings contains any string in a list
with the specific question relating to the first answer such that
filterTags = ["abc", "cd", "efg"]
var results = db.People
.Where(p => filterTags.Any(tag => p.Tags.Contains(tag)));
so basically saying
give me results from the db of all People
who's Tags field contains any of the filterTags
where Tags = a big text field populated by a bunch of space-delimited tags
This seems straightforward (esp since this has been written before)
but i get an error back
System.InvalidOperationException: The LINQ expression 'DbSet
.Where(p => __filterTags_0
.Any(tag => p.Tags.Contains(tag)))' could not be translated. Either rewrite the query in a form that can be translated, or switch to client evaluation explicitly by inserting a call to either AsEnumerable(), AsAsyncEnumerable(), ToList(), or ToListAsync()
does anyone know what this means or what im doing wrong?
This is not possible with pure EF LINQ. You have to create helper which transforms your search list in Expression Tree.
public static class QueryExtensions
{
private static MethodInfo _containsMethodInfo = typeof(string).GetMethod("Contains")!;
public static IQueryable<T> FilterUsingContains<T>(this IQueryable<T> query, Expression<Func<T, string>> prop, IList<string> items)
{
if (items.Count == 0)
return query.Where(e => 1 == 2);
var param = prop.Parameters[0];
var predicate = items.Select(i =>
(Expression)Expression.Call(prop.Body, _containsMethodInfo, Expression.Constant(i, typeof(string))))
.Aggregate(Expression.OrElse);
var lambda = Expression.Lambda<Func<T, bool>>(predicate, param);
return query.Where(lambda);
}
}
Then you can use this extension in your queries
filterTags = ["abc", "cd", "efg"]
var results = db.People
.Where(p => p.Tags.AsQueryable().FilterUsingContains(t => t, filterTags).Any());
Here is a workaround for you:
using System.Linq;
string[] filterTags = {"abc", "cd", "efg"};
var results = db.People.Where(p => filterTags.Contains(p.Tags)).ToList();

Distinct/GroupBy in WhenAll result Async

I am writing a method in which i am using async prog.
var tasks = new List<Task<List<SomeClass>>>();
tasks.Add(this.Method1());
tasks.Add(this.Method2());
var results = await Task.WhenAll(tasks).ConfigureAwait(false);
i want distinct records from this result. How to achieve that.
currently i have written
return results.SelectMany(s => s).GroupBy(x => x.Name).Select(x => x.FirstOrDefault()).ToList();
But i am not sure with SelectMany, will this give correct result.
SelectMany(s => s) is a "flatten" operation. It takes a sequence of sequences and flattens them to a single sequence.
The LINQ "distinct" operator is called Distinct. If your SomeClass overrides equality to be based on Name, then that's all you need:
return results.SelectMany(s => s).Distinct().ToList();
But if SomeClass doesn't define equality that way, you'll need to do another kind of distinct.
One option is to use the Distinct overload that takes an equality comparer. Then you can pass in an equality comparer that determines equality by Name. To do this, first define an equality comparer:
public sealed class NameEqualityComparer: IEqualityComparer<SomeClass>
{
public int GetHashCode(SomeClass obj) => EqualityComparer<string>.Default.GetHashCode(obj.Name);
public bool Equals(SomeClass x, SomeClass y) => EqualityComparer<string>.Default.Equals(x.Name, y.Name);
}
and then you can invoke the correct overload:
return results.SelectMany(s => s).Distinct(new NameEqualityComparer()).ToList();
I have a library that helps define custom comparers (properly handling all edge cases), which I prefer to use for things like this. With the Nito.Comparers library, you don't need to define a custom NameEqualityComparer; instead, you can define comparers in-line like this:
return results.SelectMany(s => s).Distinct(b => b.EquateBy(x => x.Name)).ToList();
or separately, if desired:
var comparer = EqualityComparerBuilder.For<SomeClass>().EquateBy(x => x.Name);
return results.SelectMany(s => s).Distinct(comparer).ToList();
A completely different option is to add a new "Distinct-By" operator that acts the way you want. This is part of MoreLINQ or you can add it yourself:
public static IEnumerable<T> DistinctBy<T, TKey>(this IEnumerable<T> #this, Func<T, TKey> selector)
{
var keys = new HashSet<TKey>();
foreach (var item in #this)
{
if (keys.Add(selector(item)))
yield return item;
}
}
Then you can use the new operator like this:
return results.SelectMany(s => s).DistinctBy(x => x.Name).ToList();
All of these options are more efficient than grouping.

Can I convert a Func<T, bool> to a Func<U, bool> where T and U are POCO classes where I can map properties of one to the other? If so, how?

I have a scenario where a method will take a predicate of type Func< T, bool > because the type T is the one that is exposed to the outer world, but when actually using that predicate I need that method to call another method that will take in Func< U, bool > where properties of T are mapped to properties of U.
A more concrete example would be:
public IEnumerable<ClientEntity> Search(Func<ClientEntity, bool> predicate)
{
IList<ClientEntity> result = new List<ClientEntity>();
// Somehow translate predicate into Func<Client, bool> which I will call realPredicate.
_dataFacade.Clients.Where(realPredicate).ToList().ForEach(c => result.Add(new ClientEntity() { Id = c.Id, Name = c.Name }));
return result.AsEnumerable();
}
Would that be possible?
Please note that ClientEntity is a POCO class that I defined myself while Client is an Entity Framework class created by the model (DB first).
Thanks!
I once attempted this. It resulted in a not-too-bad working expression tree rewriter when the expression tree consist of the simpler operations (equals, larger-then, smaller-then, etc).
It can be found here.
You can use it as:
Expression<Func<Poco1>> where1 = p => p.Name == "fred";
Expression<Func<Poco2>> where2 = ExpressionRewriter.CastParam<Poco1, Poco2>(where1);
EF doesn't use lambdas - it uses Expression Trees
Func<T, bool> lambda = ( o => o.Name == "fred" );
Expression<Func<T, bool>> expressionTree = ( o => o.Name == "fred" );
Expression Trees are in-memory object graphs that represent a given expression.
As they are just objects, you can create or modify them.
Here's another link: MSDN: How to: Modify Expression Trees
What I ended up doing did not require the use of Expression Trees:
public IEnumerable<ClientEntity> Search(Func<ClientEntity, bool> predicate)
{
IList<ClientEntity> result = new List<ClientEntity>();
Func<Client, bool> realPredicate = (c => predicate(ConvertFromClient(c)));
_dataFacade.Clients.Where(realPredicate).ToList().ForEach(c => result.Add(ConvertFromClient(c)));
return result.AsEnumerable();
}
private static ClientEntity ConvertFromClient(Client client)
{
ClientEntity result = new ClientEntity();
if (client != null)
{
// I actually used AutoMapper from http://automapper.org/ here instead of assigning every property.
result.Id = client.Id;
result.Name = client.Name;
}
return result;
}

How to code an Or extension method

I want to do
var testData = new[] { "aap", "aal", "noot", "mies", "wim", "zus", "jet" };
bool result = testData.Or(s => s.Contains("z"));
but there is no 'Or' method on IEnumerable.
I've tried programming an Or extension method using
public static class extensions
{
public static bool Or<TSource>(this IEnumerable<TSource> sourceCollection, Func<TSource, bool> selector)
{
return sourceCollection.Where(selector).Select(selector).FirstOrDefault();
}
}
Ofcourse, the idea is not to call selector() more often than necessary. The first call evaluating to true determines the result. The problem with my solution is that selector() is called twice on the first item that returns true. I imagine this is because of the call to Select().
How do I fix this?
var testData = new[] { "aap", "aal", "noot", "mies", "wim", "zus", "jet"};
bool result = testData.Any(s => s.Contains("z"));
This will stop evaluation at the first match, as you want.
I'm not sure I understood your problem but does the Linq extension method Any do what you're trying to achieve ?

LINQ equivalent of foreach for IEnumerable<T>

I'd like to do the equivalent of the following in LINQ, but I can't figure out how:
IEnumerable<Item> items = GetItems();
items.ForEach(i => i.DoStuff());
What is the real syntax?
There is no ForEach extension for IEnumerable; only for List<T>. So you could do
items.ToList().ForEach(i => i.DoStuff());
Alternatively, write your own ForEach extension method:
public static void ForEach<T>(this IEnumerable<T> enumeration, Action<T> action)
{
foreach(T item in enumeration)
{
action(item);
}
}
Fredrik has provided the fix, but it may be worth considering why this isn't in the framework to start with. I believe the idea is that the LINQ query operators should be side-effect-free, fitting in with a reasonably functional way of looking at the world. Clearly ForEach is exactly the opposite - a purely side-effect-based construct.
That's not to say this is a bad thing to do - just thinking about the philosophical reasons behind the decision.
Update 7/17/2012: Apparently as of C# 5.0, the behavior of foreach described below has been changed and "the use of a foreach iteration variable in a nested lambda expression no longer produces unexpected results." This answer does not apply to C# ≥ 5.0.
#John Skeet and everyone who prefers the foreach keyword.
The problem with "foreach" in C# prior to 5.0, is that it is inconsistent with how the equivalent "for comprehension" works in other languages, and with how I would expect it to work (personal opinion stated here only because others have mentioned their opinion regarding readability). See all of the questions concerning "Access to modified closure"
as well as "Closing over the loop variable considered harmful". This is only "harmful" because of the way "foreach" is implemented in C#.
Take the following examples using the functionally equivalent extension method to that in #Fredrik Kalseth's answer.
public static class Enumerables
{
public static void ForEach<T>(this IEnumerable<T> #this, Action<T> action)
{
foreach (T item in #this)
{
action(item);
}
}
}
Apologies for the overly contrived example. I'm only using Observable because it's not entirely far fetched to do something like this. Obviously there are better ways to create this observable, I am only attempting to demonstrate a point. Typically the code subscribed to the observable is executed asynchronously and potentially in another thread. If using "foreach", this could produce very strange and potentially non-deterministic results.
The following test using "ForEach" extension method passes:
[Test]
public void ForEachExtensionWin()
{
//Yes, I know there is an Observable.Range.
var values = Enumerable.Range(0, 10);
var observable = Observable.Create<Func<int>>(source =>
{
values.ForEach(value =>
source.OnNext(() => value));
source.OnCompleted();
return () => { };
});
//Simulate subscribing and evaluating Funcs
var evaluatedObservable = observable.ToEnumerable().Select(func => func()).ToList();
//Win
Assert.That(evaluatedObservable,
Is.EquivalentTo(values.ToList()));
}
The following fails with the error:
Expected: equivalent to < 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 >
But was: < 9, 9, 9, 9, 9, 9, 9, 9, 9, 9 >
[Test]
public void ForEachKeywordFail()
{
//Yes, I know there is an Observable.Range.
var values = Enumerable.Range(0, 10);
var observable = Observable.Create<Func<int>>(source =>
{
foreach (var value in values)
{
//If you have resharper, notice the warning
source.OnNext(() => value);
}
source.OnCompleted();
return () => { };
});
//Simulate subscribing and evaluating Funcs
var evaluatedObservable = observable.ToEnumerable().Select(func => func()).ToList();
//Fail
Assert.That(evaluatedObservable,
Is.EquivalentTo(values.ToList()));
}
You could use the FirstOrDefault() extension, which is available for IEnumerable<T>. By returning false from the predicate, it will be run for each element but will not care that it doesn't actually find a match. This will avoid the ToList() overhead.
IEnumerable<Item> items = GetItems();
items.FirstOrDefault(i => { i.DoStuff(); return false; });
Keep your Side Effects out of my IEnumerable
I'd like to do the equivalent of the following in LINQ, but I can't figure out how:
As others have pointed out here and abroad LINQ and IEnumerable methods are expected to be side-effect free.
Do you really want to "do something" to each item in the IEnumerable? Then foreach is the best choice. People aren't surprised when side-effects happen here.
foreach (var i in items) i.DoStuff();
I bet you don't want a side-effect
However in my experience side-effects are usually not required. More often than not there is a simple LINQ query waiting to be discovered accompanied by a StackOverflow.com answer by either Jon Skeet, Eric Lippert, or Marc Gravell explaining how to do what you want!
Some examples
If you are actually just aggregating (accumulating) some value then you should consider the Aggregate extension method.
items.Aggregate(initial, (acc, x) => ComputeAccumulatedValue(acc, x));
Perhaps you want to create a new IEnumerable from the existing values.
items.Select(x => Transform(x));
Or maybe you want to create a look-up table:
items.ToLookup(x, x => GetTheKey(x))
The list (pun not entirely intended) of possibilities goes on and on.
I took Fredrik's method and modified the return type.
This way, the method supports deferred execution like other LINQ methods.
EDIT: If this wasn't clear, any usage of this method must end with ToList() or any other way to force the method to work on the complete enumerable. Otherwise, the action would not be performed!
public static IEnumerable<T> ForEach<T>(this IEnumerable<T> enumeration, Action<T> action)
{
foreach (T item in enumeration)
{
action(item);
yield return item;
}
}
And here's the test to help see it:
[Test]
public void TestDefferedExecutionOfIEnumerableForEach()
{
IEnumerable<char> enumerable = new[] {'a', 'b', 'c'};
var sb = new StringBuilder();
enumerable
.ForEach(c => sb.Append("1"))
.ForEach(c => sb.Append("2"))
.ToList();
Assert.That(sb.ToString(), Is.EqualTo("121212"));
}
If you remove the ToList() in the end, you will see the test failing since the StringBuilder contains an empty string. This is because no method forced the ForEach to enumerate.
So many answers, yet ALL fail to pinpoint one very significant problem with a custom generic ForEach extension: Performance! And more specifically, memory usage and GC.
Consider the sample below. Targeting .NET Framework 4.7.2 or .NET Core 3.1.401, configuration is Release and platform is Any CPU.
public static class Enumerables
{
public static void ForEach<T>(this IEnumerable<T> #this, Action<T> action)
{
foreach (T item in #this)
{
action(item);
}
}
}
class Program
{
private static void NoOp(int value) {}
static void Main(string[] args)
{
var list = Enumerable.Range(0, 10).ToList();
for (int i = 0; i < 1000000; i++)
{
// WithLinq(list);
// WithoutLinqNoGood(list);
WithoutLinq(list);
}
}
private static void WithoutLinq(List<int> list)
{
foreach (var item in list)
{
NoOp(item);
}
}
private static void WithLinq(IEnumerable<int> list) => list.ForEach(NoOp);
private static void WithoutLinqNoGood(IEnumerable<int> enumerable)
{
foreach (var item in enumerable)
{
NoOp(item);
}
}
}
At a first glance, all three variants should perform equally well. However, when the ForEach extension method is called many, many times, you will end up with garbage that implies a costly GC. In fact, having this ForEach extension method on a hot path has been proven to totally kill performance in our loop-intensive application.
Similarly, the weakly typed foreach loop will also produce garbage, but it will still be faster and less memory-intensive than the ForEach extension (which also suffers from a delegate allocation).
Strongly typed foreach: Memory usage
Weakly typed foreach: Memory usage
ForEach extension: Memory usage
Analysis
For a strongly typed foreach the compiler is able to use any optimized enumerator (e.g. value based) of a class, whereas a generic ForEach extension must fall back to a generic enumerator which will be allocated on each run. Furthermore, the actual delegate will also imply an additional allocation.
You would get similar bad results with the WithoutLinqNoGood method. There, the argument is of type IEnumerable<int> instead of List<int> implying the same type of enumerator allocation.
Below are the relevant differences in IL. A value based enumerator is certainly preferable!
IL_0001: callvirt instance class
[mscorlib]System.Collections.Generic.IEnumerator`1<!0>
class [mscorlib]System.Collections.Generic.IEnumerable`1<!!T>::GetEnumerator()
vs
IL_0001: callvirt instance valuetype
[mscorlib]System.Collections.Generic.List`1/Enumerator<!0>
class [mscorlib]System.Collections.Generic.List`1<int32>::GetEnumerator()
Conclusion
The OP asked how to call ForEach() on an IEnumerable<T>. The original answer clearly shows how it can be done. Sure you can do it, but then again; my answer clearly shows that you shouldn't.
Verified the same behavior when targeting .NET Core 3.1.401 (compiling with Visual Studio 16.7.2).
If you want to act as the enumeration rolls you should yield each item.
public static class EnumerableExtensions
{
public static IEnumerable<T> ForEach<T>(this IEnumerable<T> enumeration, Action<T> action)
{
foreach (var item in enumeration)
{
action(item);
yield return item;
}
}
}
There is an experimental release by Microsoft of Interactive Extensions to LINQ (also on NuGet, see RxTeams's profile for more links). The Channel 9 video explains it well.
Its docs are only provided in XML format. I have run this documentation in Sandcastle to allow it to be in a more readable format. Unzip the docs archive and look for index.html.
Among many other goodies, it provides the expected ForEach implementation. It allows you to write code like this:
int[] numbers = { 1, 2, 3, 4, 5, 6, 7, 8 };
numbers.ForEach(x => Console.WriteLine(x*x));
According to PLINQ (available since .Net 4.0), you can do an
IEnumerable<T>.AsParallel().ForAll()
to do a parallel foreach loop on an IEnumerable.
The purpose of ForEach is to cause side effects.
IEnumerable is for lazy enumeration of a set.
This conceptual difference is quite visible when you consider it.
SomeEnumerable.ForEach(item=>DataStore.Synchronize(item));
This wont execute until you do a "count" or a "ToList()" or something on it.
It clearly is not what is expressed.
You should use the IEnumerable extensions for setting up chains of iteration, definining content by their respective sources and conditions. Expression Trees are powerful and efficient, but you should learn to appreciate their nature. And not just for programming around them to save a few characters overriding lazy evaluation.
Many people mentioned it, but I had to write it down. Isn't this most clear/most readable?
IEnumerable<Item> items = GetItems();
foreach (var item in items) item.DoStuff();
Short and simple(st).
Now we have the option of...
ParallelOptions parallelOptions = new ParallelOptions();
parallelOptions.MaxDegreeOfParallelism = 4;
#if DEBUG
parallelOptions.MaxDegreeOfParallelism = 1;
#endif
Parallel.ForEach(bookIdList, parallelOptions, bookID => UpdateStockCount(bookID));
Of course, this opens up a whole new can of threadworms.
ps (Sorry about the fonts, it's what the system decided)
As numerous answers already point out, you can easily add such an extension method yourself. However, if you don't want to do that, although I'm not aware of anything like this in the BCL, there's still an option in the System namespace, if you already have a reference to Reactive Extension (and if you don't, you should have):
using System.Reactive.Linq;
items.ToObservable().Subscribe(i => i.DoStuff());
Although the method names are a bit different, the end result is exactly what you're looking for.
ForEach can also be Chained, just put back to the pileline after the action. remain fluent
Employees.ForEach(e=>e.Act_A)
.ForEach(e=>e.Act_B)
.ForEach(e=>e.Act_C);
Orders //just for demo
.ForEach(o=> o.EmailBuyer() )
.ForEach(o=> o.ProcessBilling() )
.ForEach(o=> o.ProcessShipping());
//conditional
Employees
.ForEach(e=> { if(e.Salary<1000) e.Raise(0.10);})
.ForEach(e=> { if(e.Age >70 ) e.Retire();});
An Eager version of implementation.
public static IEnumerable<T> ForEach<T>(this IEnumerable<T> enu, Action<T> action)
{
foreach (T item in enu) action(item);
return enu; // make action Chainable/Fluent
}
Edit: a Lazy version is using yield return, like this.
public static IEnumerable<T> ForEachLazy<T>(this IEnumerable<T> enu, Action<T> action)
{
foreach (var item in enu)
{
action(item);
yield return item;
}
}
The Lazy version NEEDs to be materialized, ToList() for example, otherwise, nothing happens. see below great comments from ToolmakerSteve.
IQueryable<Product> query = Products.Where(...);
query.ForEachLazy(t => t.Price = t.Price + 1.00)
.ToList(); //without this line, below SubmitChanges() does nothing.
SubmitChanges();
I keep both ForEach() and ForEachLazy() in my library.
Inspired by Jon Skeet, I have extended his solution with the following:
Extension Method:
public static void Execute<TSource, TKey>(this IEnumerable<TSource> source, Action<TKey> applyBehavior, Func<TSource, TKey> keySelector)
{
foreach (var item in source)
{
var target = keySelector(item);
applyBehavior(target);
}
}
Client:
var jobs = new List<Job>()
{
new Job { Id = "XAML Developer" },
new Job { Id = "Assassin" },
new Job { Id = "Narco Trafficker" }
};
jobs.Execute(ApplyFilter, j => j.Id);
.
.
.
public void ApplyFilter(string filterId)
{
Debug.WriteLine(filterId);
}
This "functional approach" abstraction leaks big time. Nothing on the language level prevents side effects. As long as you can make it call your lambda/delegate for every element in the container - you will get the "ForEach" behavior.
Here for example one way of merging srcDictionary into destDictionary (if key already exists - overwrites)
this is a hack, and should not be used in any production code.
var b = srcDictionary.Select(
x=>
{
destDictionary[x.Key] = x.Value;
return true;
}
).Count();
MoreLinq has IEnumerable<T>.ForEach and a ton of other useful extensions. It's probably not worth taking the dependency just for ForEach, but there's a lot of useful stuff in there.
https://www.nuget.org/packages/morelinq/
https://github.com/morelinq/MoreLINQ
I respectually disagree with the notion that link extension methods should be side-effect free (not only because they aren't, any delegate can perform side effects).
Consider the following:
public class Element {}
public Enum ProcessType
{
This = 0, That = 1, SomethingElse = 2
}
public class Class1
{
private Dictionary<ProcessType, Action<Element>> actions =
new Dictionary<ProcessType,Action<Element>>();
public Class1()
{
actions.Add( ProcessType.This, DoThis );
actions.Add( ProcessType.That, DoThat );
actions.Add( ProcessType.SomethingElse, DoSomethingElse );
}
// Element actions:
// This example defines 3 distict actions
// that can be applied to individual elements,
// But for the sake of the argument, make
// no assumption about how many distict
// actions there may, and that there could
// possibly be many more.
public void DoThis( Element element )
{
// Do something to element
}
public void DoThat( Element element )
{
// Do something to element
}
public void DoSomethingElse( Element element )
{
// Do something to element
}
public void Apply( ProcessType processType, IEnumerable<Element> elements )
{
Action<Element> action = null;
if( ! actions.TryGetValue( processType, out action ) )
throw new ArgumentException("processType");
foreach( element in elements )
action(element);
}
}
What the example shows is really just a kind of late-binding that allows one invoke one of many possible actions having side-effects on a sequence of elements, without having to write a big switch construct to decode the value that defines the action and translate it into its corresponding method.
To stay fluent one can use such a trick:
GetItems()
.Select(i => new Action(i.DoStuf)))
.Aggregate((a, b) => a + b)
.Invoke();
For VB.NET you should use:
listVariable.ForEach(Sub(i) i.Property = "Value")
Yet another ForEach Example
public static IList<AddressEntry> MapToDomain(IList<AddressModel> addresses)
{
var workingAddresses = new List<AddressEntry>();
addresses.Select(a => a).ToList().ForEach(a => workingAddresses.Add(AddressModelMapper.MapToDomain(a)));
return workingAddresses;
}

Resources