5 Stimmen

Übergabe von void an eine generische Klasse

Ich versuche ein Formular zu erstellen, das etwas animiert, während es eine bestimmte Aufgabe verarbeitet (übergeben als Delegaten an den Konstruktor). Es funktioniert gut, aber das Problem, das ich habe, ist, dass ich keine Kopie meiner generischen Klasse instanziieren kann, wenn die bestimmte Methode, die ich ausführen möchte, einen Rückgabetyp von void hat.

Ich verstehe, dass dies so vorgesehen ist, aber ich frage mich, ob es eine bekannte Lösung für Situationen wie diese gibt.

Wenn es hilfreich ist, sieht mein Windows-Formular so aus (aus Gründen der Kürze gekürzt):

public partial class operatingWindow : Form
{
    public delegate T Operation();
    private Operation m_Operation;

    private T m_ReturnValue;
    public T ValueReturned { get { return m_ReturnValue; } }

    public operatingWindow(Operation operation) { /*...*/ }
}

Und ich rufe es so auf:

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

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

    return 0;
}

6voto

laktak Punkte 52075

Nein, du musst eine Überladung erstellen, um das zu tun.

z.B.

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

Du musst auch nicht deinen eigenen Delegierten definieren, du kannst Func und Action verwenden.

4voto

Reed Copsey Punkte 536986

Ich würde Ihr Design etwas überdenken.

Wenn Sie die Verarbeitung in einer Basisklasse implementiert hätten, könnten Sie diese mit 2 Alternativen unterteilen, die fast austauschbar wären.

Die erste könnte wie Ihre sein, bei der sie eine Operation verwendet, die einen Wert zurückgibt. (Ich würde das umgestalten, um Func anstelle Ihres eigenen Delegattyps zu verwenden.

Die zweite könnte einfach eine einfache Aktion ausführen und keinen Rückgabewert liefern. Beide könnten die gleichen Animations-/Anzeige-/usw. Routinen verwenden, aber auf unterschiedliche Weise arbeiten. Sie könnten dies auch an andere Methoden mit Hilfe der Basisklasse weitergeben, was eine hohe Flexibilität bieten würde.

Mit diesem Ansatz könnten Sie dies wie folgt aufrufen:

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(this.ReturnSleep);
    funcWindow.Execute();
    int result = funcWindow.Result;
}

Dies würde Ähnlichkeiten mit sich bringen:

public abstract partial class OperatingWindowBase : Form
{
    public void Execute()
    {
        // rufen Sie this.OnExecute(); asynchron auf, damit Sie animieren können
    }
    protected abstract void OnExecute();
}

public class OperatingWindowFunc : OperatingWindowBase
{
    Func operation;
    public T Result { get; private set; }
    public OperatingWindowFunc(Func 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();
    }
}

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X