I have Expression<Action<T>> where Action is call of function, but function result is not used. Let's consider the following code sample:
using System;
using System.Linq.Expressions;
namespace ConsoleApp
{
class Program
{
public class MyArg
{
public int Data { get; set; }
}
public class MyExecutor
{
public bool Executed { get; set; }
public int MyMethod(int simpleArg, MyArg complexArg)
{
int result = simpleArg + complexArg.Data;
this.Executed = true;
return result;
}
}
static void Main(string[] args)
{
Expression<Action<MyExecutor>> expr = t => t.MyMethod(2, new MyArg { Data = 3 });
var executor = new MyExecutor();
Action<MyExecutor> action = expr.Compile();
action(executor);
Console.WriteLine(executor.Executed); // true
}
}
}
There can lot of different actions, with different number of arguments. In all cases I have only such kind of expr which always calls a function and that function always returns the same type, in my example above it is int.
I need to have something like this:
static Expression<Func<MyExecutor, int>> ToExpressionOfFunc(Expression<Action<MyExecutor>> expr)
{
// TODO
throw new NotImplementedException();
}
to be able to make a call like this:
Expression<Func<MyExecutor, int>> funcExpr = ToExpressionOfFunc(expr);
Func<MyExecutor, int> func = funcExpr.Compile();
int result = func(executor);
Console.WriteLine(result); // should print 5
I have a feeling that this should be possible but have no ideas where to start from. I see in debug that there is an expr.Body.Method with desired ReturnType of Int32, but not clear how to extract it properly to the new Expression<Func>.
It's simple, just create a new Expression<Func<MyExecutor, int>> using the body and parameters from the existing expression:
static Expression<Func<MyExecutor, int>> ToExpressionOfFunc(Expression<Action<MyExecutor>> expr)
{
return Expression.Lambda<Func<MyExecutor, int>>(expr.Body, expr.Parameters);
}
Note that this throws an exception if expr is not of return type int.
Related
I'm building a generic interface to expose selected string properties out of a class, and then I want to search for a text inside every one of those fields, to check if it's a match.
Here's my IFieldExposer interface:
using System;
using System.Collections.Generic;
public interface IFieldExposer<T>
{
IEnumerable<Func<T, string>> GetFields();
}
Now, I implement it like this in my DataClass to expose the properties I would like to iterate. Note that I'm also exposing a property from my ChildClass:
using System;
using System.Collections.Generic;
class DataClass : IFieldExposer<DataClass>
{
public string PropertyOne { get; set; }
public string PropertyTwo { get; set; }
public ChildClass Child { get; set; }
public IEnumerable<Func<DataClass, string>> GetFields()
{
return new List<Func<DataClass, string>>
{
a => a.PropertyOne,
b => b.Child.PropertyThree
};
}
}
class ChildClass
{
public string PropertyThree { get; set; }
}
I've also created extension methods for IFieldExposer<T> because I want to keep it simple and be able to simply call obj.Match(text, ignoreCase) everywhere else in my code. This method should tell me if my object is a match for my text. Here's the code for the ExtensionClass, which isn't working as expected:
using System;
using System.Linq.Expressions;
using System.Reflection;
public static class ExtensionClass
{
public static bool Match<T>(this IFieldExposer<T> obj, string text, bool ignoreCase)
{
Func<bool> expression = Expression.Lambda<Func<bool>>(obj.CreateExpressionTree(text, ignoreCase)).Compile();
return expression();
}
private static Expression CreateExpressionTree<T>(this IFieldExposer<T> obj, string text, bool ignoreCase)
{
MethodInfo containsMethod = typeof(string).GetMethod("Contains", new Type[] { typeof(string) });
var exposedFields = obj.GetFields();
if (ignoreCase)
{
// How should I do convert these to lower too?
// exposedFields = exposedFields.Select(e => e.???.ToLower());
text = text.ToLower();
}
Expression textExp = Expression.Constant(text);
Expression orExpressions = Expression.Constant(false);
foreach (var field in exposedFields)
{
//How should I call the contains method on the string field?
Expression fieldExpression = Expression.Lambda<Func<string>>(Expression.Call(Expression.Constant(obj), field.Method)); //this doesn't work
Expression contains = Expression.Call(fieldExpression, containsMethod, textExp);
orExpressions = Expression.Or(orExpressions, contains);
}
return orExpressions;
}
}
Please check the comments in the code above. I would like to know how to convert all my string properties to lowercase (if desired) and how to call string.Contains in each one of them. I get this error when I create my fieldExpression:
Method 'System.String <GetFields>b__12_0(DataClass)' declared on type 'DataClass+<>c' cannot be called with instance of type 'DataClass'
I don't have experience working with Expression Trees. I've spent hours reading docs and other answers for similar issues but I still can't understand how to achieve what I want... I have no clue what to do now.
I'm testing this in a console app so here's the main class if you want to build it yourself:
using System.Collections.Generic;
using System.Linq;
class Program
{
static void Main(string[] args)
{
var data = new DataClass
{
PropertyOne = "Lorem",
PropertyTwo = "Ipsum",
Child = new ChildClass
{
PropertyThree = "Dolor"
}
};
var dataList = new List<DataClass> { data };
var results = dataList.Where(d => d.Match("dolor", true));
}
}
EDIT
I forgot to mention that my dataList should be IQueryable and I want to execute my code in SQL, that's why I'm trying to build the expression trees myself. So it appears my example code should be:
var dataList = new List<DataClass> { data };
var query = dataList.AsQueryable();
var results = query.Where(ExtensionClass.Match<DataClass>("lorem dolor"));
while my method becomes: (I'm following #sjb-sjb's answer and changed the GetFields() method in IFieldExposer<T> to a SelectedFields property)
public static Expression<Func<T, bool>> Match<T>(string text, bool ignoreCase) where T : IFieldExposer<T>
{
ParameterExpression parameter = Expression.Parameter(typeof(T), "obj");
MemberExpression selectedFieldsExp = Expression.Property(parameter, "SelectedFields");
LambdaExpression lambda = Expression.Lambda(selectedFieldsExp, parameter).Compile();
[...]
}
And then it seems that I have to dinamically call selectedFieldsExp with Expression.Lambda. I came up with:
Expression.Lambda(selectedFieldsExp, parameter).Compile();
and that works, but I don't know how to properly call DynamicInvoke() for the lambda expression.
It throws Parameter count mismatch. if I call it without parameters and Object of type 'System.Linq.Expressions.TypedParameterExpression' cannot be converted to type 'DataClass'. if I do DynamicInvoke(parameter).
Any ideas?
Before getting to the implementation, there are some design flaws that needs to be fixed.
First, almost all query providers (except LINQ to Object which simply compiles the lambda expressions to delegates and executes them) don't support invocation expressions and custom (unknown) methods. That's because they do not execute the expressions, but translate them to something else (SQL for instance), and translation is based on pre knowledge.
One example of invocation expression are Func<...> delegates. So the first thing you should do is to use Expression<Func<...>> wherever you currently have Func<...>.
Second, the query expression trees are built statically, i.e. there is no real object instance you can use to obtain the metadata, so the idea of IFieldExposer<T> won't work. You'd need a statically exposed list of expressions like this:
class DataClass //: IFieldExposer<DataClass>
{
// ...
public static IEnumerable<Expression<Func<DataClass, string>>> GetFields()
{
return new List<Expression<Func<DataClass, string>>>
{
a => a.PropertyOne,
b => b.Child.PropertyThree
};
}
}
Then the signature of the method in question could be like this
public static Expression<Func<T, bool>> Match<T>(
this IEnumerable<Expression<Func<T, string>>> fields, string text, bool ignoreCase)
with usage like this
var dataList = new List<DataClass> { data };
var query = dataList.AsQueryable()
.Where(DataClass.GetFields().Match("lorem", true));
Now the implementation. The desired expression could be built purely with Expression class methods, but I'll show you an easier (IMHO) method, which composes expression from compile time expression by replacing the parameter(s) with other expression(s).
All you need is a small helper utility method for replacing lambda expression parameter with another expression:
public static partial class ExpressionUtils
{
public static Expression ReplaceParameter(this Expression expression, ParameterExpression source, Expression target)
{
return new ParameterReplacer { Source = source, Target = target }.Visit(expression);
}
class ParameterReplacer : ExpressionVisitor
{
public ParameterExpression Source;
public Expression Target;
protected override Expression VisitParameter(ParameterExpression node)
=> node == Source ? Target : base.VisitParameter(node);
}
}
Internally it uses ExpressionVistor to find each instance of the passed ParameterExpression and replace it with the passed Expression.
With this helper method, the implementation could be like this:
public static partial class ExpressionUtils
{
public static Expression<Func<T, bool>> Match<T>(this IEnumerable<Expression<Func<T, string>>> fields, string text, bool ignoreCase)
{
Expression<Func<string, bool>> match;
if (ignoreCase)
{
text = text.ToLower();
match = input => input.ToLower().Contains(text);
}
else
{
match = input => input.Contains(text);
}
// T source =>
var parameter = Expression.Parameter(typeof(T), "source");
Expression anyMatch = null;
foreach (var field in fields)
{
// a.PropertyOne --> source.PropertyOne
// b.Child.PropertyThree --> source.Child.PropertyThree
var fieldAccess = field.Body.ReplaceParameter(field.Parameters[0], parameter);
// input --> source.PropertyOne
// input --> source.Child.PropertyThree
var fieldMatch = match.Body.ReplaceParameter(match.Parameters[0], fieldAccess);
// matchA || matchB
anyMatch = anyMatch == null ? fieldMatch : Expression.OrElse(anyMatch, fieldMatch);
}
if (anyMatch == null) anyMatch = Expression.Constant(false);
return Expression.Lambda<Func<T, bool>>(anyMatch, parameter);
}
}
The input => input.ToLower().Contains(text) or input => input.Contains(text) is our compile time match expression, which we then replace the input parameter with the body of the passed Expression<Func<T, string>> lambda expressions, with their parameter replaced with a common parameter used in the final expression. The resulting bool expressions are combined with Expression.OrElse which is the equivalent of the C# || operator (while Expression.Or is for bitwise | operator and in general should not be used with logical operations). Same btw for && - use Expression.AndAlso and not Expression.And which is for bitwise &.
This process is pretty much the expression equivalent of the string.Replace. In case the explanations and code comments are not enough, you can step through the code and see the exact expression transformations and expression building process.
There is no need to get into the complexities of dynamically creating an Expression, because you can just invoke the Func delegate directly:
public interface IFieldExposer<T>
{
IEnumerable<Func<T,string>> SelectedFields { get; }
}
public static class FieldExposerExtensions
{
public static IEnumerable<Func<T,string>> MatchIgnoreCase<T>( this IEnumerable<Func<T,string>> stringProperties, T source, string matchText)
{
return stringProperties.Where(stringProperty => String.Equals( stringProperty( source), matchText, StringComparison.OrdinalIgnoreCase));
}
}
class DataClass : IFieldExposer<DataClass>
{
public string PropertyOne { get; set; }
public string PropertyTwo { get; set; }
public ChildClass Child { get; set; }
public IEnumerable<Func<DataClass, string>> SelectedFields {
get {
return new Func<DataClass, string>[] { #this => #this.PropertyOne, #this => #this.Child.PropertyThree };
}
}
public override string ToString() => this.PropertyOne + " " + this.PropertyTwo + " " + this.Child.PropertyThree;
}
class ChildClass
{
public string PropertyThree { get; set; }
}
Then to use it,
class Program
{
static void Main(string[] args)
{
var data = new DataClass {
PropertyOne = "Lorem",
PropertyTwo = "Ipsum",
Child = new ChildClass {
PropertyThree = "Dolor"
}
};
var data2 = new DataClass {
PropertyOne = "lorem",
PropertyTwo = "ipsum",
Child = new ChildClass {
PropertyThree = "doloreusement"
}
};
var dataList = new List<DataClass>() { data, data2 };
IEnumerable<DataClass> results = dataList.Where( d => d.SelectedFields.MatchIgnoreCase( d, "lorem").Any());
foreach (DataClass source in results) {
Console.WriteLine(source.ToString());
}
Console.ReadKey();
}
}
Following up on my comment above, I think you could do it like this:
class DataClass
{
…
static public Expression<Func<DataClass,bool>> MatchSelectedFields( string text, bool ignoreCase)
{
return #this => (
String.Equals( text, #this.PropertyOne, (ignoreCase? StringComparison.OrdinalIgnoreCase: StringComparison.Ordinal))
|| String.Equals( text, #this.Child.PropertyThree, (ignoreCase? StringComparison.OrdinalIgnoreCase: StringComparison.Ordinal))
);
}
}
Then the query is just
Expression<Func<DataClass,bool>> match = DataClass.MatchSelectedFields( "lorem", ignoreCase);
IEnumerable<DataClass> results = dataList.Where( d => match(d));
I wouldn't usually post a second answer but I thought it would be useful to see how to avoid dynamic modification of Expressions.
Caveat: I didn't actually try to compile it.
Given the following set of classes:
public class MyClass
{
public int MyInt { get; set; }
}
public class ObjectProcessor
{
public int ProcessObject(MyClass myClass)
{
return myClass.MyInt ++;
}
}
public class Runner
{
public void Run()
{
var classToPass = new MyClass();
FuncExecutor.ExecuteAction<MyClass>(x => x.ProcessObject(classToPass));
}
}
public static class FuncExecutor
{
public static void ExecuteAction<T>(Expression<Func<ObjectProcessor, int>> expression)
{
// var func = expression.Compile(); ... does having an Expression help?
// How can I get a reference to 'classToPass' at this point?
// The 'classToPass' Type is known to be 'T', in this case 'MyClass'.
}
}
From within the ExecuteAction method, how can I get a reference to the classToPass instance that was passed in to ProcessObject?
EDIT: The comments have highlighted the complexity of trying to parse Expression Trees which could vary widely in their composition.
However, in this particular case there are two facts which cut down this variation considerably:
ProcessObject will only ever take a single parameter.
The parameter type is known in advance.
Code altered to express this.
To answer very specifically:
public class Runner
{
public void Run()
{
var classToPass = new MyClass();
classToPass.MyInt = 42;
FuncExecutor.ExecuteAction(x => x.ProcessObject(classToPass));
}
}
public class FuncExecutor
{
public static void ExecuteAction(Expression<Func<ObjectProcessor, int>> expression)
{
var lambdaExpression = (LambdaExpression)expression;
var methodCallExpression = (MethodCallExpression)lambdaExpression.Body;
var memberExpression = (MemberExpression)methodCallExpression.Arguments[0];
var constantExpression = (ConstantExpression)memberExpression.Expression;
var fieldInfo = (FieldInfo)memberExpression.Member;
var myClassReference = (MyClass) fieldInfo.GetValue(constantExpression.Value);
Console.WriteLine(myClassReference.MyInt); // prints "42"
}
}
Please note that when you pass the lambda to the ExecuteAction method, you capture a local variable reference (classToPass). The compiler will generate some code to handle that properly. More precisely, it will generate a type with a single member (a field) of type MyClass to hold the reference and use it from this point. That's why you'll get a MemberExpression in the argument expression list.
Since you can't directly manipulate this generated type, you can't just use the member expression Value property. But you can dynamically invoke the member accessor using the MemberInfo and the target reference (an instance of the compiler generated type).
I would not rely on this code.
You can read more about lambda related compiler generated code here, for example: http://thewalkingdev.blogspot.fr/2012/04/c-lambda-expressions-and-closures.html
The easiest way is to pass the instance as parameter and let ExecuteAction take care of calling the process method using that instance. To do this it is necessary to give your code a little bit of structure using a generic object processor interface:
public interface IObjectProcessor<T> {
public int ProcessObject(T instance);
}
public class MyClassProcessor : IObjectProcessor<MyClass> {
public int ProcessObject(MyClass myClass) {
return myClass.MyInt ++;
}
}
public class Runner {
public void Run() {
var classToPass = new MyClass();
var processor = new MyClassProcessor();
FuncExecutor.ExecuteAction<MyClass>(processor, classToPass);
}
}
public class FuncExecutor {
public static void ExecuteAction<T>(IObjectProcessor<T> processor, T obj) {
int result = processor.ProcessObject(obj);
}
}
This design could be a little annoying especially if your processor are "stateless" and if you really need a Func as parameter. In this case you can drop the interface and use static processors:
public class MyClassProcessor
public static int ProcessObject(MyClass myClass) {
return myClass.MyInt ++;
}
}
public class Runner {
public void Run() {
var classToPass = new MyClass();
FuncExecutor.ExecuteAction<MyClass>(MyClassProcessor.ProcessObject, classToPass);
}
}
public class FuncExecutor {
public static void ExecuteAction<T>(Func<T, int> process, T obj) {
int result = process(obj);
}
}
I want to update a list of objects(mycapsule, has many other members) when a condition (pred) holds for one of its class members(value). Whenever I change something another thing fails, I'm newbie in C# and really confused.
Can somebody fix my code:
In the best condition I only get get this error but I think many things are missing in my code
The type or namespace name `T' could not be found. Are you missing a using directive or an assembly reference?
here is my code
using System;
using System.Collections.Generic ;
namespace test
{
class MainClass
{
public static List< mycapsule<int,double> > sample= new List< mycapsule<int,double>>();
public static void Main (string[] args)
{
sample.Add(new mycapsule<int,double> {id=1 , value= 1.2});
update(pred, 12.3);
}
public static bool pred(double x)
{
if (x==2.5) return true;
return false;
}
public class mycapsule<KT, T>
{
public KT id {get ; set; }
public T value { get ; set; }
public int p; // and more
}
public bool update(Func<T, bool> predicate, T i)
{
foreach (var x in sample.FindAll(item => predicate(JustValue(item))) )
{
x.value = i ;
}
return true ;
}
public T JustValue(mycapsule<int,T> i)
{
return i.value;
}
}
}
Look at your update method:
public bool update(Func<T, bool> predicate, T i)
{
foreach (var x in KeyRecord.FindAll(item => predicate(JustValue(item))) )
{
x.value = i ;
}
return true ;
}
What do you expect T to be here? The method is not generic (it's not written as update<T>) and it's not declared in a generic class.
It's possible that you just want:
public bool update<T>(Func<T, bool> predicate, T i)
... but it's hard to say without knowing what KeyRecord.FindAll looks like. Oh, and you've got the same problem with JustValue.
As a side issue, the method names update and pred don't follow .NET naming conventions, and JustValue is a poor method name in terms of descriptiveness. mycapsule also doesn't follow .NET naming conventions. These things really matter in terms of readability.
I'm afraid this won't work due to type safety reasons. I corrected the code as much as possible and got this:
public static List<mycapsule<int, double>> sample = new List<mycapsule<int, double>>();
public static void Main(string[] args)
{
sample.Add(new mycapsule<int, double> { id = 1, value = 1.2 });
update(pred, 12.3);
}
public static bool pred(double x)
{
if (x == 2.5) return true;
return false;
}
public class mycapsule<KT, T>
{
public KT id { get; set; }
public T value { get; set; }
public int p; // and more
}
public static bool update<T>(Func<T, bool> predicate, T i)
{
List<mycapsule<int, double>> list = sample.FindAll(item => predicate(JustValue(item)));
foreach (var x in list)
{
x.value = i;
}
return true;
}
public static T JustValue<T>(mycapsule<int, T> i)
{
return i.value;
}
The error is:
predicate(JustValue(item)) => Argument 1: cannot implicitly convert from double to T
This comes from the fact that you are trying to forcefully call a method that you've specified as taking a generic type T (Func<T, bool>) with a value that is known to be double. Although we know that T will be double from the call to update(pred, 12.3);, nothing prevents me from passing in a predicate that takes an incompatible type e.g.:
public static bool pred(string x)
{
return false;
}
and
update(pred, "asdf");
Which is clearly inconsistent. The compiler is simply trying to prevent you from shooting yourself in the foot accidentally.
To solve this, you could explicitly pass the collection to the update method, thus ensuring that the types are consistent:
public static List<mycapsule<int, double>> sample = new List<mycapsule<int, double>>();
public static void Main(string[] args)
{
sample.Add(new mycapsule<int, double> { id = 1, value = 1.2 });
update(pred, 12.5, sample);
}
public static bool pred(double x)
{
if (x == 2.5) return true;
return false;
}
public class mycapsule<KT, T>
{
public KT id { get; set; }
public T value { get; set; }
public int p; // and more
}
public static bool update<T>(Func<T, bool> predicate, T i, List<mycapsule<int, T>> list)
{
foreach (var x in list.FindAll(item => predicate(JustValue(item))))
{
x.value = i;
}
return true;
}
public static T JustValue<T>(mycapsule<int, T> i)
{
return i.value;
}
Try this, And for generic method the method definition you have used is not correct.
It should be
//MethodName<T,U>(T para1, U para2)
I have change the code to include reflections, this should work.
Please try and give feedback.
using System;
using System.Collections.Generic;
using System.Reflection;
namespace test
{
class MainClass
{
public static List<Mycapsule<int, double>> sample = new List<Mycapsule<int, double>>();
public static void Main(string[] args)
{
sample.Add(new Mycapsule<int, double> { id = 1, value = 1.2 });
update(pred, 12.3);
}
public static bool pred(double x)
{
if (x == 2.5) return true;
return false;
}
public static bool update<T>(Func<T, bool> predicate, T i)
{
var myCollection = sample.FindAll(p => pred(JustValue<double>(p)));
MainClass mainClass = new MainClass();
foreach (var x in myCollection)
{
MethodInfo changeTypeMethod = typeof(MainClass).GetMethod("GetValue");
object value = changeTypeMethod.Invoke(mainClass, new object[] { i, typeof(T) });
PropertyInfo valueProperty = x.GetType().GetProperty("value");
valueProperty.SetValue(x, value);
}
return true;
}
public T GetValue<T>(T i)
{
return (T)Convert.ChangeType(i, typeof(T));
}
public static T JustValue<T>(Mycapsule<int, T> i)
{
return i.value;
}
}
//Outside the MainClass inside the same namespace
public class Mycapsule<KT, T>
{
public KT id { get; set; }
public T value { get; set; }
public int p; // and more
}
}
So I am writing a C# application, using .net/c# 4.0
I have a method which takes in a custom type and a dictionary.
I reuse this for a variety of things but for some reason I cannot think of a way to encapsulate the logic. The problem is this line
if (FastIntParse.FastParse(_dict[_Rule.Key].hourly_data[a].PropertyA) >
_Rule.Value)
In another use it may be
if (FastIntParse.FastParse(_dict[_Rule.Key].hourly_data[a].PropertyB) >
_Rule.Value)
The only thing that varies in the various cases is the Property I am using to compare to the rule value. For some reason I cannot think of a way to reuse it because I don't have the value to pass in to some function since the value is derived IN the function. How can I write a function to abstract away it's need to know which value it needs to derive and pass that information in ie pass it which property it will need to check and not the value of said property.
int a;
for (int z= 0;z<=2;z++)
{
a = (z * z) * 24;
for (; (a%24) <= _Rule.AlertEndTime; a++)
{
if (FastIntParse.FastParse(_dict[_Rule.Key].hourly_data[a].PropertyA) >
_Rule.Value)
{
EnqueueRuleTrigger(_Rule);
break;
}
}
}
I keep rewriting this method inline wherever I need it with the proper property.... this is obviously quite wasteful and any change needs to be made in many places.
Thanks in advance
You can use an Expression and then pull out the property within the method, then use reflection to tie this up to the object within the method
class Program
{
static void Main(string[] args)
{
List<PropertyBag> bags = new List<PropertyBag>()
{
new PropertyBag() {Property1 = 1, Property2 = 2},
new PropertyBag() {Property1 = 3, Property2 = 4}
};
Runme(x => x.Property1, bags);
Runme(x => x.Property2, bags);
Console.ReadLine();
}
public static void Runme(Expression<Func<PropertyBag, int>> expression, List<PropertyBag> bags)
{
var memberExpression = expression.Body as MemberExpression;
var prop = memberExpression.Member as PropertyInfo;
bags.ForEach( bag =>
Console.WriteLine(prop.GetValue(bag, null))
);
}
}
public class PropertyBag
{
public int Property1 { get; set; }
public int Property2 { get; set; }
}
}
to solve the problem with access to different properties and with the use of different boolean-function (<, >, ==) you could use delegates like this:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Reflection;
namespace ConsoleApplication1
{
delegate bool CompareFunction(Fii test, Foo item);
class Program
{
static List<Foo> list = new List<Foo>() {
new Foo() { PropertyA = 0, PropertyB = 9 },
new Foo() { PropertyA = 1, PropertyB = 10 }
};
static Fii test = new Fii() { PropertyA = 1 };
static void Main(string[] args)
{
Bar(list, delegate(Fii item1, Foo item2) { return item2.PropertyA < item1.PropertyA; });
Bar(list, delegate(Fii item1, Foo item2) { return item2.PropertyB > item1.PropertyA; });
Bar(list, delegate(Fii item1, Foo item2) { return item2.PropertyA == item1.PropertyA; });
Console.ReadLine();
}
static void Bar(List<Foo> list, CompareFunction cmp)
{
foreach (Foo item in list)
if (cmp(test, item))
Console.WriteLine("true");
else
Console.WriteLine("false");
}
}
class Foo
{
public int PropertyA { get; set; }
public int PropertyB { get; set; }
}
class Fii
{
public int PropertyA { get; set; }
}
}
Make your function take a lambda argument and pass it _ => _.PropertyA, _ => _.PropertyB etc.:
void CheckAndEnqueueRulesByProperty (Func<YourObject, string> propertyGetter)
{
...
if (FastIntParse.FastParse (propertyGetter (
_dict[_Rule.Key].hourly_data[a])) > _Rule.Value)
{
...
}
...
}
If you have many types of objects to check with the same logic, make this function generic.
This is kind of a weird question but it came up the other day and it has me thinking.
When is it preferable design to use lambda expressions in this form ".(x => x.Whatever)" verse ".(() => obj.Whatever)".
Consider the following extension methods.
public static class ExtensionMethods
{
public static string TryToGetTheString<T>(this T value, Func<T, string> method)
{
try
{
return method(value);
}
catch (Exception)
{
return "banana";
}
}
public static string TryToGetTheStringTwo<T>(this T value, Func<string> method)
{
try
{
return method();
}
catch (Exception)
{
return "banana";
}
}
}
And the following self referencing class.
public class testClass5000
{
private int? _id;
public int? ID { get { return _id; } set { _id = value; } }
private string _urgh;
public string Urgh { get; set; }
public testClass5000 tc5k { get; set; }
}
Then using an extremely lazy process to avoid checking for nulls, while attempting to get a string (Urgh) from testClass5000, you could implement the extension methods and class like such,
private void main()
{
var tc = new testClass5000();
textBox1.text = tc.TryToGetTheString(x => x.tc5k.tc5k.tc5k.Urgh);
}
However, since tc is declared locally the following also works.
private void main()
{
var tc = new testClass5000();
textBox1.text = tc.TryToGetTheStringTwo(() => tc.tc5k.tc5k.tc5k.Urgh);
}
I am curious when (x => x.tc5k.tc5k.tc5k.Urgh) is necessary and when (() => tc.tc5k.tc5k.tc5k.Urgh) is preferable.
//////////////////////////////////////////
I did come up with the following scenario where passing the parameter seems preferable.
With the following extension methods.
public static class ExtensionMethods
{
public static T TestOne<T>(this T value, Func<T, T> method)
{
try
{
return method(value);
}
catch (Exception)
{
return default(T);
}
}
public static T TestTwo<T>(this T value, Func<T> method)
{
try
{
return method();
}
catch (Exception)
{
return default(T);
}
}
}
And using the following code.
private void Form1_Load(object sender, EventArgs e)
{
var firstValue = 5;
var secondValue = 10;
var resultOne = firstValue.TestOne(x => x + 1).TestOne(x => x * 2);
//returns 12
var resultTwo = secondValue.TestTwo(() => secondValue + 1).TestTwo(() => secondValue * 2);
//returns 20
var resultThree = secondValue.TestTwo(() => secondValue.TestTwo(() => secondValue + 1) * 2);
//returns 22
}
In this example .TestOne(x => x + 1).TestOne(x => x * 2) is preferable notation because to achieve the same thing without passing a paremeter you need to start nesting expressions.
Injecting the parameters values directly in the lambda is more costly, because the compiler has to create a special class just for this purpose.
If we exclude performance considerations, then I would say that injecting the parameter is easier to write (personal preference here), and keeping the parameters in the prototype ( (x,y) => // do something) is useful when you're not actually the one providing the value of the parameters. For instance, when using the Select Linq query. Or I often use that for load balancing scenarios (a lambda "service => service.SomeFunction()", then a special factory retrieve the service and execute the lambda).
In cases where the parameters are simply not the same as the original value you provided.
A crude example
public static class Extensions
{
public static void DoSomething(this string s,Action<string> action)
{
var something = Enumerable.Range(1,100).Select(i=> String.Format("{0}_{1}",s,i));
foreach (var ss in something)
{
action(ss);
}
}
}
Then
var something = "ABC123";
something.DoSomething(x=>Console.WriteLine(x));
//Ignoring that we could do something.DoSomething(Console.WriteLine);
Obviously without the parameter you cant access the actual value you are insterested in, and the original value is of no use within this concept.