Chiamare il costruttore di base in C#
-
08-06-2019 - |
Domanda
Se ho ereditare da una classe base e vogliono trasmettere qualcosa dal costruttore della classe ereditata al costruttore della classe base, come devo fare?
Per esempio,
Se ho ereditano dalla classe Exception voglio fare qualcosa di simile a questo:
class MyExceptionClass : Exception
{
public MyExceptionClass(string message, string extraInfo)
{
//This is where it's all falling apart
base(message);
}
}
In pratica quello che voglio è essere in grado di passare la stringa messaggio alla base classe di Eccezione.
Soluzione
Modificare il costruttore al seguente così che si chiama il costruttore della classe base in modo corretto:
public class MyExceptionClass : Exception
{
public MyExceptionClass(string message, string extrainfo) : base(message)
{
//other stuff here
}
}
Nota che un costruttore non è qualcosa che si può chiamare in qualsiasi momento all'interno di un metodo.Per questo motivo si riscontrano errori nella chiamata al costruttore di corpo.
Altri suggerimenti
Si noti che è possibile utilizzare statico metodi per la chiamata al costruttore di base.
class MyExceptionClass : Exception
{
public MyExceptionClass(string message, string extraInfo) :
base(ModifyMessage(message, extraInfo))
{
}
private static string ModifyMessage(string message, string extraInfo)
{
Trace.WriteLine("message was " + message);
return message.ToLowerInvariant() + Environment.NewLine + extraInfo;
}
}
Se avete bisogno di chiamare il costruttore di base, ma non subito, perché il nuovo (derivato) classe richiede manipolazione dei dati, la soluzione migliore è ricorrere a metodi factory.Quello che dovete fare è quello di marchio privato derivata costruttore, e poi di realizzare un metodo statico in classe che farà tutto il materiale necessario e poi chiamare il costruttore e restituire l'oggetto.
public class MyClass : BaseClass
{
private MyClass(string someString) : base(someString)
{
//your code goes in here
}
public static MyClass FactoryMethod(string someString)
{
//whatever you want to do with your string before passing it in
return new MyClass(someString);
}
}
È vero, uso il base
(qualcosa) per chiamare il costruttore della classe base, ma in caso di sovraccarico di utilizzare il this
parola chiave
public ClassName() : this(par1,par2)
{
// do not call the constructor it is called in the this.
// the base key- word is used to call a inherited constructor
}
// Hint used overload as often as needed do not write the same code 2 or more times
public class MyExceptionClass : Exception
{
public MyExceptionClass(string message,
Exception innerException): base(message, innerException)
{
//other stuff here
}
}
È possibile passare eccezione interna di uno dei costruttori.
Da Quadro Di Linee Guida Per La Progettazione e FxCop regole.:
1.Eccezione personalizzato dovrebbe avere un nome che termina con l'Eccezione
class MyException : Exception
2.L'eccezione deve essere pubblica
public class MyException : Exception
3. CA1032:Eccezione implementa standard costruttori.
- Un pubblico costruttore senza parametri.
- Un costruttore pubblico con un argomento di tipo stringa.
- Un costruttore pubblico con una corda e l'Eccezione (come si può avvolgere un'altra Eccezione).
Una serializzazione costruttore protetto se il tipo non è sigillato e privato, se il tipo è sigillato.Basato su MSDN:
[Serializable()] public class MyException : Exception { public MyException() { // Add any type-specific logic, and supply the default message. } public MyException(string message): base(message) { // Add any type-specific logic. } public MyException(string message, Exception innerException): base (message, innerException) { // Add any type-specific logic for inner exceptions. } protected MyException(SerializationInfo info, StreamingContext context) : base(info, context) { // Implement type-specific serialization constructor logic. } }
o
[Serializable()]
public sealed class MyException : Exception
{
public MyException()
{
// Add any type-specific logic, and supply the default message.
}
public MyException(string message): base(message)
{
// Add any type-specific logic.
}
public MyException(string message, Exception innerException):
base (message, innerException)
{
// Add any type-specific logic for inner exceptions.
}
private MyException(SerializationInfo info,
StreamingContext context) : base(info, context)
{
// Implement type-specific serialization constructor logic.
}
}
È anche possibile effettuare un controllo condizionale con parametri nel costruttore, che consente una certa flessibilità.
public MyClass(object myObject=null): base(myObject ?? new myOtherObject())
{
}
o
public MyClass(object myObject=null): base(myObject==null ? new myOtherObject(): myObject)
{
}
class Exception
{
public Exception(string message)
{
[...]
}
}
class MyExceptionClass : Exception
{
public MyExceptionClass(string message, string extraInfo)
: base(message)
{
[...]
}
}
public class MyException : Exception
{
public MyException() { }
public MyException(string msg) : base(msg) { }
public MyException(string msg, Exception inner) : base(msg, inner) { }
}
Come per alcune delle altre risposte elencati qui, è possibile passare parametri al costruttore della classe base.Si consiglia di chiamare il costruttore della classe base all'inizio del costruttore classe ereditata.
public class MyException : Exception
{
public MyException(string message, string extraInfo) : base(message)
{
}
}
Faccio notare che nel tuo esempio hai mai fatto uso di extraInfo
parametro, così ho pensato che si potrebbe desiderare per concatenare i extraInfo
parametro di stringa per la Message
di proprietà del tuo eccezione (sembra che questo viene ignorato accettate risposta e il codice nella tua domanda).
Questo si ottiene semplicemente richiamando il costruttore della classe base, e quindi l'aggiornamento di proprietà del Messaggio con le informazioni supplementari.
public class MyException: Exception
{
public MyException(string message, string extraInfo) : base($"{message} Extra info: {extraInfo}")
{
}
}