Il post di ieri di Daniele Mantovani mi ha fatto nascere un dubbio: dal momento che il Common Language Runtime del .NET Framework 3.5 è lo stesso della versione precedente e che gli extension methods sono semplicemente "zucchero sintattico", c'è un modo per utilizzarli anche con i progetti indirizzati a .NET 2.0? La risposta è... sì, è possibile!
Vediamo come fare. Creiamo un progetto .NET 2.0 con Visual Studio 2008 e definiamo la seguente classe:
1 using System;
2 using System.Text;
3
4 namespace ExtensionMethods
5 {
6 public static class Utils
7 {
8 public static byte[] GetBytes(this string str)
9 {
10 return Encoding.Default.GetBytes(str);
11 }
12 }
13 }
Provando a compilare, si ottiene il seguente messaggio di errore:
Cannot define a new extension method because the compiler required type 'System.Runtime.CompilerServices.ExtensionAttribute' cannot be found. Are you missing a reference to System.Core.dll?
Ovviamente, il codice non funziona perché il compilatore non trova l'attributo ExtensionAttribute, contenuto nell'assembly System.Core.dll, che fa parte di .NET 3.5 (Una piccola nota: utilizzare la parola chiave this prima del tipo dell'argomento accettato dal metodo (riga 8) equivale a dire che quel metodo deve essere decorato con l'attributo ExtensionAttribute). Tuttavia, andando ad indagare, si scopre che questo è un attributo "vuoto", ovvero non contiene proprietà sue: in pratica, serve solo al compilatore per fargli capire che stiamo definendo una nuova estensione per il tipo.
A questo punto ci si può chiedere: e se io mi definissi a mano l'attributo mancante? Proviamo. Aggiungiamo un nuovo namespace in fondo alla classe ExtensionMethods, in questo modo:
namespace System.Runtime.CompilerServices
{
public class ExtensionAttribute : Attribute
{ }
}
In pratica, ci siamo definiti a mano l'attributo ExtensionAttribute. Se tentiamo una nuova compilazione, notiamo che ora fila tutto liscio! Facciamo un'ultima prova per verificare il corretto funzionamento. Spostiamoci in un'altra classe e digitiamo il seguente codice:
string s = "Marco";
Console.WriteLine(s.GetBytes()[0]);
Anche in questo caso, la compilazione avviene correttamente: il metodo GetBytes è stato riconosciuto come extension method per il tipo string.