Cast a function as variable - c#

Let be the following function Measure for measurement of execution time for some functnion method
public static TimeSpan Measure(Action method)
{
var stopwatch = new Stopwatch();
stopwatch.Start();
method.Invoke();
stopwatch.Stop();
return stopwatch.Elapsed;
}
This method is launched by the following line of code
var ExecTime = ComplexityCounters.Measure(() => method(int a, int b));
As we can see it's a very huge recall of Measure, so, let's try to short it by the following function
public static TimeSpan ExecTime (Action method)
{
var ExecutionTime = Measure(() => method.Invoke());
return ExecutionTime;
}
But
var ExecTime = ExecTime(method(int a, int b));
gives the error c# cannot convert from 'void' to 'System.Action'. How to fix it ? Or may be is there a way to compose those two function in one ?

here full example
public static TimeSpan Measure(Action method)
{
var stopwatch = new Stopwatch();
stopwatch.Start();
method.Invoke();
stopwatch.Stop();
return stopwatch.Elapsed;
}
public static TimeSpan ExecTime(Action method)
{
var ExecutionTime = Measure(() => method.Invoke());
return ExecutionTime;
}
private static void Main(string[] args)
{
var spentTime = ExecTime(() => Sum(1,2));
}
public static int Sum(int t1, int t2)
{
return t1 + t2;
}
actually you are declaring your variable ExecTime same as your method name ExecTime

Related

Generic function declaration in C#

