2010-09-10 21 views
18

Estoy haciendo un método para obtener una lista de nombres de archivos de un servidor, pero he llegado a un problema que no puedo responder.¿Código de retorno o parámetro de salida?

el método devuelve dos cosas:

  • un SftpResult que es una enumeración con una variedad de códigos de retorno.
  • la lista de nombres de archivos.

De estas tres firmas:

public static ArrayList GetFileList(string directory, out SftpResult result)

public static SftpResult GetFileList(string directory, out ArrayList fileNames)

public static SftpFileListResult GetFileList(string directory)

(donde SftpFileListResult es un objeto compuesto de una SftpResult y un ArrayList)

, ¿cuál es el preferido y por qué?

+1

¿Cuál es el propósito de SftpResult? Si se supone que debe explicar por qué falló la llamada, tal vez deberías lanzar una excepción. – Guillaume

+0

Decidí que sería excesivo, teniendo en cuenta que todo lo que hago es informar el estado. No es un problema grave si falla y realmente no necesito deshacer la pila solo porque escribieron el directorio incorrecto. Acabo de devolver un DirectoryNotFound y continuar con mi negocio :-) – Nobody

+1

Considere abandonar el uso de ArrayList a favor de IEnumerable . –

Respuesta

32

Personalmente prefiero la última opción (aunque usando un List<T> o ReadOnlyCollection<T> en lugar de ArrayList). Los parámetros out son básicamente una forma de devolver valores múltiples, y es generalmente más agradable para encapsularlos.

Otra opción en .NET 4 sería

Tuple<SftpResult, ArrayList> GetFileList(string directory) 

Eso dice explícitamente: "este método devuelve dos cosas ... los he empaquetadas para usted para este caso en particular, pero no vale la pena más encapsulándolos: no vale la pena componerlos en un tipo separado ".

(Si no está utilizando .NET 4 siempre se puede escribir su propio tipo Tuple.)

+0

Gracias, ni siquiera consideré una Tuple. Ese fue mi principal problema con la tercera opción: sentí que realmente no justificaba una clase completamente nueva. – Nobody

+0

+1 también para tuplas, probablemente una de mis cosas favoritas sobre .NET 4. – BoltClock

+0

No puedo contar cuántas clases Tuple personalizadas he creado a lo largo de los años, ¡me alegra que finalmente haya una real! Ahora si solo pudiera obtener nuestro proyecto para actualizar de 3.4 a 4 ... – mikemanne

4

Prefiero la última opción. Los parámetros de salida rara vez se usan y pueden ser sorprendentes/confusos para algunos. Crear un objeto de resultado compuesto es una solución limpia. El único inconveniente es que debe crear una clase únicamente para este fin.

+2

".. rara vez usado y puede ser sorprendente ... "- ¡Intenta decirle eso a un programador C o C++! –

9

yo preferiría envolverlo en un objeto de retorno:

class FileResult 
{ 
    public FileResult(SftpResult resultCode, IEnumerable<string> files) 
    { 
     ResultCode = resultCode; 
     FileList = new List<string>(files); 
    } 
    public SftpResult ResultCode { get; private set; } 
    public IEnumerable<string> FileList { get; private set; } 
} 

Se siente una mucho más limpio para no usar out.

+3

Creo que esa es la última opción presentada ... aunque personalmente la convertiría en inmutable. –

+0

@Jon: Sí, es la última opción, y por supuesto debería ser inmutable . No sé lo que me pasa, no debería estar aquí hoy;) –

3

Diría que es el tercero, ya que encapsula la lógica que necesita en una ubicación. Solo puedo suponer que los métodos de retorno SftpResult y ArrayList deben ser privados y luego compensar la lógica interna del objeto de retorno compuesto.

2

lo haría:

public static bool GetFileList(string directory, out SftpResult result, out ArrayList fileNames) 

lo que no hay confusión acerca de lo que hace la función, y también me gustaría devolver un bool, si el GetFileList puede fallar.

1

¿Por qué no proporcionar los tres? Prefiero no tener parámetros fuera de mi función de llamadas, pero puedo apreciar que en muchas ocasiones son necesarios.Si no sabe qué firma respaldar, entonces apoye los tres. En última instancia, la elección está del lado de la persona que llama y lo mejor que puede hacer es ofrecer esta opción.

+2

En una palabra .. YAGNI .. http://en.wikipedia.org/wiki/You_ain't_gonna_need_it –

2

Si te gustan los diseños donde una función hace dos cosas, entonces usaría una tupla a la Jon o un objeto de retorno a la Fredrik.

Si quería ser todo OOPy de ello se podía permitir que el sistema de tipos hacen el trabajo:

abstract class FtpResult { ... } 
sealed class FileList : FtpResult { ... } 
sealed class Error : FtpResult { ... } 
... 
sealed class FtpService 
{ 
    ... 
    public FtpResult GetFileList(string directory) { ... } 
    ... 
} 
... 
var result = service.GetFileList(dir); 
var error = result as Error; 
var list = result as FileList; 
if (error != null) { ... } 
else if (list != null) 
{ 
    foreach(var name in list.Files) { ... } 
} 
... 
Cuestiones relacionadas