2009-03-20 8 views
5

générique que je suis en train de créer une forme qui anime quelque chose lors du traitement d'une tâche particulière (adoptée en tant que délégué au constructeur). Cela fonctionne bien, mais le problème que je rencontre est que je ne peux pas instancier une copie de ma classe générique si la méthode particulière que je veux effectuer a un type de retour de void.passage vide à une classe

Je comprends que ce soit par la conception et tout, mais je me demande s'il y a une solution de contournement connue pour ce genre de situations.

Si elle aide à toutes mes fenêtres sous forme ressemble à ceci (parés par souci de concision):

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) { /*...*/ } 
} 

Et je l'appelle aime:

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

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

    return 0; 
} 

Répondre

4

Je repenserais légèrement votre conception.

Si vous avez implémenté le traitement dans une classe de base, vous pouvez sous-classe avec 2 alternatives qui seraient presque interchangable.

La première pourrait être comme le vôtre, où il faut une opération qui retourne une valeur. (Je voudrais retravailler cela pour utiliser Func<T> au lieu d'avoir votre propre type de délégué, cependant

Le second pourrait juste prendre une action simple et ne pas fournir une valeur de retour.Les deux pourraient utiliser les mêmes routines d'animation/affichage/etc, .. mais fournir une autre façon de travailler vous pouvez également passer ce hors d'autres méthodes utilisant la classe de base, ce qui fournirait une grande flexibilité Avec cette approche

, vous pouvez appeler cela comme:

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; 
} 

Cela ressemblerait à quelque chose comme:

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(); 
    } 
} 
6

Non, vous aurez besoin de créer un surcharge pour le faire.

par exemple.

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

Aussi, vous n'avez pas besoin de définir votre propre délégué, vous pouvez utiliser Func<T> et action.