2008-09-20 17 views
6

En C#, si tiene varios constructores, se puede hacer algo como esto:varios constructores con una lógica compleja

public MyClass(Guid inputId, string inputName){ 
    // do something 
} 

public MyClass(Guid inputId): this(inputId, "foo") {} 

La idea es de la reutilización de código del curso. Sin embargo, ¿cuál es el mejor enfoque cuando se necesita un poco de lógica compleja? Digamos que quiero este constructor:

public MyClass(MyOtherClass inputObject) 
{ 
    Guid inputId = inputObject.ID; 
    MyThirdClass mc = inputObject.CreateHelper(); 
    string inputText = mc.Text; 
    mc.Dispose(); 
    // Need to call the main Constructor now with inputId and inputText 
} 

La advertencia aquí es que necesito para crear un objeto que tiene que ser eliminados después de su uso. (Aclaración: no de inmediato, pero tengo que llamar a Dispose() en lugar de esperar a Garbage Collection)

Sin embargo, no veo una forma de llamar al constructor base nuevamente si agrego algún código dentro de mi constructor sobrecargado. ¿Hay alguna manera de llamar al constructor base desde dentro de uno sobrecargado?

O es posible utilizar

public MyClass(MyOtherClass inputObject): this(inputObject.ID, 
               inputObject.CreateHelper().Text) 
{} 

¿Esto Desechar automáticamente el objeto generado a partir de CreateHelper()?

Edit: Gracias hasta ahora. Dos problemas: no controlo MyOtherClass y no tengo métodos de extensión (solo .NET 3.0 ...). Sin embargo, yo controlo mi propia clase, y desde que comencé a escribirla, no tengo problemas para refactorizar los constructores si hay un buen enfoque.

Respuesta

17

El patrón más común utilizado para resolver este problema es tener un método Initialize() que sus constructores llaman, pero en el ejemplo que acaba de dar, agregar un método estático al que llamó como el siguiente código, sería el truco .

public MyClass(MyOtherClass inputObject): this(inputObject.ID, GetHelperText(inputObject) {} 

private static string GetHelperText(MyOtherClass o) 
{ 
    using (var helper = o.CreateHelper()) 
     return helper.Text; 
} 
+0

Ese es un enfoque bastante inteligente, creo que lo agregaré a mi libro de mejores prácticas :) Eso funcionará. –

+0

Estoy de acuerdo en que el método de inicialización es el patrón más común. Creo que eso es más consistente con el marco. –

+0

Si pudiera darle un voto triple-cuádruple, lo haría ... – TonyOssa

1

El objeto solo se eliminará automáticamente cuando se ejecute la recolección de elementos no utilizados. Si desea que el disponer para funcionar tan pronto como salió de su alcance, se debe utilizar un bloque de using:

using (MyThirdClass mc = inputObject.CreateHelper()) 
{ 
    // do something with mc 
} 

Esto es realmente más de un problema con el estilo y no es realmente el centro de la cuestión que tenía.

+0

Dado que dijo * que * debe desecharse después del uso, entendí que significa "inmediatamente después del uso", en cuyo caso sería necesario usar un bloque. –

+0

Esto realmente no resuelve el problema planteado, el de cómo realizar una operación lógica en un parámetro y aún caer a través de otro constructor usando el patrón contructor(): this(). –

+0

de hecho. Lo siento si no estaba claro. Mi problema es que necesito llegar a mi constructor base nuevamente con los datos y que tengo que deshacerme de mc y no esperar a que se recoja la basura. Tu ejemplo y el mío son esencialmente lo mismo, usar y llamar a Dispose() explícitamente no hace diferencia para la pregunta. –

2

No veo ninguna razón para creer que la creación de un objeto en el constructor eliminará automáticamente el objeto. Sí, su objeto saldrá inmediatamente del alcance y estará disponible para la recolección de basura, pero ciertamente no es lo mismo que desecharlo.

Realmente no hay una gran manera de hacer exactamente lo que quiere hacer, pero parece que podría beneficiarse de alguna refactorización. Ese es generalmente el caso en mi propio código cuando me encuentro tratando de hacer todo lo posible para crear una sobrecarga de constructor.

Si usted tiene control sobre MyOtherClass, por qué no simplificar el acceso a la propiedad de texto mediante la adición de un método getter que maneja el disponer:

public class MyOtherClass 
{ 
    //... 
    public string GetText() 
    { 
     using (var h = CreateHelper()) 
      return h.Text; 
    } 
} 

si no controlan MyOtherClass se puede utilizar un método de extensión

public static class MyOtherClassExtensions 
{ 
    public static string GetText(this MyOtherClass parent) 
    { 
     using(var helper = parent.CreateHelper()) 
     { 
      return helper.Text; 
     } 
    } 
} 

Luego, por supuesto, en su constructor puede llamar de forma segura

public MyClass(MyOtherClass inputObject): this(inputObject.ID, inputObject.GetText()) {} 
+0

Gracias. No puedo usar ninguno debido a 2 restricciones que acabo de agregar a la pregunta, pero +1 por su respuesta. –

Cuestiones relacionadas