将void传递给泛型类

Ste*_*ers 5 c# generics delegates

我正在尝试创建一个表单,在处理特定任务时将其动画化(作为委托人传递给构造函数).它工作正常,但我遇到的问题是,如果我想要执行的特定方法的返回类型为void,我无法实例化我的泛型类的副本.

我知道这是设计和所有,但我想知道是否有这样的情况已知的解决方法.

如果它有助于我的所有窗体看起来像这样(为简洁起见修剪):

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) { /*...*/ }
}
Run Code Online (Sandbox Code Playgroud)

我称之为:

operatingWindow<int> processing = new operatingWindow<int>(new operatingWindow<int>.Operation(this.doStuff));
processing.ShowDialog();

// ... 
private int doStuff()
{
    Thread.Sleep(3000);

    return 0;
}
Run Code Online (Sandbox Code Playgroud)

lak*_*tak 6

不,你需要创建一个重载来做到这一点.

例如

public operatingWindow(Action action) 
{ 
    m_Operation=() => { action(); return null; }
}
Run Code Online (Sandbox Code Playgroud)

此外,您不需要定义自己的委托,您可以使用Func<T>和Action.


Ree*_*sey 4

我会稍微重新考虑一下你的设计。

如果您在基类中实现了处理,则可以使用两个几乎可以互换的替代方案对其进行子类化。

第一个可能像您的那样,它需要一个返回值的操作。(不过,我会重新设计它以使用Func<T>而不是拥有自己的委托类型。

第二个可以只执行一个简单的操作而不提供返回值。两者都可以使用相同的动画/显示/等。惯例,但提供了不同的工作方式。您还可以使用基类将其传递给其他方法,这将提供很大的灵活性。

通过这种方法,您可以这样称呼它:

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;
}
Run Code Online (Sandbox Code Playgroud)

这看起来像:

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();
    }
}
Run Code Online (Sandbox Code Playgroud)