I have a tree structure that has a Traverse function, the traverse function takes an action that it will perform on each layer:
public void Traverse(Action<ILayer> action)
{
action(this);
foreach (var child in children)
child.Traverse(action);
}
However I find myself about to write code like this:
private List<ILayer> filteredList = new List<ILayer>();
private string condition;
void AddLayerIf(ILayer layer)
{
if (layer.Type == "condition")
filteredList.Add(layer);
}
void main()
{
filteredList.Clear();
condition = "Image";
rootLayer.Traverse(AddLayerIf);
List<ILayer> allImageLayers = filteredList;
}
And that feels totally wrong. Could I send the two variables as parameters instead of having them global? or is there an even better trick I am missing? I started to write the action as a lambda but not sure that is right either
I did some lambda which feels much better! Any advice on improving welcome :)
ILayer imageLayers= new ImageFolder("Images");
rootLayer.Traverse(
(ILayer x) =>
{
if (x.Type == "Image")
imageLayers.AddChild(x);
});
Related
I had to write my own foreach method for various reasons. This resembles an IEnumerable foreach statement:
public void ForEachEdge(in Vertex vertex, Action<Edge> callback)
{
var edge = GetEdge(vertex.BaseEdgeIndex);
do
{
callback.Invoke(edge);
edge = GetEdge(edge.GetNext(vertex.Index));
} while (edge.Index != vertex.BaseEdgeIndex);
}
I'm using it like so but I wish to be able to "break" out of the entire loop:
ForEachEdge(edge.Vertex0Index, (e) =>
{
if (inEdge.AreConnectingSameVertices(e))
{
// break out of inner while loop here ...
}
});
What would be best practice to break?
Return a status value?
Pass a "ref bool stopEnumerating" parameter in? (requires class instance to wrap it in, right?)
Your thoughts ...
I'm mostly concerned about what end users (developers) would expect in such a case.
the ref parameter method won't be as clean as a return value indicating continuation status. You would have to switch to a Func<Edge, bool>
Func<Edge, bool> callback;
...
if (callback.Invoke(edge)) {
/// do your break logic
}
I decided that (for now) I'll go with a Predicate<> rather than Action<>:
public void ForEachEdge(in Vertex vertex, Predicate<Edge> callback)
{
var edge = GetEdge(vertex.BaseEdgeIndex);
do
{
if (callback.Invoke(edge))
break;
edge = GetEdge(edge.GetNextRadialEdgeIndex(vertex.Index));
} while (edge.IsValid && edge.Index != vertex.BaseEdgeIndex);
}
Which makes the user's code look like this:
ForEachEdge(edge.Vertex0Index, e =>
{
if (inEdge.AreConnectingSameVertices(e))
{
// found it, do something, then exit loop
return true;
}
// continue with next item
return false;
});
The nicest thing about this solution: both Predicate<> and Action<> variants can exist side-by-side! User either returns true/false from the predicate, or does not return anything and thus uses the Action<> version, like so:
ForEachEdge(edge.Vertex0Index, e =>
{
if (inEdge.AreConnectingSameVertices(e))
{
// do stuff
}
});
Purrfect! :)
I would like to be able to describe some actions as function calls represented in a datastructure. Then I would like to be able to loop through the data structure and call the functions.
This pseudo-code describes what I would like to achieve:
static void Main(string[] args)
{
Action[] actions = new Action[]
{
new Action(DoAction1(5)),
new Action(DoAction1(7)),
new Action(DoAction2("100201")),
};
foreach (Action action in actions)
{
action.<Run the action function>;
}
}
public static void DoAction1(int x)
{
}
public static void DoAction2(string x)
{
}
It kind of looks like delegates, but not quite.
Any ideas on how to achieve this?
This is what you're looking for?
Action[] actions = new Action[]
{
new Action(()=>DoAction1(5)),
new Action(()=>DoAction1(7)),
new Action(()=>DoAction2("100201"))
};
foreach (Action action in actions)
{
action();
}
The Action class in .net allows you to directly assign lambdas
var actions = new List<Action>
{
() => DoAction1(5),
() => DoAction1(7),
() => DoAction2("100201"),
};
then executing an array of actions can be done like :-
actions.ForEach(a => a());
then you can add more actions to the list
actions.Add(() => DoAction2("blah blah"));
may be you can use reflection
var methodNames = typeof(MyType).GetMethods(BindingFlags.Public |
BindingFlags.Static)
.Select(x => x.Name)
.Distinct()
.OrderBy(x => x);
OR
foreach (var property in yourObject.GetType().GetProperties())
{
if (property.PropertyType.GetInterfaces().Contains(typeof(IEnumerable)))
{
foreach (var item in (IEnumerable)property.GetValue(yourObject, null))
{
//do stuff
}
}
}
Since you seem not to want to use the Action class, you can check out the SharpByte codebase, specifically the SharpByte.Dynamic namespace. It allows evaluating statements and executing scripts with just a single method call, like this:
someContextObject.Execute("[executable code here]");
However, you can use it another way which may be what you're looking for. When you execute one of those dynamic compilation/execution extension methods, here's what's actually happening (paraphrased):
IExecutable executable = ExecutableFactory.Default.GetExecutable(ExecutableType.Script, "[source code here]", optionalListOfParameterNames, optionalListOfNamespaces);
If you wanted to evaluate an expression/function instead of run multiple-lined statements, you'd use ExecutableType.Expression . The main point is that you can keep a reference around to an IExecutable object and run it as many times as you like, passing different parameter values each time. You can also copy IExecutable objects freely using the .Copy() method of each; they are designed to be thread-safe but lightweight, and references or copies could thus be placed in a data structure for further (re)use. This post explains a bit more.
I'm looking for a way to pass through items with certain logic. The most obvious answer probably would be to use .Select which is sort of works with most of the cases but I have a special case and the question can be actually rephrased as how to call a certain method after an item is consumed by all subscribers?
I was thinking about an extension looking like this PassThrough(this IObservable<TSource> obj, Action<TSource, IObserver<TResult>> selector) and I would use it in the following way
.PassThrough((source, observer) => {
if(source != null) {
using(var result = new Result(source)) {
observer.OnNext(result);
}
}
});
The most important part of this is calling .Dispose for the result object after the object is passed to OnNext in other words after it is consumed by subscribers. I didn't find such extension method. Could somebody give an example how to achieve it with existing Rx.NET API or how to create an extension which will do this, presuming it is possible?
What you are looking for is probably Observable.Create via an extension method. In your case it may look like the following:
public static IObservable<Result> PassThrough(this IObservable<TSource> obj, T source) {
return Observable.Create(observer => {
if(source != null) {
using(var result = new Result(source)) {
observer.OnNext(result);
observer.OnCompleted();
}
} else {
observer.OnError(Some Error);
...
}
})
}
Obviously depending on whether you want to keep the stream going, you would omit the OnCompleted() call.
See here for more information on usage of Observable.Create:
http://introtorx.com/Content/v1.0.10621.0/04_CreatingObservableSequences.html#CreationOfObservables
Going from a lambda to an Expression is easy using a method call...
public void GimmeExpression(Expression<Func<T>> expression)
{
((MemberExpression)expression.Body).Member.Name; // "DoStuff"
}
public void SomewhereElse()
{
GimmeExpression(() => thing.DoStuff());
}
But I would like to turn the Func in to an expression, only in rare cases...
public void ContainTheDanger(Func<T> dangerousCall)
{
try
{
dangerousCall();
}
catch (Exception e)
{
// This next line does not work...
Expression<Func<T>> DangerousExpression = dangerousCall;
var nameOfDanger =
((MemberExpression)dangerousCall.Body).Member.Name;
throw new DangerContainer(
"Danger manifested while " + nameOfDanger, e);
}
}
public void SomewhereElse()
{
ContainTheDanger(() => thing.CrossTheStreams());
}
The line that does not work gives me the compile-time error Cannot implicitly convert type 'System.Func<T>' to 'System.Linq.Expressions.Expression<System.Func<T>>'. An explicit cast does not resolve the situation. Is there a facility to do this that I am overlooking?
Ooh, it's not easy at all. Func<T> represents a generic delegate and not an expression. If there's any way you could do so (due to optimizations and other things done by the compiler, some data might be thrown away, so it might be impossible to get the original expression back), it'd be disassembling the IL on the fly and inferring the expression (which is by no means easy). Treating lambda expressions as data (Expression<Func<T>>) is a magic done by the compiler (basically the compiler builds an expression tree in code instead of compiling it to IL).
Related fact
This is why languages that push lambdas to the extreme (like Lisp) are often easier to implement as interpreters. In those languages, code and data are essentially the same thing (even at run time), but our chip cannot understand that form of code, so we have to emulate such a machine by building an interpreter on top of it that understands it (the choice made by Lisp like languages) or sacrificing the power (code will no longer be exactly equal to data) to some extent (the choice made by C#). In C#, the compiler gives the illusion of treating code as data by allowing lambdas to be interpreted as code (Func<T>) and data (Expression<Func<T>>) at compile time.
private static Expression<Func<T, bool>> FuncToExpression<T>(Func<T, bool> f)
{
return x => f(x);
}
What you probably should do, is turn the method around. Take in an Expression>, and compile and run. If it fails, you already have the Expression to look into.
public void ContainTheDanger(Expression<Func<T>> dangerousCall)
{
try
{
dangerousCall().Compile().Invoke();;
}
catch (Exception e)
{
// This next line does not work...
var nameOfDanger =
((MemberExpression)dangerousCall.Body).Member.Name;
throw new DangerContainer(
"Danger manifested while " + nameOfDanger, e);
}
}
public void SomewhereElse()
{
ContainTheDanger(() => thing.CrossTheStreams());
}
Obviously you need to consider the performance implications of this, and determine if it is something that you really need to do.
If you sometimes need an expression and sometimes need a delegate, you have 2 options:
have different methods (1 for each)
always accept the Expression<...> version, and just .Compile().Invoke(...) it if you want a delegate. Obviously this has cost.
NJection.LambdaConverter is a library that converts a delegate to an expression
public class Program
{
private static void Main(string[] args) {
var lambda = Lambda.TransformMethodTo<Func<string, int>>()
.From(() => Parse)
.ToLambda();
}
public static int Parse(string value) {
return int.Parse(value)
}
}
You can go the other way via the .Compile() method however - not sure if this is useful for you:
public void ContainTheDanger<T>(Expression<Func<T>> dangerousCall)
{
try
{
var expr = dangerousCall.Compile();
expr.Invoke();
}
catch (Exception e)
{
Expression<Func<T>> DangerousExpression = dangerousCall;
var nameOfDanger = ((MethodCallExpression)dangerousCall.Body).Method.Name;
throw new DangerContainer("Danger manifested while " + nameOfDanger, e);
}
}
public void SomewhereElse()
{
var thing = new Thing();
ContainTheDanger(() => thing.CrossTheStreams());
}
Expression<Func<T>> ToExpression<T>(Func<T> call)
{
MethodCallExpression methodCall = call.Target == null
? Expression.Call(call.Method)
: Expression.Call(Expression.Constant(call.Target), call.Method);
return Expression.Lambda<Func<T>>(methodCall);
}
JB Evain from the Cecil Mono team is doing some progress to enable this
http://evain.net/blog/articles/2009/04/22/converting-delegates-to-expression-trees
Change
// This next line does not work...
Expression<Func<T>> DangerousExpression = dangerousCall;
To
// This next line works!
Expression<Func<T>> DangerousExpression = () => dangerousCall();
I can't explain an issue I've run across. Basically I get a different answer if I use lambda syntax in a foreach loop than if I use it in a for loop. In the code below I register a delegate in a "dispatcher" class. I then later wrap the delegate on the way out in another delegate and return a list of these wrapped delegates. I then execute them. The expected output of executing the wrapped function list is 1,2. However I don't see that when I combine a lambda and a foreach loop.
This is not the code that is causing the problem, but the simplest case I could make to reproduce it. I would prefer not to discuss use cases of this, I'm more curious as to why I get behavior I'm not expecting. If I use the foreach loop below with the lambda syntax it fails. If I use the new Action() syntax and a foreach it works, if I use the lambda syntax in a for loop it works. Can anyone explain what is going on here. This has me really stumped.
public class Holder
{
public Holder(int ID, Dispatcher disp)
{
this.ID = ID;
disp.Register(Something);
}
public int ID { get; set; }
private void Something(int test) { Console.WriteLine(ID.ToString()); }
}
public class Dispatcher
{
List<Action<int>> m_Holder = new List<Action<int>>();
public void Register(Action<int> func)
{
m_Holder.Add(func);
}
public List<Action<int>> ReturnWrappedList()
{
List<Action<int>> temp = new List<Action<int>>();
//for (int i = 0; i < m_Holder.Count; i++) //Works - gives 1, 2
//{
// var action = m_Holder[i];
// temp.Add(p => action(p));
//}
foreach (var action in m_Holder)
{
temp.Add(p => action(p)); //Fails - gives 2,2
//temp.Add(new Action<int>(action)); Works - gives 1,2
}
return temp;
}
}
class Program
{
static void Main(string[] args)
{
var disp = new Dispatcher();
var hold1 = new Holder(1, disp);
var hold2 = new Holder(2, disp);
disp.ReturnWrappedList().ForEach(p => p(1));
}
}
This is the infamous "closing over the loop variable" gotcha.
Closing over the loop variable considered harmful (and part two)
Have you tried:
foreach (var action in m_Holder)
{
var a = action;
temp.Add(p => a(p));
}
This is the classic issue of a captured closure with a scope that isn't what you expect. In the foreach, the action has outer scope, so the execution captures the last value of the loop. In the for case, you create the action in inner scope, so the closure is over the local value at each iteration.