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
Related
Here is example of how to sort array of objects by it's fields. I need to create function which will do same thing but WITHOUT Linq, Generics or any other classes.
p.s You can add methods in Test class to compare fields.
using System;
using System.Linq;
class Test {
public int Count;
public int Sum;
}
class Program {
static void Main() {
Test a1 = new Test() {
Count = 1 ,
Sum = 20
};
Test a2 = new Test() {
Count = 2 ,
Sum = 10
};
Test a3 = new Test() {
Count = 3 ,
Sum = 30
};
var arr = new Test[] { a1, a2, a3};
var result = arr.OrderBy(n => n.Count).ToList();
foreach (var item in result) {
Console.WriteLine(item.Count);
}
}
static void MyOrder() {
//function which will sort passed array of objects by fields
}
}
One method is to use Array.Sort() static method. But if you want to use it, you class must implement IComparable interface, for example:
class Test : IComparable
{
public int Count;
public int Sum;
public int CompareTo(object obj)
{
if (!(obj is Test))
throw new ArgumentException("You can't compare two objects of different types!");
var test = (Test)obj;
if (test.Count < this.Count) return 1;
else if (test.Count > this.Count) return -1;
else return 0;
}
}
And then code would become:
var arr = new Test[] { a1, a3, a2 };
Array.Sort(arr);
EDIT:
If you want to change ordering field at runtime, you can use IComparer interface as folloing:
public class Test
{
public int Count;
public int Sum;
}
public class TestComparerBySum : IComparer<Test>
{
public int Compare(Test x, Test y)
{
if (x.Sum > y.Sum) return 1;
else if (x.Sum < y.Sum) return -1;
else return 0;
}
}
public class TestComparerByCount : IComparer<Test>
{
public int Compare(Test x, Test y)
{
if (x.Count > y.Count) return 1;
else if (x.Count < y.Count) return -1;
else return 0;
}
}
And use it in code like this:
var arr = new Test[] { a3, a2, a1 };
Array.Sort(arr, new TestComparerBySum());
Array.Sort(arr, new TestComparerByCount());
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);
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();
}
}
I recently designed a data structure similar to 'Queue' and 'Stack' for a special purpose, with a fixed maximum number of objects in it and when it is full and inserted, the first inserted object drops out.
The Code:
public class AssemblyLine<T>
{
private long length;
public long Length { get { return this.length; } }
private T[] data;
private long Pointer = 0;
private long count = 0;
public long Count { get { return this.count; } }
public void Insert(T obj)
{
this.Data[Pointer] = obj;
this.Next();
if (this.count < this.length)
this.count++;
}
public T[] GetLastX(long x)
{
long p = this.Pointer;
if (x > this.count)
x = this.count;
T[] result = new T[x];
for (int i = 0; i < x; i++)
{
Previous();
result[i] = Grab();
}
this.Pointer = p;
return result;
}
public T[] GetFirstX(long x)
{
long p = this.Pointer;
if (x > this.count)
x = this.count;
long gap = this.length - this.count;
this.Pointer = (this.Pointer + gap) % this.length;
T[] result = new T[x];
for (int i = 0; i < x; i++)
{
result[i] = Grab();
Next();
}
this.Pointer = p;
return result;
}
public void Clear()
{
this.data = new T[this.length];
this.count = 0;
}
private void Next()
{
this.Pointer++;
if (this.Pointer > this.length - 1)
this.Pointer = 0;
}
private void Previous()
{
this.Pointer--;
if (this.Pointer < 0)
this.Pointer = this.length - 1;
}
private T Grab()
{
return this.data[this.Pointer];
}
public AssemblyLine(long Length)
{
this.length = Length;
this.data = new T[Length];
}
}
Now I am curious if its possible to get that connected to Linq, providing something like this:
AssemblyLine<int> myAssemblyLine = new AssemblyLine(100);
// Insert some Stuff
List<int> myList = myAssemblyLine.Where(i => i > 5).ToList();
Any idea someone?
Almost all LINQ extension methods are declared on IEnumerable<T>, so as soon as your class implements that interface, you'll get it for free.
There are just couple methods that use non-generic IEnumerable, like Cast or OfType, but if you can get your class implement generic IEnumerable<T> it will be much better, because users won't have to call Cast<T> first, to get IEnumerable<T> and access all the other methods (as is right now the case for some legacy collections).
You have to implement IEnumerable<T> for .Where(). See Adding LINQ to my classes.
Once you implement IEnumerable<T> and all required methods, you will have access to these methods: http://msdn.microsoft.com/en-us/library/vstudio/system.linq.enumerable_methods(v=vs.100).aspx
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("----------");
}
}