I'm trying to create some stats about method call duration in a library.
Instead of wrapping each method call to the library with lines to time and track it, I want to create a generic action and function which does these recurring steps.
E.g. for methods that don't return a value, I have created this:
private readonly Action<string, Action> timedAction = (name, action) =>
{
var sw = Stopwatch.StartNew();
action.Invoke();
trackDuration(name, sw.ElapsedMilliseconds);
};
That can be invoked with timedAction("methodname", () => lib.methodname()).
I want to do something similar for methods that return a value, but obviously Action can't be used for that purpose, since it can't return a value.
Is there a way to do this with a generic Func, so I don't have to declare one for each combination of library method parameters?
You can use a generic function like this:
private static TValue FuncHandler<TValue>(string name, Func<TValue> func)
{
var sw = Stopwatch.StartNew();
var result = func();
trackDuration(name, sw.ElapsedMilliseconds);
return result;
}
Call it like this:
var result = FuncHandler("name", () => MyMethod(param1));
Indeed, AOP will buy you more than this sort of tediousness:
https://dotnetfiddle.net/5PLCmM
// Needs to be replicated after Func<T1, TResult>, Func<T1, T2, TResult>, etc, for all the functions arities you'll want to wrap with it
public static TResult Timed<T1, /*T2, etc*/TResult>(out long duration, Func<T1, /*T2, etc*/TResult> func, T1 arg1/*T2 arg2, etc*/)
{
//start timing
var t0 = DateTime.Now;
var result = func(arg1/*, arg2, etc*/);
//end timing
duration = (long)DateTime.Now.Subtract(t0).TotalMilliseconds;
return result;
}
public int Factorial(int n)
{
return n > 0 ? n * Factorial(n - 1) : 1;
}
public int Fibonacci(int n)
{
return n > 1 ? Fibonacci(n - 2) + Fibonacci(n - 1) : n;
}
public static void Main()
{
var program = new Program();
long duration;
var _12bang = Timed(out duration, program.Factorial, 12);
Console.WriteLine("{0}! = {1} in {2} ms", 12, _12bang, duration);
var fib31 = Timed(out duration, program.Fibonacci, 31);
Console.WriteLine("Fib {0} = {1} in {2} ms", 31, fib31, duration);
}
(yes, I know about StopWatch; was just too lazy to put it in there)
'Hope this helps.
In your case AOP will be more tedious. Here is my solution which works:
Class1.cs
using System;
namespace ClassLibrary1
{
public class Class1
{
public void WriteNoParam()
{
Console.WriteLine("void");
}
public void WriteWithParam(string name)
{
Console.WriteLine("My name is: " + name);
}
}
}
Program.cs
using System;
namespace ConsoleApplication2
{
using System.Diagnostics;
using System.Reflection;
using ClassLibrary1;
class Program
{
static void Main(string[] args)
{
var prReflection = new TestReflection<Class1>();
var elapsed = prReflection.TestFunc(new Class1(), #"C:\Users\yasir\Documents\visual studio 2013\Projects\ConsoleApplication2\ClassLibrary1\bin\Debug\ClassLibrary1.dll", "WriteNoParam", new string[0]);
Console.WriteLine("Elapsed time for non parameter method: "+elapsed);
elapsed = prReflection.TestFunc(new Class1(), #"C:\Users\yasir\Documents\visual studio 2013\Projects\ConsoleApplication2\ClassLibrary1\bin\Debug\ClassLibrary1.dll", "WriteWithParam", new[]{"Yasir"});
Console.WriteLine("Elapsed time for parameter method: " + elapsed);
Console.ReadLine();
}
}
public class TestReflection<T> where T: class
{
public Func<T, string, string, string[], long> TestFunc = (arg1, s, s2, arr) =>
{
var assembly = Assembly.LoadFile(s);
var type = assembly.GetType(typeof (T).ToString());
long executionTime;
if (type != null)
{
var methodInfo = type.GetMethod(s2);
if (methodInfo != null)
{
ParameterInfo[] parameters = methodInfo.GetParameters();
object classInstance = Activator.CreateInstance(type, null);
var stopWatch = new Stopwatch();
if (parameters.Length == 0)
{
// This works fine
stopWatch.Start();
methodInfo.Invoke(classInstance, null);
return stopWatch.ElapsedMilliseconds;
}
stopWatch.Start();
methodInfo.Invoke(classInstance, arr); ;
return stopWatch.ElapsedMilliseconds;
}
}
return 0;
};
}
}
I have run in debug mode to test if the console is able to output in milliseconds and it works.
If you don't run in debug, execution will be really fast and console will output 0.
I know this question already has an answer, but I think this solution can be interesting, if you don't want to have to pass the name, yourself, each time, you could do this:
(It was a lot inspired by #selami' answer.)
private MemberInfo GetMethodName<T>(Expression<T> expression)
{
Expression body = expression.Body;
// You might want to complete this
// depending on which expression you want to use
return ((MethodCallExpression)body).Method.Name;
}
// Works for both Action and Func
private object TimedMethodInvoke<T>(Expression<T> funcExpression)
{
var sw = Stopwatch.StartNew();
var result = ((Delegate)(object)funcExpression.Compile()).DynamicInvoke();
trackDuration(GetMethodName(funcExpression), sw.ElapsedMilliseconds);
return result;
}
And your final methods:
public void TimeMethod(Expression<Action> actionExpression)
{
TimedMethodInvoke(actionExpression);
}
public TValue TimeMethod<TValue>(Expression<Func<TValue>> funcExpression)
{
return (TValue)TimedMethodInvoke(funcExpression);
}
I didn't run a benchmark over this solution, but I guess you should encounter a little performance hit, but if you don't mind about that and want to avoid to type the name each time, this could help.

Task.Factory.StartNew Passing return values

i gote the following method and i want to pass the return values of the dosleep method:
static void Main(string[] args)
{
var t1 = Task.Factory.StartNew(() => dosleep(2000));
var t2 = Task.Factory.StartNew(() => dosleep(1000));
Task.WaitAll(t1,t2);
Console.WriteLine("All Done in {0} milliseconds!"); //t1+t2 here!!
}
public static int dosleep(int Milliseconds)
{
System.Threading.Thread.Sleep(Milliseconds);
Console.WriteLine("Task finished");
return Milliseconds;
}
Use the Result property of the Task object
Console.WriteLine("All Done in {0} milliseconds!", t1.Result + t2.Result);

Returning values from threads

If I created a delegate to allow multiple parameters to be passed into the thread start method, as described in this answer, what would be the best way to return a value from the RealStart method to the method which starts the thread?
As I see it, my options are either to create a static variable.
private static Boolean result;
private static String message = "";
public Thread StartTheThread(SomeType param1, SomeOtherType param2) {
var t = new Thread(() => RealStart(param1, param2));
t.Start();
return t;
}
private static void RealStart(SomeType param1, SomeOtherType param2) {
...
}
or to wrap the the delegate in a class
private class TestThread
{
public String message = "";
public Boolean result;
public Thread StartTheThread(SomeType param1, SomeOtherType param2) {
var t = new Thread(() => RealStart(param1, param2));
t.Start();
return t;
}
private static void RealStart(SomeType param1, SomeOtherType param2) {
...
}
}
One issue I see with using a class is that it somewhat negates the point of passing parameters via the delegate as I could pass them into the class when I initialize it.
(Or the third option of not using it in this manner)
Could RealStart ever have a return type?
Are there any pros or cons to using either of the processes described, even if it just comes down to structure/organisation of code?
Use Task, and Task.Result:
// Return a value type with a lambda expression
Task<int> task1 = Task<int>.Factory.StartNew(() => 1);
int i = task1.Result;
// Return a named reference type with a multi-line statement lambda.
Task<Test> task2 = Task<Test>.Factory.StartNew(() =>
{
string s = ".NET";
double d = 4.0;
return new Test { Name = s, Number = d };
});
Test test = task2.Result;
You can use Actions too (for updating form components...):
public TextBox foo = new TextBox();
foo.Text = "foo";
.
.
.
Thread t = new Thread(() => FooBar(p1, p2) );
t.Start();
public void FooBar(Parm parm1, Parm parm2)
{
...
this.foo.BeginInvoke(new Action(() => foo.Text = "bar"));
}

Sum of TimeSpans in C#

I have a collection of objects that include a TimeSpan variable:
MyObject
{
TimeSpan TheDuration { get; set; }
}
I want to use LINQ to sum those times.
Of course, (from r in MyCollection select r.TheDuration).Sum(); doesn't work!
I'm thinking of changing the datatype of TheDuration to an int and then summing it and converting the sum to a TimeSpan. That will be messy because each TheDuration in my collection is used in as a timespan somewhere else.
Any suggestion on this summation?
Unfortunately, there isn't a an overload of Sum that accepts an IEnumerable<TimeSpan>. Additionally, there's no current way of specifying operator-based generic constraints for type-parameters, so even though TimeSpan is "natively" summable, that fact can't be picked up easily by generic code.
One option would be to, as you say, sum up an integral-type equivalent to the timespan instead, and then turn that sum into a TimeSpan again. The ideal property for this is TimeSpan.Ticks, which round-trips accurately. But it's not necessary to change the property-type on your class at all; you can just project:
var totalSpan = new TimeSpan(myCollection.Sum(r => r.TheDuration.Ticks));
Alternatively, if you want to stick to the TimeSpan's + operator to do the summing, you can use the Aggregate operator:
var totalSpan = myCollection.Aggregate
(TimeSpan.Zero,
(sumSoFar, nextMyObject) => sumSoFar + nextMyObject.TheDuration);
This works well (code based on Ani's answer)
public static class StatisticExtensions
{
public static TimeSpan Sum<TSource>(this IEnumerable<TSource> source, Func<TSource, TimeSpan> selector)
{
return source.Select(selector).Aggregate(TimeSpan.Zero, (t1, t2) => t1 + t2);
}
}
Usage :
If Periods is a list of objects with a Duration property
TimeSpan total = Periods.Sum(s => s.Duration)
I believe this is the cleanest LINQ extension:
public static class LinqExtensions
{
public static TimeSpan Sum<TSource>(this IEnumerable<TSource> source, Func<TSource, TimeSpan> func)
{
return new TimeSpan(source.Sum(item => func(item).Ticks));
}
}
Usage is the same:
TimeSpan total = Periods.Sum(s => s.Duration)
Here's what I tried and it worked:
System.Collections.Generic.List<MyObject> collection = new List<MyObject>();
MyObject mb = new MyObject();
mb.TheDuration = new TimeSpan(100000);
collection.Add(mb);
mb.TheDuration = new TimeSpan(100000);
collection.Add(mb);
mb.TheDuration = new TimeSpan(100000);
collection.Add(mb);
var sum = (from r in collection select r.TheDuration.Ticks).Sum();
Console.WriteLine( sum.ToString());
//here we have new timespan that is sum of all time spans
TimeSpan sumedup = new TimeSpan(sum);
public class MyObject
{
public TimeSpan TheDuration { get; set; }
}
I put this in a class to add an extension method to a collection of timespans:
public static class Extensions:
{
public static TimeSpan TotalTime(this IEnumerable<TimeSpan> TheCollection)
{
int i = 0;
int TotalSeconds = 0;
var ArrayDuration = TheCollection.ToArray();
for (i = 0; i < ArrayDuration.Length; i++)
{
TotalSeconds = (int)(ArrayDuration[i].TotalSeconds) + TotalSeconds;
}
return TimeSpan.FromSeconds(TotalSeconds);
}
}
So now, I can write TotalDuration = (my LINQ query that returns a collection of timespan).TotalTime();
Voila!
This works for both a collection, and a property within a collection;
void Main()
{
var periods = new[] {
new TimeSpan(0, 10, 0),
new TimeSpan(0, 10, 0),
new TimeSpan(0, 10, 0),
};
TimeSpan total = periods.Sum();
TimeSpan total2 = periods.Sum(p => p);
Debug.WriteLine(total);
Debug.WriteLine(total2);
// output: 00:30:00
// output: 00:30:00
}
public static class LinqExtensions
{
public static TimeSpan Sum(this IEnumerable<TimeSpan> timeSpanCollection)
{
return timeSpanCollection.Sum(s => s);
}
public static TimeSpan Sum<TSource>(this IEnumerable<TSource> source, Func<TSource, TimeSpan> func)
{
return new TimeSpan(source.Sum(item => func(item).Ticks));
}
}
I created extension method for IEnumerable<TimeSpan>
public static class TimeSpanExtensions
{
public static TimeSpan Sum(this IEnumerable<TimeSpan> source)
{
return source.Aggregate(TimeSpan.Zero, (subtotal, time) => subtotal.Add(time));
}
}
Thanks to that I can use:
IEnumerable<TimeSpan> times = new List<TimeSpan>();
TimeSpan totalTime = times.Sum();
You can use .Aggregate rather than .Sum, and pass it a timespan-summing function that you write, like this:
TimeSpan AddTimeSpans(TimeSpan a, TimeSpan b)
{
return a + b;
}
Once you understand that timespans can't be summed and know to use Ticks, it seems to me that this extension to just convert a long into a timespan looks more linq-ee. I believe it lets the reader have a more readable view of the operation:
var times = new[] { new TimeSpan(0, 10, 0), new TimeSpan(0, 20, 0), new TimeSpan(0, 30, 0) };
times.Sum(p => p.Ticks)
.ToTimeSpan(); // output: 01:00:00
Here is the one extension:
public static class LongExtensions
{
public static TimeSpan ToTimeSpan(this long ticks)
=> new TimeSpan(ticks);
}

C# Memoization of functions with arbitrary number of arguments [closed]

Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
Closed 4 years ago.
This question was caused by a typo or a problem that can no longer be reproduced. While similar questions may be on-topic here, this one was resolved in a way less likely to help future readers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Improve this question
I'm trying to create a memoization interface for functions with arbitrary number of arguments, but I'm failing miserably I feel like my solution is not very flexible. I tried to define an interface for a function which gets memoized automatically upon execution and each function will have to implement this interface. Here is an example with a two parameter Exponential Moving Average function:
class EMAFunction:IFunction
{
Dictionary<List<object>, List<object>> map;
class EMAComparer : IEqualityComparer<List<object>>
{
private int _multiplier = 97;
public bool Equals(List<object> a, List<object> b)
{
List<object> aVals = (List<object>)a[0];
int aPeriod = (int)a[1];
List<object> bVals = (List<object>)b[0];
int bPeriod = (int)b[1];
return (aVals.Count == bVals.Count) && (aPeriod == bPeriod);
}
public int GetHashCode(List<object> obj)
{
// Don't compute hash code on null object.
if (obj == null)
{
return 0;
}
List<object> vals = (List<object>) obj[0];
int period = (int) obj[1];
return (_multiplier * period.GetHashCode()) + vals.Count;
}
}
public EMAFunction()
{
NumParams = 2;
Name = "EMA";
map = new Dictionary<List<object>, List<object>>(new EMAComparer());
}
#region IFunction Members
public int NumParams
{
get;
set;
}
public string Name
{
get;
set;
}
public object Execute(List<object> parameters)
{
if (parameters.Count != NumParams)
throw new ArgumentException("The num params doesn't match!");
if (!map.ContainsKey(parameters))
{
//map.Add(parameters,
List<double> values = new List<double>();
List<object> asObj = (List<object>)parameters[0];
foreach (object val in asObj)
{
values.Add((double)val);
}
int period = (int)parameters[1];
asObj.Clear();
List<double> ema = TechFunctions.ExponentialMovingAverage(values, period);
foreach (double val in ema)
{
asObj.Add(val);
}
map.Add(parameters, asObj);
}
return map[parameters];
}
public void ClearMap()
{
map.Clear();
}
#endregion
}
Here are my tests of the function:
private void MemoizeTest()
{
DataSet dataSet = DataLoader.LoadData(DataLoader.DataSource.FROM_WEB, 1024);
List<String> labels = dataSet.DataLabels;
Stopwatch sw = new Stopwatch();
IFunction emaFunc = new EMAFunction();
List<object> parameters = new List<object>();
int numRuns = 1000;
long sumTicks = 0;
parameters.Add(dataSet.GetValues("open"));
parameters.Add(12);
// First call
for(int i = 0; i < numRuns; ++i)
{
emaFunc.ClearMap();// remove any memoization mappings
sw.Start();
emaFunc.Execute(parameters);
sw.Stop();
sumTicks += sw.ElapsedTicks;
sw.Reset();
}
Console.WriteLine("Average ticks not-memoized " + (sumTicks/numRuns));
sumTicks = 0;
// Repeat call
for (int i = 0; i < numRuns; ++i)
{
sw.Start();
emaFunc.Execute(parameters);
sw.Stop();
sumTicks += sw.ElapsedTicks;
sw.Reset();
}
Console.WriteLine("Average ticks memoized " + (sumTicks/numRuns));
}
Update:
Thanks for pointing out my n00bish error... I always forget to call Reset on the stopwatch!
I've seen another approach to memoization as well... it doesn't offer n-argument memoization, but my approach with the Interface is not much more advantageous since I have to write a class for each function. Is there a reasonable way that I can merge these ideas into something more robust? I want to make it easier to memoize a function without making the user write a class for each function that they intend to use.
How about this? First write a one-argument memoizer:
static Func<A, R> Memoize<A, R>(this Func<A, R> f)
{
var d = new Dictionary<A, R>();
return a=>
{
R r;
if (!d.TryGetValue(a, out r))
{
r = f(a);
d.Add(a, r);
}
return r;
};
}
Straightforward. Now write a function tuplifier:
static Func<Tuple<A, B>, R> Tuplify<A, B, R>(this Func<A, B, R> f)
{
return t => f(t.Item1, t.Item2);
}
And a detuplifier:
static Func<A, B, R> Detuplify<A, B, R>(this Func<Tuple<A, B>, R> f)
{
return (a, b) => f(Tuple.Create(a, b));
}
and now a two-argument memoizer is easy:
static Func<A, B, R> Memoize<A, B, R>(this Func<A, B, R> f)
{
return f.Tuplify().Memoize().Detuplify();
}
To write a three-argument memoizer just keep following this pattern: make a 3-tuplifier, a 3-untuplifier, and a 3-memoizer.
Of course, if you don't need them, there's no need to make the tuplifiers nominal methods:
static Func<A, B, R> Memoize<A, B, R>(this Func<A, B, R> f)
{
Func<Tuple<A, B>, R> tuplified = t => f(t.Item1, t.Item2);
Func<Tuple<A, B>, R> memoized = tuplified.Memoize();
return (a, b) => memoized(Tuple.Create(a, b));
}
UPDATE: You ask what to do if there is no tuple type. You could write your own; it's not hard. Or you could use anonymous types:
static Func<T, R> CastByExample<T, R>(Func<T, R> f, T t) { return f; }
static Func<A, B, R> Memoize<A, B, R>(this Func<A, B, R> f)
{
var example = new { A=default(A), B=default(B) };
var tuplified = CastByExample(t => f(t.A, t.B), example);
var memoized = tuplified.Memoize();
return (a, b) => memoized(new {A=a, B=b});
}
Slick, eh?
UPDATE: C# 7 now has value tuples built in to the language; use them rather than rolling your own or using anonymous types.
First, you need to call sw.Reset() between your tests. Otherwise your results for the second test will be in addition to the time from the first.
Second, you probably shouldn't use vals.GetHashCode() in your GetHashCode() override on the comparer, as this will lead you to getting different hash codes for objects that would evaluate to true for your Equals override. For now, I would worry about making sure that equivalent objects always get the same hash code rather than trying to get an even distribution of the codes. If the hash codes don't match, Equals will never be called, so you'll end up processing the same parameters multiple times.
StopWatch.Stop does not reset the stopwatch so you are accumulating time on each start/stop.
For example
Stopwatch sw = new Stopwatch();
sw.Start();
System.Threading.Thread.Sleep(100);
sw.Stop();
Debug.WriteLine(sw.ElapsedTicks);
sw.Start();
System.Threading.Thread.Sleep(100);
sw.Stop();
Debug.WriteLine(sw.ElapsedTicks);
Gives the following results
228221
454626
You can use StopWatch.Restart (Framework 4.0) to restart the stopwatch each time, or if not Framework 4.0, you can use StopWatch.Reset to reset the stopwatch.
Alternative (to tuples & anonymous types) approach might be as follows:
static void Main(string[] args)
{
var func = Memoize<int, int, int>(Func);
Console.WriteLine(func(3)(4));
Console.WriteLine(func(3)(5));
Console.WriteLine(func(2)(5));
Console.WriteLine(func(3)(4));
}
//lets pretend this is very-expensive-to-compute function
private static int Func(int i, int j)
{
return i + j;
}
private static Func<TArg1, Func<TArg2, TRes>> Memoize<TArg1, TArg2, TRes>(Func<TArg1, TArg2, TRes> func)
{
Func<TArg1, Func<TArg2, TRes>> func1 =
Memoize((TArg1 arg1) => Memoize((TArg2 arg2) => func(arg1, arg2)));
return func1;
}
private static Func<TArg, TRes> Memoize<TArg, TRes>(Func<TArg, TRes> func)
{
var cache = new Dictionary<TArg, TRes>();
return arg =>
{
TRes res;
if( !cache.TryGetValue(arg, out res) )
{
Console.WriteLine("Calculating " + arg.ToString());
res = func(arg);
cache.Add(arg, res);
}
else
{
Console.WriteLine("Getting from cache " + arg.ToString());
}
return res;
};
}
Based on these two Memoize funcs you can easily build extensions for as many args as you wish.
I initially came here just looking for an abstract memoization method for a no-parameter function. This isn't exactly an answer to the question but wanted to share my solution in case someone else came looking for the simple case.
public static class MemoizationExtensions
{
public static Func<R> Memoize<R>(this Func<R> f)
{
bool hasBeenCalled = false; // Used to determine if we called the function and the result was the same as default(R)
R returnVal = default(R);
return () =>
{
// Should be faster than doing null checks and if we got a null the first time,
// we really want to memoize that result and not inadvertently call the function again.
if (!hasBeenCalled)
{
hasBeenCalled = true;
returnVal = f();
}
return returnVal;
};
}
}
If you use LinqPad you can use the following code to easily test out the functionality through the use of LinqPad's super cool Dump method.
new List<Func<object>>(new Func<object>[] {
() => { "Entered func A1".Dump(); return 1; },
() => { "Entered func A2".Dump(); return default(int); },
() => { "Entered func B1".Dump(); return String.Empty; },
() => { "Entered func B2".Dump(); return default(string); },
() => { "Entered func C1".Dump(); return new {Name = String.Empty}; },
() => { "Entered func C2".Dump(); return null; },
})
.ForEach(f => {
var f1 = MemoizationExtensions.Memoize(f);
Enumerable
.Range(1,3)
.Select(i=>new {Run=i, Value=f1()})
.Dump();
});
P.S. You will need to include the MemoizationExtensions class in the code of the LinqPad script otherwise it won't work!

Categories

Resources