передача пустого в общий класс - PullRequest
5 голосов
/ 21 марта 2009

Я пытаюсь создать форму, которая будет анимировать что-то при обработке определенной задачи (передается в качестве делегата в конструктор). Он работает нормально, но проблема в том, что я не могу создать копию своего универсального класса, если конкретный метод, который я хочу выполнить, имеет тип возврата 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) { /*...*/ }
}

И я называю это как:

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

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

    return 0;
}

Ответы [ 2 ]

6 голосов
/ 21 марта 2009

Нет, для этого вам потребуется создать перегрузку.

, например

public operatingWindow(Action action) 
{ 
    m_Operation=() => { action(); return null; }
}

Также вам не нужно определять свой собственный делегат, вы можете использовать Func<T> и Action.

4 голосов
/ 21 марта 2009

Я бы немного переосмыслил ваш дизайн.

Если бы вы реализовали обработку в базовом классе, вы могли бы разделить ее на две альтернативы, которые были бы почти взаимозаменяемыми.

Первый может быть как ваш, где требуется операция, которая возвращает значение. (Однако я бы переработал это, чтобы использовать 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;
}

Это будет выглядеть примерно так:

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();
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...