C#: uno strano comportamento con l'override

Per una buona comprensione di questo post è necessario conoscere l'ereditarietà a livello elementare e cosa sono i params.

Ieri mi sono trovato all'improvviso in un loop infinito. Per quanto potesse essere chiaro cosa stava succedendo, non mi è stato subito chiaro il PERCHE'.

Oggi ho scritto un po' di codice in modo da mettere la situazione su un "banco di prova".

La necessità era quella di ampliare una classe di log in modo da incorporare una funzionalità inn stile string.format.

   1:          public class clsLogger
   2:          {
   3:              public void scrivi(string Msg)
   4:              {
   5:                  Console.WriteLine("1)" + Msg);
   6:              }
   7:              public void scrivi(string Msg, params object[] arg)
   8:              {
   9:                  scrivi("2)" + string.Format(Msg, arg));
  10:              }
  11:          }
  12:   
  13:   
  14:          static void Main(string[] args)
  15:          {
  16:              Console.WriteLine("********* Test Overload ***********");
  17:   
  18:              clsLogger Test = new clsLogger();
  19:              Test.scrivi("Scrivi");
  20:              Test.scrivi("Scrivi, parametro: {0}", 123456);
  21:   
  22:              Console.ReadKey();
  23:          }

In questo modo il compilatore è perfettamente in grado di distinguere i due metodi: la chiamata scrivi della riga 19 si riferisce al metodo scrivi della riga 3 mentre la chiamata della riga 20 alla funzione scrivi della riga 7.

Complichiamoci un poco la situazione: la nostra classe di log deve estenderne una di base in cui è definito il metodo scrivi semplice.

   1:          public class clsLoggerBase
   2:          {
   3:              public virtual void scrivi(string Msg)
   4:              {
   5:                  Console.WriteLine("1)" + Msg);
   6:              }
   7:          }
   8:   
   9:          public class clsLoggerInherits : clsLoggerBase
  10:          {
  11:              public override void scrivi(string Msg)
  12:              {
  13:                  base.scrivi(Msg);
  14:              }
  15:              public void scrivi(string Msg, params object[] arg)
  16:              {
  17:                  scrivi("2)" + string.Format(Msg, arg));
  18:              }
  19:          }
  20:   
  21:          static void Main(string[] args)
  22:          {
  23:              Console.WriteLine("********* Test Overload ***********");
  24:   
  25:              clsLoggerInherits Test = new clsLoggerInherits();
  26:              Test.scrivi("Scrivi");
  27:              Test.scrivi("Scrivi, parametro: {0}", 123456);
  28:   
  29:              Console.ReadKey();
  30:          }

In questo caso il compilatore referenzia sempre il metodo della riga 15. Questo avviene sia nelle due chiamate alle righe 26 e 27 della funzione Main, sia nella chiamate interna di riga 17 (che diventa ricorsiva generando un'eccezione di stackoverflow).

Anche non sovrascrivendo la funzione scrivi in clsLoggerInherits otteniamo la stessa situazione.

posted @ sabato 1 novembre 2008 15:39

Print
«ottobre»
domlunmarmergiovensab
262728293012
3456789
10111213141516
17181920212223
24252627282930
31123456