References to methods C# - 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
}

Related

Is there a way to name the fields when receiving a ValueTuple as a parameter?

There is a method that receives a ValueTuple and returns it after modifying it. In this case, can I specify the field name of the ValueTuple in the method parameter?
private static void Operation()
{
var tuple = (X: 10, Y: 20);
var changeTuple = ChangeTuple(tuple);
}
private static ValueTuple<int, int> ChangeTuple(ValueTuple<int, int> tuple)
{
tuple.Item1 = 100; // ex) tuple.X = 100;
tuple.Item2 = 200; // ex) tuple.Y = 200;
return tuple;
}
Yes, you can simply replace ValueTuple<int, int> to (int X, int Y):
private static (int X, int Y) ChangeTuple((int X, int Y) tuple)
{
tuple.X = 100;
tuple.Y = 200;
return tuple;
}
For reference: naming tuple's fields
Or you can use deconstruction:
private static (int X, int Y) ChangeTuple(ValueTuple<int, int> tuple)
{
var (X, Y) = tuple;
X = 100;
Y = 200;
return (X, Y);
}
Please note that in both cases you are not modifying the original ValueTuple rather create a new one:
In the first case it is because the ValueTuple is a struct, so it is passed by value
In the second case we explicitly create a new named ValueTuple

Several nested loops to one

In computational programs there is often such code as
foreach (var x in xx)
foreach (var y in yy)
foreach (var z in zz)
Calculate(x, y, z);
Can it be simplified to just one loop, like
foreach (var (x, y, z) in F(xx, yy, zz)) Calculate(x, y, z);
For any number of variables, probably having different types?
If you want to deal with arbitrary types, you will have to define a generic method for all each amount of parameters you have - this is the same problem as with the predefined delagates Action, Action<T>, Action<T1,T2>, ...
Hence your code could look like this
public static class Helper
{
public static IEnumerable<(T1,T2)> CrossJoin<T1,T2>(IEnumerable<T1> input1, IEnumerable<T2> input2)
{
return input1.SelectMany(x => input2, (x,y) => (x,y));
}
public static IEnumerable<(T1,T2,T3)> CrossJoin<T1,T2,T3>(IEnumerable<T1> input1, IEnumerable<T2> input2, IEnumerable<T3> input3)
{
return CrossJoin(input1,input2).SelectMany(x => input3, (x,y) => (x.Item1, x.Item2, y));
}
public static IEnumerable<(T1,T2,T3,T4)> CrossJoin<T1,T2,T3,T4>(IEnumerable<T1> input1, IEnumerable<T2> input2, IEnumerable<T3> input3, IEnumerable<T4> input4)
{
return CrossJoin(input1,input2,input3).SelectMany(x => input4, (x,y) => (x.Item1, x.Item2, x.Item3, y));
}
// and so on
}
Because we have to define a method for every amount of parameters, there is no need for a sophisticated recursive method which catches all cases. Because only value tuples are used and no arrays are created, the garbage collection won't have so much work as in your solution.
Online demo: https://dotnetfiddle.net/HrkhX6
I have come up with a simple cross join method, but all variables should have the same type T:
public static IEnumerable<T[]> CrossJoin<T>(params IEnumerable<T>[] seqs)
{
if (seqs.Length == 1) foreach (var x in seqs[0]) yield return new[] { x };
else
{
var subres = CrossJoin(seqs.Skip(1).ToArray());
var res = from x in seqs[0] from xx in subres select xx.Prepend(x);
foreach (var x in res) yield return x.ToArray();
}
}
usage:
foreach (var (x, y, z) in Helper.CrossJoin(xx, yy, zz)) Calculate(x, y, z);
It can be changed to work with object but it will require type casting to use the variables..

C# - Passing functions (with arguments) as arguments of a function

