Store an operator in a variable - c#

Is there a way to store an operator inside a variable? I want to do something like this (pseudo code):
void MyLoop(int start, int finish, operator op)
{
for(var i = start; i < finish; op)
{
//do stuff with i
}
}
I could then call this method like so:
MyLoop(15, 45, ++);
MyLoop(60, 10, --);
Does something like this exist in C#?

I suppose something like this. You do not define the operator, but a function (lambda) which does the change for you.
void MyLoop(int start, int finish, Func<int, int> op)
{
for(var i = start; i < finish; i = op(i))
{
//do stuff with i
}
}
I could then call this method like so:
MyLoop(15, 45, x => x+1);
MyLoop(60, 10, x => x-1);

Use a Function delegate;
Encapsulates a method that has one parameter and returns a value of
the type specified by the TResult parameter.
void MyLoop(int start, int finish, Func<int, int> op)
{
for(var i = start; i < finish; i = op(i))
{
//do stuff with i
}
}
Then;
MyLoop(15, 45, x => ++x);
MyLoop(60, 10, x => --x);
Here is a DEMO.

I tried a different approach, using a class that defines operators and accessing via reflection - i.e. you can store your operators as strings.
This allows for relational operators as well.
class Program
{
static void Main(string[] args)
{
Operators ops = new Operators();
object result = ops.Use("LessOrEqual", new object[] {3,2}); // output: False
Console.WriteLine(result.ToString());
result = ops.Use("Increment", new object[] {3}); // output: 4
Console.WriteLine(result.ToString());
Console.ReadKey();
}
}
public class Operators
{
public object Use(String methodName, Object[] parameters)
{
object result;
MethodInfo mInfo = this.GetType().GetMethod(methodName);
result = mInfo.Invoke(this, parameters); // params for operator, komma-divided
return result;
}
public bool LessOrEqual(int a, int b)
{
if (a <= b)
{
return true;
}
else
{
return false;
}
}
public int Increment(int a)
{
return ++a;
}
}

