visual programacion parametros parameter opcionales metodo funciones enviar c# .net

programacion - C#constructores con las mismas firmas de parámetros



parametros opcionales c# (7)

Estoy seguro de que este debe ser un problema común. Tengo una clase que en un mundo ideal tendría los siguientes constructores

public Thing(string connectionString) public Thing(string fileName)

Obviamente esto no está permitido porque las firmas son las mismas. ¿Alguien sabe de una solución elegante a este problema?


Aquí hay algunas soluciones.

Tener un constructor que toma una cadena de conexión, y luego tener un método de fábrica en la clase que toma el nombre del archivo. Algo como esto:

public static Thing CreateThing(string fileName)

este método puede llamar a un parámetro privado menos constructor, y puede tomarlo desde allí.

Otra opción es tener una enumeración que tenga dos tipos. FileName y ConnectionString. Entonces solo tiene un constructor que toma una cadena y la enumeración. Luego, según la enumeración, puede determinar qué camino tomar.


Bueno, hay varios potenciales: lo que se considera elegent depende del escenario de uso.

  • Métodos de fábrica estáticos, que llaman a un constructor privado.

    static Thing thingWithFileName(string fileName)

  • Cree un tipo diferente para uno de los parámetros, o use un built-in. En lugar de un string fileName, puede usar System.IO.FileStream. Esto también es más seguro, ya que no puedo pasar accidentalmente los datos incorrectos al método o campo estático incorrecto.

  • Pase un segundo parámetro al constructor, ya sea enum o boolean, indicando la intención del primer parámetro

    enum ThingType { FileName, ConnectionString } Thing(string str, ThingType type) ...

  • Subclass Thing, por lo que tiene ConnectionTypeThing y FileBackedThing

  • Elimine por completo a Thing haciendo su conexión, y tenga las fuentes de datos preconectadas provistas. Entonces terminas con

    Thing(InputStream dataSource)

    o algo análogo.

Mi dinero de "elegancia" sigue la primera o la segunda sugerencia, pero necesitaría más contexto para estar contento con cualquier opción.


En realidad, me parecen diferentes "cosas", ya sea una clase asociada a un archivo o una clase asociada a una base de datos. Definiría una interfaz, luego tendría implementaciones separadas para cada una. Use una fábrica para generar la implementación correcta.

Una sugerencia de que puede necesitar cambiar su diseño es si sus métodos tienen que decidir si están trabajando con un archivo o una base de datos antes de realizar la acción requerida. Si este es el caso, entonces separarme en diferentes clases sería la forma en que iría.

public interface IThing { ... methods to do the things that Things do } public class FileThing : IThing { ... file-based methods } public class DatabaseThing : IThing { ... database-based methods } public static class ThingFactory { public IThing GetFileThing( string name ) { return new FileThing( name ); } public IThing GetDatabaseThing( string connectionString ) { return new DatabaseThing( connectionString ); } }

Si tuviera un comportamiento común, podría definir alternativamente una clase abstracta que contenga el comportamiento predeterminado / común y derivar de ella en lugar de / además de la interfaz.


Haga dos propiedades públicas ConnectionString y FileName y luego utilícelas para completar su objeto.

En C # puedes usar un objeto initalizer. Me gusta esto:

Thing thing = new Thing{FileName = "abc", ConnectionString = "123"};


Me gustan las funciones constructor estáticas:

class Thing { public static Thing NewConnection(string connectionString) { return new Thing(connectionString, true); } public static Thing NewFile(string fileName); { return new Thing(fileName, false); } } . . . { var myObj = Thing.NewConnection("connect=foo"); var Obj2 = Thing.NewFile("myFile.txt"); }

(no se muestra, pero es sencillo, la implementación de Thing-Constructor con un parámetro booleano adicional).


Puede hacer todos los constructores privados y crear métodos de fábrica (métodos estáticos en la clase como CreateFromConnectionString ()).


Puede usar el modismo de constructor nombrado:

public class Thing { private string connectionString; private string filename; private Thing() { /* Make this private to clear things up */ } public static Thing WithConnection(string connectionString) { var thing = new Thing(); thing.connectionString = connectionString; return thing; } public static Thing WithFilename(string filename) { var thing = new Thing(); thing.filename = filename; return thing; } }