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
293012345
6789101112
13141516171819
20212223242526
272829303112
3456789