use something like Func<int, int> op
or change the type of op to string, then check the value and according to it build your for loop like:
void MyLoop(int start, int finish, string op)
{
if ((op.Equals("++") && (start < finish))
{
for(var i = start; i < finish; i++)
{
//processMethod(i)
}
}
else if ((op.Equals("--") && (start > finish))
{
for(var i = start; i < finish; i--)
{
//processMethod(i)
}
}
}

public class Program {
public static void Main(String[] args) {
Looper(x => x + 1);
Looper(x => ++x);
//Looper(x => x++); will not works
Looper(x => x * 2);
}
public static void Looper(Func<int, int> op) {
for (int i = 1; i < 10; i = op(i)) {
Console.WriteLine(i);
}
Console.WriteLine("----------");
}
}

Related

How to return a generic function from a non-generic function?

This will probably be easiest to explain with an example.
So, let's start with the following TryNTimes function.
public static T TryNTimes<T>(Func<T> f, int n)
{
var i = 0;
while (true)
{
try
{
return f();
}
catch
{
if (++i == n)
{
throw;
}
}
}
}
And use it like
MyType x = TryNTimes(DoSomething, 3);
MyOtherType y = TryNTimes(DoSomethingElse, 3);
But I'm using this in many cases with the same N, so I'd like to make it easy to create a function that injects the n value into here. So the use would be
var tryThreeTimes = CreateRetryWrapper(3);
MyType x = tryThreeTimes(DoSomething);
MyOtherType y = tryThreeTimes(DoSomethingElse);
The closest I could come up with was
public static Func<Func<T>, T> CreateRetryWrapper<T>(int n)
{
return f => TryNTimes(f, n);
}
But that's not really what I want, because it forces me to specify T a-priori, so it's not really reusable in the way that I want. I want to be able to delay the T, returning a generic function as a value. Something like
public static Func<Func<_>, _> CreateRetryWrapper(int n)
{
return f => TryNTimes(f, n);
}
Is this something that's possible in C#?
workaround:
class RetryWrapper
{
int n;
public RetryWrapper(int _n) => n =_n;
public T Try<T>(Func<T> f) => TryNTimes(f, n);
}
Use:
var tryThreeTimes = new RetryWrapper(3);
MyType x = tryThreeTimes.Try(DoSomething);
MyOtherType y = tryThreeTimes.Try(DoSomethingElse);
class RetryWrapper
{
readonly int n;
private RetryWrapper(int n)
{
this.n = n;
}
public static RetryWrapper Create(int n)
{
return new RetryWrapper(n);
}
public T TryNTimes<T>(Func<T> f)
{
var i = 0;
while (true)
{
try
{
return f();
}
catch
{
if (++i == n)
{
throw;
}
}
}
}
}
Usage:
RetryWrapper.Create(3).TryNTimes(() => 16);

Advanced DynamicInvocation of arguments for a "Delegated Switch"

Context
In my free time, I wanted to develop a tools that will fulfill the following needs :
Looping over a bit[] value to execute a determined method for each True.
Easy to implement a new method and easy to call overall in case of new filter OR adding length to the bit[] values.
I called this need "Delegated Switch" but their is no real relation to switch...
Needs
I realized that I also want to give arguments to my methods (which could be different from a method to another). So I searched for solutions and found tricks to not have arguments using inheritance of OperatorOnFilter.
What I want to know is:
Does it exist a way to do that without inheritance (changing OperatorOnFilter)?
(Optionally if not, any architectural recommendation?)
(Optionally, Delegate.DynamicInvoke() is a bit slow. Any better idea?)
Existing Code
public class OperatorOnFilter
{
Dictionary<int, Delegate> Operations;
public OperatorOnFilter() { Operations = new Dictionary<int, Delegate>(); }
public void AddOrReplace(int numTraitement, Delegate Action)
{
if (Operations.ContainsKey(numTraitement))
Operations[numTraitement] = Action;
else
Operations.Add(numTraitement, Action);
}
public void ApplyOperations(FilterManager Filter)
{
for (int i = 0; i < Filter.Values.Count(); i++)
if (Operations.ContainsKey(i) && Filter.Values[i])
Operations[i].DynamicInvoke();
}
}
public class FilterManager
{
public bool[] Values;
public FilterManager(int filtre)
{
List<bool> tmpList = new List<bool>();
int i = 0;
while (filtre >> i > 0)
{
tmpList.Add((filtre & (1 << i)) == (1 << i));
i++;
}
Values = tmpList.ToArray();
}
}
Test
class Program
{
static int theYes = 0;
delegate void operate();
static void Main(string[] args)
{
int i = 0;
OperatorOnFilter myOperators = new OperatorOnFilter();
myOperators.AddOrReplace(0, (operate)delegate() { Console.Write("a"); theYes++; }); //1
myOperators.AddOrReplace(1, (operate)delegate() { Console.Write("b"); theYes++; }); //2
myOperators.AddOrReplace(2, (operate)delegate() { Console.Write("c"); theYes++; }); //4
myOperators.ApplyOperations(new FilterManager(7)); //"abc" 7 = 1 + 2 + 4
myOperators.ApplyOperations(new FilterManager(3)); //"ab" 3 = 1 + 2
myOperators.ApplyOperations(new FilterManager(6)); //"bc" 6 = 2 + 4
Console.WriteLine(theYes); // 7
Console.ReadKey();
}
}
// FINAL RESULT :
// abcabbc
// 7
If I understand your question correctly, you are looking for a way to write the function without specifying the number of parameters that you pass in.
There is a way to do this, using the params keyword. There's also a good (and probably better) example at https://msdn.microsoft.com/en-us/library/ms228391(v=vs.90).aspx
This can require you to declare at least the type of the argument that you will pass in. However, you can set that type as Object or a generic, or even use the Delegate type that you are already familiar with to pass in other functions.
If you do this, a function signature will be like:
public void AddOrReplace(Delegate Action, params int[] list){...}
And you would call it with:
myOperators.AddOrReplace((operate)delegate() { Console.Write("a"); theYes++; }, 1, 2, 3, 4, 5);
Based on #Erk comments and some self improvement. I found my answers using explicit parameters on delegate and on my AddOrReplace methods.
Final Code (Tuple is added since I work with .NET 3.5)
public class OperatorOnFilter
{
Dictionary<int, Tuple<int, object[]>> Operations = new Dictionary<int, Tuple<int, object[]>>();
List<Delegate> lstOperations = new List<Delegate>();
public OperatorOnFilter() { }
public void AddOrReplace(int numTraitement, Delegate Action, params object[] Arguments)
{
if (!lstOperations.Contains(Action))
lstOperations.Add(Action);
if (Operations.ContainsKey(numTraitement))
Operations[numTraitement] = new Tuple<int, object[]>(lstOperations.IndexOf(Action), Arguments);
else
Operations.Add(numTraitement, new Tuple<int, object[]>(lstOperations.IndexOf(Action), Arguments));
}
public void ApplyOperations(FilterManager Filter)
{
for (int i = 0; i < Filter.Values.Count(); i++)
if (Operations.ContainsKey(i) && Filter.Values[i])
lstOperations[Operations[i].First].DynamicInvoke(Operations[i].Second);
}
}
public class FilterManager
{
public bool[] Values;
public FilterManager(int filtre)
{
List<bool> tmpList = new List<bool>();
int i = 0;
while (filtre >> i > 0)
{
tmpList.Add((filtre & (1 << i)) == (1 << i));
i++;
}
Values = tmpList.ToArray();
}
}
public class Tuple<T1, T2>
{
public T1 First { get; private set; }
public T2 Second { get; private set; }
internal Tuple(T1 first, T2 second)
{
First = first;
Second = second;
}
}
public static class Tuple
{
public static Tuple<T1, T2> New<T1, T2>(T1 first, T2 second)
{
var tuple = new Tuple<T1, T2>(first, second);
return tuple;
}
}
Test Class
class Program
{
static int theYes = 0;
delegate void operate1();
delegate void operate2(string a);
delegate void operate3(string a, uint x);
static void Main(string[] args)
{
int i = 0;
OperatorOnFilter myOperators = new OperatorOnFilter();
myOperators.AddOrReplace(0, (operate1)delegate() { Console.Write("a"); theYes++; }); //1
myOperators.AddOrReplace(1, (operate2)delegate(string a) { Console.Write(a); theYes++; }, "b"); //2
myOperators.AddOrReplace(2, (operate3)delegate(string a, uint x) { for (uint j = 0U; j < x; j++) { Console.Write(a); theYes++; } }, "c", 3U); //4
myOperators.ApplyOperations(new FilterManager(7)); //"abccc" 7 = 1 + 2 + 4
myOperators.ApplyOperations(new FilterManager(3)); //"ab" 3 = 1 + 2
myOperators.ApplyOperations(new FilterManager(6)); //"bccc" 6 = 2 + 4
Console.WriteLine(theYes); // 11
Console.ReadKey();
}
}

C#: making a class usable in foreach

I'm having a little problem with this thing:
I have to make a PrimeCollection class in C# that implements IEnumerable interface and generates prime numbers collection on the fly.
So if I write as a test something like this:
static void Main(string[] args) {
PrimeCollection pc = new PrimeCollection();
foreach (int p in pc)
Console.WriteLine(p);
}
It should generate primes until it reaches int32 limit.
So far I have this:
class PrimeCollection {
public IEnumerable<int> Primes() {
var ints = Enumerable.Range(2, Int32.MaxValue - 1);
return ints.Where(x => !ints.TakeWhile(y => y < Math.Sqrt(x)).Any(y => x % y == 0));
}
}
However to do the generating i need to call out it like this:
static void Main(string[] args) {
PrimeCollection pc = new PrimeCollection();
foreach (int p in pc.Primes())
Console.WriteLine(p);
}
I assume I need to make the class IEnumerable, not the method, however I have no idea how to generate the numbers on the fly.
If you want to specifically create your custom primes-enumerable, you can define it as a wrapper over your existing linq query. Like this:
public class PrimesEnumerable : IEnumerable<int> {
public PrimesEnumerable() {
var ints = Enumerable.Range(2, Int32.MaxValue - 1);
_internalEnumerable = ints.Where(x => !ints.TakeWhile(y => y*y<=x).Any(y => x % y == 0));
}
public readonly IEnumerable<int> _internalEnumerable;
public IEnumerator<int> GetEnumerator() {
return _internalEnumerable.GetEnumerator();
}
System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() {
return _internalEnumerable.GetEnumerator();
}
}
Now you can foreach over it:
var primes = new PrimesEnumerable();
int i = 0;
foreach (var prime in primes) {
if (i == 10)
break;
Console.WriteLine(prime);
i++;
}
Console.ReadLine();
Note: do fix the bug that #CarstenKönig is talking about.
There is no reason to have an instantiable class at all. You are not holding a state.
public static class Prime
{
public static IEnumerable<int> Values()
{
var ints = Enumerable.Range(2, Int32.MaxValue - 1);
return ints.Where(x => !ints.TakeWhile(y => y < Math.Sqrt(x)).Any(y => x % y == 0));
}
}
Then you can use it like this:
static void Main(string[] args)
{
foreach (int p in Prime.Values())
Console.WriteLine(p);
}
You mean something like this?
class Program
{
static void Main(string[] args)
{
foreach(var prime in new PrimeCollection())
{
Console.WriteLine(prime);
}
Console.Read();
}
}
class PrimeCollection : IEnumerable
{
public IEnumerator GetEnumerator()
{
var ints = Enumerable.Range(2, Int32.MaxValue - 1);
return ints.Where(x => !ints.TakeWhile(y => y < Math.Sqrt(x)).Any(y => x % y == 0)).GetEnumerator();
}
}

How, if possible, can you pass in a C# Property to be used like a method?

I know Func<> is used to pass a method that has a return value to be used inside another method. I know Action<> is used to pass a method that does not have a return value to be used inside another method. Is there a way to pass in a property so it's get/set can be used inside another method?
For example, here is a method that uses Func<>:
public bool RangeCheck (int minVal, int maxVal, Func<< int, int >> someMethod)
{
bool retval = true;
try
{
for (int count = min; count <= max; count++)
{
int hello = someMethod(count);
}
}
catch
{
retval = false;
}
return retval;
}
What I am looking for is something like this:
public bool RangeCheck(int min, int max, Prop<< int >> someProperty)
{
bool retval = true;
try
{
for (int count = min; count <= max; count++)
{
someProperty = count;
}
}
catch
{
retval = false;
}
return retval;
}
Is there anything out there like this? I can't find anything. This would be very useful. Thanks.
Could you use a lambda as a wrapper?
MyClass myClass = new MyClass();
bool val = RangeCheck(0, 10, () => myClass.MyProperty);
If you're looking to do both, you would make two lambdas, one for set, and one for get.
bool val = RangeCheck(0, 10, () => myClass.MyProperty, (y) => myClass.MyProperty = y);
My syntax is probably off, but I think this gives the idea.
Not that I know of. You could try using reflection and pass the object along with the corresponding PropertyInfo object of the property you want to get the value of. You then call PropertyInfo's SetValue function to assign a value to it (assuming it's read/write, of course).
public void SetMyIntValue()
{
SetPropertyValue(this, this.GetType().GetProperty("MyInt"));
}
public int MyInt { get; set; }
public void SetPropertyValue(object obj, PropertyInfo pInfo)
{
pInfo.SetValue(obj, 5);
}
Why not simply make it a ref argument?
public bool RangeCheck(int min, int max, ref int someProperty)
You can now set the value of someProperty inside the method.
And call it like so:
RangeCheck(min, max, ref myProperty);
You could use a Func like this Func<int, T>
void Main()
{
var sc = new SimpleClass();
var result = RangeCheck(0, 10, x => sc.Value = x );
System.Console.WriteLine(result);
System.Console.WriteLine(sc.Value);
}
public class SimpleClass
{
public int Value { get; set; }
}
public bool RangeCheck<T>(int minVal, int maxVal, Func<int, T> someMethod)
{
bool retval = true;
try
{
for (int count = minVal; count <= maxVal; count++)
{
//someMethod(count); //is not a range check,
//Did you mean
someMethod(count - minValue);
}
}
catch
{
retval = false;
}
return retval;
}

Multicast delegate always does the last operation

So I have the following the code:
namespace ConsoleApplication1
{
public delegate int Transformer(int x);
class Test
{
public static void Transform(int[] values, Transformer t)
{
for (int i = 0; i < values.Length; i++)
{
values[i] = t(values[i]);
}
}
static int Square(int x)
{
return x * x;
}
static int Minus(int x)
{
return x - 1;
}
static void Main()
{
int[] values = { 1, 2, 3 };
Transformer t = Test.Minus;
t += Test.Square;
Test.Transform(values, t);
foreach (int i in values)
{
Console.Write(i + " ");
}
}
}
}
Why is it always does only the last operation to the array(Square in my case). What should I need to change so it will do both Minus and Square ?
Multicast delegates always return the value of the last delegate in chain. Since you don't modify values in Test.Minus and Test.Square, but return new values, only latter is applied. The simplest way to fix this would to make your transformers take values by reference and modify them. e.g:
namespace ConsoleApplication1
{
public delegate void Transformer(ref int x);
class Test
{
public static void Transform(int[] values, Transformer t)
{
for (int i = 0; i < values.Length; i++)
{
t(ref values[i]);
}
}
static void Square(ref int x)
{
x = x * x;
}
static void Minus(ref int x)
{
x = x - 1;
}
static void Main()
{
int[] values = { 1, 2, 3 };
Transformer t = Test.Minus;
t += Test.Square;
Test.Transform(values, t);
foreach (int i in values)
{
Console.Write(i + " ");
}
}
}
}
Because the result is not chained through all the delegates
the code becomes the equivalent of
Minus(1);
return Square(1);
change the code to alter the variable in place.
public delegate void Transformer(ref int x);
public static void Transform(int[] values, Transformer t)
{
for (int i = 0; i < values.Length; i++)
{
t(ref values[i]);
}
}
static void Square(ref int x)
{
x*= x;
}
static void Minus(ref int x)
{
x--;
}
A far better solution would be to use a linq agregate because you could transform the solution without affecting the source.
public static int[] Transform(int[] values, params Func<int,int>[] t){
return values.Select(v=>t.Aggregate(v,(x,f)=>f(x))).ToArray();
}
Then you can just call
values=Transform(values,new[] { Minus,Square });
or
int[] values = {1,2,3};
int[] result = Transform(values,Minus,Square);
After this call values!=result so source is unchanged

Categories