W .NET 3.5 (a konkretniej – C# 3.0 oraz VB 9.0) pojawił się mechanizm “extension methods”. Cel przyświecający jego autorom był zaiste godny uwagi: umożliwienie dodania nowych funkcjonalności do już istniejących, skompilowanych klas. Jedna z kilku “Ruby-like features” wprowadzonych do świata .NET. Przydatność takiego rozwiązania trudno przecenić – w ten sposób rozszerzono m.in. klasy już istniejące w .NET 2.0 (*).
Rodzi się jednak pytanie: w jaki sposób osiągnięto ów cel, skoro wiadomo, że CLR pozostało niezmienione od wersji 2.0(*)? Odpowiedź jest jasna – jakaś “magia” ma miejsce już na poziomie kompilacji do IL, czyli zajęły się tym zespoły tworzące kompilatory C# i VB (kolokwializując – wzięli to na klatę, twardziele).
Zobaczmy:
Przykładowa implementacja metody “doklejonej” do klasy string podczas kompilacji:
1: static class StringExtentions
2: {
3: public static string HeilMe(this string instance)
4: {
5: return string.Format(“Heil {0}!”, instance);
6: }
7: }
Wywołujemy ją w ten cudny sposób:
1: string str = “Ojciec Dyrektor”;
2: Console.WriteLine(str.HeilMe());
Co zrobi z tym kompilator C#? Wynikowy kod IL dla pokazanej operacji:
IL_0008: call string ExtMethods.StringExtentions::HeilMe(string)IL_000d: call void [mscorlib]System.Console::WriteLine(string)
Znajomo? A jakże! Dla porównania zwykła metoda statyczna:
1: static class PreWinFX
2: {
3: public static string HeilString(string instance)
4: {
5: return string.Format(“Heil {0}!”, instance);
6: }
7: }
Wywołana następująco:
1: string str = “Ojciec Dyrektor”;
2: Console.WriteLine(PreWinFX.HeilString(str));
Otrzymany kod IL:
IL_0014: call string ExtMethods.PreWinFX::HeilString(string)IL_0019: call void [mscorlib]System.Console::WriteLine(string)
To samo. Wniosek: kompilator C# wykrywa odwołania do metod zawierających słowo kluczowe this przed pierwszym parametrem i zamienia je na wywołanie klasycznych metod statycznych dostępnych od lat. Sprytny trik.
Wynik wywołania obu metod jest oczywiście taki sam (i – na szczęście – już nie do końca dogmatyczny!):
* – o szczegółach “porządkujących” wiedzę na ten temat napiszę wkrótce. Stay tooned.
Update: zapowiedziany wpis pojawił się tutaj