How to use/understand lambda expressions? - c#

I have the following method:
private byte[] GetEmailAsBytes(string lstrBody)
{
byte[] lbytBody;
ASCIIEncoding lASCIIEncoding = new ASCIIEncoding();
lbytBody = lASCIIEncoding.GetBytes(lstrBody);
return lbytBody;
}
I was wondering if this could be converted to a lambda expression. Im new to this. I have tried:
Func<string> BodyToBytes = x => {
ASCIIEncoding lASCIIEncoding = new ASCIIEncoding();
return lASCIIEncoding.GetBytes(x);
}
but this does not compile. Simply i wish to convert a string to a series of bytes, and for interest sake would like to do this using lambda expressions.

The expression Func<string> is equivalent to a function which accepts no arguments and returns a string.
Your example clearly returns a byte[], but you want it to accept a string and return a byte[].
To solve this, change BodyToBytes to match the following. Note that the type of the arguments come first, comma delimited, followed by the return type. In this case, x will be of type string.
Func<string, byte[]> BodyToBytes = x => {
ASCIIEncoding lASCIIEncoding = new ASCIIEncoding();
return lASCIIEncoding.GetBytes(x);
}
For a reference, see Func Type or the MSDN docs.

I have writeen a NUnit Example for my personal understanding.
private class ld
{
public Boolean make<T>(T param, Func<T, bool> func)
{
return func(param);
}
}
private class box
{
public Boolean GetTrue() { return true; }
public int Secret = 5;
}
[Test]
public void shouldDemonstrateLambdaExpressions()
{
//Normal Boolean Statement with integer
int a = 5;
Assert.IsTrue(a == 5);
Assert.IsFalse(a == 4);
//Boolean Statement Expressed Via Simple Lambda Expression
Func<int, bool> myFunc = x => x == 5;
Assert.IsTrue(myFunc(5));
Assert.IsFalse(myFunc(4));
//Encapsuled Lambda Expression Called on Integer By Generic Class with integer
ld t = new ld();
Assert.IsTrue(t.make<int>(5,myFunc));
Assert.IsFalse(t.make<int>(4, myFunc));
//Encapsuled Lambda Expression Called on Integer By Generic Class with implicit Generics
Assert.IsTrue(t.make(5, myFunc));
//Simple Lambda Expression Called on Integer By Generic Class with implicit Generic
Assert.IsTrue(t.make(20, (x => x == 20)));
Assert.IsTrue(t.make(20, (x => x > 12)));
Assert.IsTrue(t.make(20, (x => x < 100)));
Assert.IsTrue(t.make(20, (x => true)));
//Simple Lambda Expression Called on a Class By Generic Class with implicit Generic
//FULL LAMBDA POWER REACHED
box b = new box();
Assert.IsTrue(t.make(b, (x => x.GetTrue())));
Assert.IsTrue(t.make(b, (x => x.Secret == 5)));
Assert.IsFalse(t.make(b, (x => x.Secret == 4)));
}

Related

Return expression instead result

