c# - predeterminado - sobrecarga de constructores c++
Llamar al constructor anulado y al constructor base en C# (8)
¿No puedes tener el constructor de Bar que toma una invocación int del constructor sin parámetros?
Tengo dos clases, Foo y Bar, que tienen constructores como este:
class Foo
{
Foo()
{
// do some stuff
}
Foo(int arg)
{
// do some other stuff
}
}
class Bar : Foo
{
Bar() : base()
{
// some third thing
}
}
Ahora quiero introducir un constructor para Bar que toma un int, pero quiero que las cosas que suceden en Bar () se ejecuten , así como las cosas de Foo (int). Algo como esto:
Bar(int arg) : Bar(), base(arg)
{
// some fourth thing
}
¿Hay alguna manera de hacer esto en C #? Lo mejor que tengo hasta ahora es poner el trabajo hecho por Bar () en una función, que también se llama por Bar (int), pero esto es bastante poco elegante.
¿Puedes poner las cosas desde Bar () en Bar (int) y llamar a Bar (int) con Bar () con un valor predeterminado? Entonces Bar (int) puede llamar al constructor base.
class Bar : Foo
{
Bar() : this(0)
{
}
Bar(int arg) : base(arg)
{
}
}
Eso no responde exactamente a su pregunta, pero dependiendo de su escenario podría ser una solución viable.
¿puedes tomar el código de inicialización para Bar () y convertirlo en un método y llamarlo desde ambos constructores, y hacer que el nuevo constructor simplemente llame a base (arg)?
Esto es solo lo que puedo pensar ...
public class Foo
{
public Foo()
{
}
public Foo(int? arg): this()
{
}
}
public class Bar : Foo
{
private int x;
public Bar(): this(new int?()) // edited to fix type ambiguity
{
// stuff that only runs for paramerless ctor
}
public Bar(int? arg)
: base(arg)
{
if (arg.HasValue)
{
// Do stuff for both parameterless and parameterized ctor
}
// Do other stuff for only parameterized ctor
}
}
No, esto no es posible Si usa Reflector para examinar el IL que se genera para cada constructor, verá por qué: terminaría llamando a ambos constructores para la clase base. En teoría, el compilador podría construir métodos ocultos para lograr lo que quiere, pero realmente no hay ninguna ventaja sobre usted haciendo lo mismo explícitamente.
Recomiendo cambiar su cadena de constructores para pasar de la menos específica a la más específica.
class Foo
{
Foo()
{
// do some stuff
}
Foo(int arg): this()
{
// do some other stuff
}
}
class Bar : Foo
{
Bar() : Bar(0)
{
// some third thing
}
Bar(int arg): base(arg)
{
// something
}
}
Cualquier creación del objeto Bar ahora llamará a los 4 constructores. El encadenamiento de constructores debería proporcionar valores predeterminados a constructores más específicos, y no al revés. Deberías mirar lo que estás tratando de lograr y asegurarte de que lo que estás haciendo tenga sentido. Curt tiene razón en que hay razones técnicas por las que no puede hacer esto, pero también hay razones lógicas por las que no debería hacerlo.
Volvería a encadenar constructores, por lo que se llaman como
Bar() : this(0)
Bar(int) : Foo(int) initializes Bar
Foo(int) initializes Foo
Foo() : this(0)
Esto es adecuado, si los constructores sin parámetros están asumiendo algún tipo de valor predeterminado para el parámetro int de otro constructor. Si los constructores no están relacionados, probablemente estés haciendo algo mal con tu tipo, o tal vez necesitamos más información sobre lo que estás tratando de lograr.
Puedes usar este código:
public Foo
{
public Foo()
{
this.InitializeObject();
}
public Foo(int arg) : this()
{
// do something with Foo''s arg
}
protected virtual void InitializeObject()
{
// initialize object Foo
}
}
public Bar : Foo
{
public Bar : base() { }
public Bar(int arg) : base(arg)
{
// do something with Bar''s arg
}
protected override void InitializeObject()
{
// initialize object Bar
base.InitializeObject();
}
}
Simplemente anule el método InitializeObject()
como en el código anterior, y coloque allí todo el código que quiera poner en el constructor sin parámetros. Y finalmente llame a base.InitializeObject()
al final del código.
Espero que esto sea útil.