I need to create a function, that will take another functions (always different quantity of them). Can someone help me please?
Function DoThisFunction will have different types and quantity of parameters.
there can be different number of condition functions.
I'll try to show it here:
bool MyFunction(condition1(args), condition2(args), condition3(args), ... , DoThisFunction(args))
{
...
if (condition1(int x) == true && condition2(int x, string C) == 5)
{
DoThisFunction(par1, par2, par3 ...);
return true;
}
}
bool condition1(int x)
{
if (x>5)
return true;
else
return false;
}
int condition2(int x, string C)
{
....
return par1;
}
etc...
Then I need to call:
bool z = MyFunction(condition1(int x)==true, condition2(int x, string C)==5, DoThisFunction(par1, anotherArguments ...))
I would like to suggest another approach for your code.
Maybe, you can keep a separated list with all the functions you need to verify, and run each method inside a very simple loop (foreach), in this case:
the code will be very friendly (easy to understand)
better maintainability
you can review less code and add more functionality (for instance, you may inject some code and just add another Func<> into your List<>)
Please, take a look at the following example:
static class Program
{
private static void Main(string[] args)
{
var assertions = new List<Func<object[], bool>>
{
Assertion1,
Assertion2,
Assertion3
};
var yourResult = Assert(assertions, 1, "1", true);
Console.WriteLine(yourResult); // returns "True" in this case
Console.ReadLine();
}
private static bool Assert(IEnumerable<Func<object[], bool>> assertions, params object[] args)
{
// the same as
// return assertions.Aggregate(true, (current, assertion) => current & assertion(args));
var result = true;
foreach (var assertion in assertions)
result = result & assertion(args);
return result;
}
private static bool Assertion1(params object[] args)
{
return Convert.ToInt32(args[0]) == 1;
}
private static bool Assertion2(params object[] args)
{
return Convert.ToInt32(args[0]) == Convert.ToInt32(args[1]);
}
private static bool Assertion3(params object[] args)
{
return Convert.ToBoolean(args[2]);
}
}
This solution seems to generic for your problem.
For checking preconditions before executing methods have a look at Code Contracts
You can use functor like the following:
private bool MyFunction(Func<int, bool> condition1, Func<int,string,int> condition2, Func<int,string,int, int> doThisFunction, int x, string str)
{
if (condition1(x) && condition2(x, str) == 5)
return doThisFunction(x, str, x) == 10;
return false;
}
Then call this function in your code like the below:
MyFunction(x => x > 5 ? true : false, (x, C) => C.Length == x * 5 ? 5 : C.Length,
(x, str, y) =>
{
if (x + y > str.Length)
return 5;
else if (x * y > 5)
return 10;
else
return 15;
}, 10, "Csharp");

Implementing Callback in WP7 C#

I have an app that runs a function that could take a decent amount of time, so I need to add a callback method. How would I go about this?
Mainly, my question is what is the type that needs to be passed to the class constructor?
On C# (not only on WP7) you can call any function asynchronously by wrapping it in a delegate. On the delegate's BeginInvoke call you'd pass a callback which will be invoked when the operation is completed. See the example below:
int MyLongOperation(int x, int y) {
Thread.Sleep(10000);
return x+y;
}
void CallingLongOperation(){
int x = 4;
int y = 5;
Func<int, int, int> func = MyLongOperation;
func.BeginInvoke(x, y, OperationCallback, func);
}
void OperationCallback(IAsyncResult asyncResult) {
Func<int, int, int> func = (Func<int, int, int>) asyncResult.AsyncState;
int result = func.EndInvoke(asyncResult);
// do something with the result
}
If you need to pass some additional parameter in the asyncState / userState property, you can also use the AsyncDelegate property of the IAsyncResult parameter (which for delegate calls is always System.Runtime.Remoting.Messaging.AsyncResult) and retrieve the delegate from there as well, as shown below.
public int MyLongOperation(int x, int y)
{
Thread.Sleep(10000);
return x + y;
}
public void CallLongOperation()
{
Func<int, int, int> func = MyLongOperation;
func.BeginInvoke(5, 7, MyCallback, "Expected result: " + 12);
Console.WriteLine("Called BeginInvoke");
func.BeginInvoke(11, 22, MyCallback, "Expected result: " + 33);
Console.WriteLine("Press ENTER to continue");
Console.ReadLine();
}
void MyCallback(IAsyncResult asyncResult)
{
Func<int, int, int> func = (Func<int, int, int>)((System.Runtime.Remoting.Messaging.AsyncResult)asyncResult).AsyncDelegate;
string expectedResult = (string)asyncResult.AsyncState;
int result = func.EndInvoke(asyncResult);
Console.WriteLine("Result: {0} - {1}", result, expectedResult);
}

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