If I have function like this
double GetExpression(int x, int y, int z)
{
return x * y + z;
}
is it possible to modify it somehow, to not return result immediately only some object which is expression and then evaluate it this way:
var expression = GetExpression(1,2,3);
double result = expression.Execute() or expression.Evaluate()
other words just return function
?
Yes!
Func<double> GetExpression(int x, int y, int z)
{
return () => x * y + z;
}
use as:
var expression = GetExpression(1,2,3);
double result = expression();
Well, you could use delegates, and return a Func<double>:
Func<double> GetExpression(int x, int y, int z)
{
return () => x * y + z;
}
var expression = GetExpression(1,2,3);
double result = expression(); // Or expression.Invoke()
Is that what you were looking for?
Now each time you call expression() it will execute the code in the lambda expression. You can observe that if you use code which doesn't just return the same value each time. For example:
Func<int> GetExpression()
{
Random rng = new Random();
return () => rng.Next(10);
}
var expression = GetExpression();
for (int i = 0; i < 10; i++)
{
Console.WriteLine(expression());
}
That will print 10 random numbers in the range [0, 10). Note that this will only create one instance of Random (avoiding a common problem) - each time you call expression() it will call the Next() method on the same instance. The constructor for Random is called in the "normal" part of the method - it's not in the lambda expression. So that gets executed when you first call the GetExpression method (even if you never call expression() afterwards).
Note however that the arguments to your GetExpression were still passed by value though, and are captured by the lambda express. So consider this:
Func<int> GetExpression(int a, List<int> b)
{
return () => a + b.Count;
}
int x = 10;
List<int> list = new List<int> { 1, 2, 3 };
var expression = GetExpression(x, list);
Console.WriteLine(expression()); // 13
x = 20;
list.Add(100);
Console.WriteLine(expression()); // 14
Here the value of the list variable has been captured, so changes the the object that the value refers to are visible in the lambda expression, but changes to the x variable itself are not visible in the lambda expression. (Likewise if you had list = new List<int>(); that change wouldn't be visible...
To expand on Jon Skeet's answer, about capturing variables, if you didn't want to, you could do something like this:
double GetExpression(int x, int y, int z)
{
return x * y + z;
}
Func<int, int, int, double> expression = GetExpression;
for (int i = 0; i < 10; i++)
Console.WriteLine("{0}", expression(i, i+1, i+2));
Which avoids modifying the existing code (in case you wanted to point to a function you didn't have control over), and avoids capturing values outside of the lamda.

c# and LINQ where property-name of collection member is passed via function

As always, help/comments thoughts are always appreciated, and appologies for the naivety of my programming.
I am trying to create a broadly applicable function which can be used in future research which involves block randomization. Each member of patientDataCollection will have a boolean property named something like interventionArm, givenDrugX or something similar. The function aims to (pseudo-)randomly assign to an arm of a study, depending on block size - that is to say if block size is 8, 4 will be assigned to treatment and 4 to control (no treatment).
The code so far:
public static bool nextAllocation<T>(int blockSize, IEnumerable<T> patientDataCollection, string allocationPropertyName)
{
int remainingAllocations = blockSize - patientDataCollection.Count();
if (remainingAllocations <= 0) throw new Exception("All alocations within block accounted for");
var p = typeof(T).GetProperty(allocationPropertyName);
int remainingInterventions = blockSize/2 - patientDataCollection.Count(c => c.p);
double Pintervention = (double)remainingInterventions / (double)remainingAllocations;
double rdm = new Random().NextDouble();
return (rdm <= Pintervention);
}
this is of course flawed logic because the variable p does not relate to c.p referenced in the linq statement patientDataCollection.Count(c => c.p). obviously this statement is simply to count all elements which have a true value.
ASP is 4.0. Can anyone see how to achieve this
You can pass to your method a Func<T, bool> which will be used for counting.
public static bool nextAllocation<T>(int blockSize, IEnumerable<T> patientDataCollection, Func<T,bool> predicate)
{
int remainingAllocations = blockSize - patientDataCollection.Count();
if (remainingAllocations == 0) throw new Exception("All alocations within block accounted for");
int remainingInterventions = blockSize/2 - patientDataCollection.Count(predicate);
double Pintervention = remainingInterventions / remainingAllocations;
double rdm = new Random().NextDouble();
return (rdm <= Pintervention);
}
An example of usage would be something like this:
var result = nextAllocation(10, collection, c=>c.interventionArm);
You can use reflection to get the value of the property:
int remainingInterventions = blockSize/2 -
patientDataCollection.Count(c => (bool)p.GetValue(c,null));
Add error checking as well.
Try using Expressions
public static class ExpressionCreator
{
public static Func<T, TProperty> CreatePropertyAccessExpression<T, TProperty>(string propertyName)
{
var tType = typeof (T);
var property = tType.GetProperty(propertyName);
var parameterExpression = Expression.Parameter(tType);
var memberAccessExpression = Expression.MakeMemberAccess(parameterExpression, property);
var lambda = Expression.Lambda<Func<T, TProperty>>(memberAccessExpression, parameterExpression);
return lambda.Compile();
}
}
Example usage:
public class A
{
public bool Thing1 { get; set; }
public bool Thing2 { get; set; }
}
static void Main(string[] args)
{
var #as = new A[10];
for(var i = 0; i < #as.Length; i+=2)
{
#as[i] = new A {Thing1 = true};
#as[i + 1] = new A {Thing2 = i%4 == 0};
}
var thing1Expression = ExpressionCreator.CreatePropertyAccessExpression<A, bool>("Thing1");
var thing2Expression = ExpressionCreator.CreatePropertyAccessExpression<A, bool>("Thing2");
Console.WriteLine(#as.Count(thing1Expression));
Console.WriteLine(#as.Count(thing2Expression));
Console.ReadLine();
}

How to create C# delegate double callable like this `f(a + k * h)`?

I have created a public delegate double DynamicFunc(double x);
and now I try to create an instance of it to pass into a component later
private DynamicFunc f(double x)
{
return (return_ => x);
}
But when I do stuff alike this:
double value = 2 * f(50);
I get: Error Operator '*' cannot be applied to operands of type 'double' and 'DynamicFunc';
Why - what is wrong with my deligate?
Calling function f with any sort of argument returns a dynamic function, not a value you can use in a math expression..
private DynamicFunc f(double x)
{
return (return_ => x);
}
double value = 2 * f(50)();
However, have you considered this alternative? That way you need no delegate:
private Func<double> f(double x)
{
return (() => return x;);
}
double value = 2 * f(50)();
Try the existing Func delegate :
Func<double, double> f = new Func<double, double>(x => x);
double value = 2 * f(50);
The f function returns a delegate (DynamicFunc). You need to invoke this delegate by passing it a double argument in order to get the result:
double value = 2 * f(50)(20);
Because f() is declared to return a delegate and not a double.
You should declare f like this:
private double f(double x)
{
return (return_ => x);
}
Then in a call:
private double SomeFunc(DyanmicFunc func)
{
return 2 * func(50);
}
And call it with:
double result = SomeFunc(f);

References to methods C#

I'm just wondering if there is a C# equivilent for this python code.
I want to store the names of methods in some sort of collection and call them later on. I have searched, but I really don't know what to look for.
For example in python I could do:
def add_one(x):
return x + 1
def double_it(x):
return x*2
maths_rules = [add_one, double_it]
def do_maths(maths_rules, x):
for func in maths_rules:
x = func(x)
return x
print do_maths(maths_rules, 9)
# >>> 20
This is a silly example, but you should get the idea.
You are looking for delegates.
A delegate is a type that defines a method signature. When you instantiate a delegate, you can associate its instance with any method with a compatible signature. You can invoke
(or call) the method through the delegate instance.
Your example in C#, using the Func<T, TResult> Delegate:
int add_one(int x) { return x + 1; }
int double_it(int x) { return x * 2; }
var maths_rules = new List<Func<int,int>> { add_one, double_it };
int do_maths(IEnumerable<Func<int,int>> maths_rules, int x)
{
foreach (var func in maths_rules)
{
x = func(x);
}
return x;
}
Console.WriteLine(do_maths(maths_rules, 9));
// prints "20"
Yes, you can use delegates. For this one use Func<int, int>.
like:
int addone(int x)
{
return x + 1;
}
and in main:
Func<int, int> myFunc = new Func<int, int>(addone);
myFunc(5); // to use it, you can pass it as you like
example on your code:
static int add_one(int x)
{
return x + 1;
}
static int double_it(int x)
{
return x * 2;
}
static int do_maths(List<Func<int, int>> math_rules, int x)
{
foreach(var func in math_rules)
x = func(x);
return x;
}
static void Main(string[] Args)
{
List<Func<int, int>> math_rules = new List<Func<int, int>>();
math_rules.Add(new Func<int, int>(add_one));
math_rules.Add(new Func<int, int>(double_it));
Console.WriteLine(do_maths(math_rules, 9)); // 20
}
or use lambdas as suggested in comment:
static int do_maths(List<Func<int, int>> math_rules, int x)
{
foreach(var func in math_rules)
x = func(x);
return x;
}
static void Main(string[] Args)
{
List<Func<int, int>> math_rules = new List<Func<int, int>>();
math_rules.Add(new Func<int, int>((x) => (x + 1)));
math_rules.Add(new Func<int, int>((x) => (x * 2)));
Console.WriteLine(do_maths(math_rules, 9)); // 20
}

Can I use a lambda expression with params keyword?

Lets say I have the following code:
delegate int MyDel (int n); // my delegate
static int myMethod( MyDel lambda, int n) {
n *= n;
n = lambda(n);
return n; // returns modified n
}
This way, having different lambda expression I can tune the output of the Method.
myMethod ( x => x + 1, 5);
myMethod ( x => x - 1, 5);
Now, if I don't want to do any aritmethic in lambda expression, I could use:
myMethod ( x => x, 5); // and lambda will simply return x
My question is, is there a way to use the lambda expresion with 'params' optional properties? Maybe somehow embedding my delegate in array?
static int myMethod (int n, params MyDel lambda) {
Does this work?
EDIT
Sorry, was doing this with one eye, let me rephrase that.
static int myMethod (int n, params MyDel[] lambdas) {
Yes you can.
delegate int MyDelegate(int n);
static void MyMethod(int n, params MyDelegate[] handlers)
{
for (int i = 0; i < handlers.Length; i++)
{
if (handlers[i] == null)
throw new ArgumentNullException("handlers");
Console.WriteLine(handlers[i](n));
}
}
static void Main(string[] args)
{
MyMethod(1, x => x, x => x + 1);
Console.Read();
}
Output:
1
2

Categories

Resources