2010-12-10 28 views
2

Bonjour mes chers collègues experts,Conception de la signature de fonction - valeur de retour ou paramètre de sortie

Je suis en train de concevoir une fonction qui doit traiter les fichiers dans le dossier. La fonction doit indiquer le nombre de fichiers traités et également s'il y a une erreur. Quelle est la meilleure façon de concevoir une telle fonction? Je choisis entre trois choix:

bool ProcessFiles(out int fileCount) 
{ 
    // return true or false 
} 

int ProcessFiles() 
{ 
    // return -1 when failed 
} 

int ProcessFiles(out bool success) 
{ 
    // return count 
} 

Bien sûr, cet exemple est plutôt une illustration de problèmes réels. Je veux juste élaborer une bonne stratégie.

Répondre

7

Je vais pour:

int ProcessFiles() // returns count 
{ 
    if(error) 
    { 
     throw new MyException(); 
    } 
} 
+0

Mais alors je dois fournir un bloc catch. Plus de codage. –

+1

@captain: Eh bien, sinon, vous devriez avoir du code qui vérifie la valeur de retour, donc vous devez toujours avoir du code. –

2

je pencherais pour

bool ProcessFiles(out int fileCount) 
{ 
    // return true or false 
} 
1

Personnellement, pour une approche mono-thread, je choisirais la première. Cependant, je vous suggère que cette opération en arrière-plan serait préférable et que par conséquent BeginProcessFiles et EndProcessFiles ou un rappel d'événement serait un meilleur moyen de déterminer le succès de l'opération et combien de fichiers ont été traités .

2

Pourquoi ne pas jeter une exception si le processus échoue?

1

Pourquoi ne pas:

int ProcessFiles() 
{ 

    int num_of_files_processed = 0; 

    if(error) 
    { 
     throw new MyException(num_of_files_processed, error_code); 

    return num_of_files_processed; 
} 
1

Je voudrais aussi Choise la solution lancer une exception. Parfois, une exception n'est pas une option (par exemple API). Pourquoi ne pas créer un cours?

public class RetrnClass 
{ 
    public int AmountOfFiles { get; set; } 
    public int ErrorCode { get; set; } 
    public String ErrorMessage { get; set; } 
    public Exception ExceptionObject { get; set; } 
    public bool IsValid { get { return ExceptionObject == null; } } 
    public static implicit operator bool(RetrnClass cls) { return cls.IsValid; } 
} 
1

Que diriez-vous de quelque chose de plus sophistiqué?

class ProcessingResult 
{ 
    public ProcessingResult(IEnumerable<Foo> processedFiles, IEnumerable<Foo> failures) 
    { 
     this.ProcessedFiles = processedFiles; 
     this.Failures = failures ; 
    } 

    public IEnumerable<Foo> ProcessedFiles { get; private set; } 
    public IEnumerable<Foo> Failures { get; private set; } 
} 

Ensuite, vous méthode devient:

ProcessingResult ProcessFiles(IEnumerable<Foo> files) 
{ 
    List<Foo> failures = new List<Foo>(); 
    ProcessingResult result = new ProcessingResult(files, failures); 

    foreach (var foo in files) 
    { 
     // voodoo 

     if (error) 
      failures.Add(foo); 
    } 

    return result; 
} 

Vous pouvez dire s'il y avait des échecs en demandant result.Failures.Any(). La classe ProcessingResult peut facilement être étendue pour contenir plus de détails, comme exactement le problème avec chaque élément défaillant, ou plusieurs problèmes par élément, ce qui peut être plus utile qu'un simple "échec de celui-ci".