Reputation: 17196
I'm trying to create a form that will animate something while processing a particular task (passed as a delegate to the constructor). It's working fine, but the problem I'm having is that I can't instantiate a copy of my generic class if the particular method that I want to perform has a return type of void.
I understand that this is by design and all, but I'm wondering if there is a known workaround for situations like this.
If it helps at all my windows form looks like so (trimmed for brevity):
public partial class operatingWindow<T> : Form
{
public delegate T Operation();
private Operation m_Operation;
private T m_ReturnValue;
public T ValueReturned { get { return m_ReturnValue; } }
public operatingWindow(Operation operation) { /*...*/ }
}
And I call it like:
operatingWindow<int> processing = new operatingWindow<int>(new operatingWindow<int>.Operation(this.doStuff));
processing.ShowDialog();
// ...
private int doStuff()
{
Thread.Sleep(3000);
return 0;
}
Upvotes: 5
Views: 3050
Reputation: 60003
No, you'll need to create an overload to do that.
e.g.
public operatingWindow(Action action)
{
m_Operation=() => { action(); return null; }
}
Also you don't need to define your own delegate, you can use Func<T>
and Action.
Upvotes: 6
Reputation: 564413
I would rethink your design slightly.
If you implemented the processing in a base class, you could subclass it with 2 alternatives that would be nearly interchangable.
The first could be like yours, where it takes an Operation that returns a value. (I would rework this to use Func<T>
instead of having your own delegate type, though.
The second could just take a simple Action and not provide a return value. Both could use the same animation/display/etc. routines, but provide a different way of working. You could also pass this off to other methods using the base class, which would provide a lot of flexibility.
With this approach, you could call this like:
private void DoSleep()
{
Thread.CurrentThread.Sleep(5000);
}
private int ReturnSleep()
{
Thread.CurrentThread.Sleep(5000);
return 5000;
}
...
{
var actionWindow = new OperatingWindowAction(this.DoSleep);
actionWindow.Execute();
var funcWindow = new OperatingWindowFunc<int>(this.ReturnSleep);
funcWindow.Execute();
int result = funcWindow.Result;
}
This would look something like:
public abstract partial class OperatingWindowBase : Form
{
public void Execute()
{
// call this.OnExecute(); asyncronously so you can animate
}
protected abstract void OnExecute();
}
public class OperatingWindowFunc<T> : OperatingWindowBase
{
Func<T> operation;
public T Result { get; private set; }
public OperatingWindowFunc<T>(Func<T> operation)
{
this.operation = operation;
}
protected override OnExecute()
{
this.Result = operation();
}
}
public class OperatingWindowAction
{
Action operation;
public OperatingWindow(Action operation)
{
this.operation = operation;
}
protected override OnExecute()
{
operation();
}
}
Upvotes: 4