2008-10-26 17 views
31

W szczególności, byłoby możliwe, aby mieć kod podobny do tego kodu C++ wykonanego w czasie kompilacji w C#?Czy możliwe jest metaprogramowanie w C#?

template <int N> 
struct Factorial 
{ 
    enum { value = N * Factorial<N - 1>::value }; 
}; 

template <> 
struct Factorial<0> 
{ 
    enum { value = 1 }; 
}; 

// Factorial<4>::value == 24 
// Factorial<0>::value == 1 
void foo() 
{ 
    int x = Factorial<4>::value; // == 24 
    int y = Factorial<0>::value; // == 1 
} 
+5

Chociaż nie jest to możliwe w języku C#, jest to możliwe w alternatywnych językach .NET o silnym typie, takich jak [Boo] (http://boo.codehaus.org/) i [Nemerle] (http://nemerle.org/Main_Page). –

+1

Możesz przeczytać Metaprogramming w .NET http://www.manning.com/hazzard przez Kevina Hazzarda i Jason Bocka –

+0

@ Jordão: Boo jest bardzo różnym językiem, a Nemerle jest mniej lub bardziej martwy, ponieważ Jetbrains wynajął mózgi. Być może warto wspomnieć o Script.NET. –

Odpowiedz

30

Nie, metaprogramowanie tej złożoności nie jest obsługiwane bezpośrednio przez język C#. Jednak, jak powiedział @littlegeek, Text Template Transformation Toolkit zawarty w Visual Studio pozwoli ci na generowanie kodu o dowolnej złożoności.

+0

bez problemu littlegeek; Głosowałem na ciebie za pokonanie mnie przez 4 godziny, nawet bez schowka :) –

+0

Bardzo fajne, dzięki. –

+0

Link "Szablon do transformacji szablonów" jest uszkodzony, spróbuj tego zamiast: http://wekeroad.com/2008/10/13/make-visual-studio-generate-your-repository/ –

6

Nie, metaprogramowanie nie jest możliwe w języku C#.

+2

dlaczego w dół, to było zabawne! – GogaRieger

3

Bardzo ograniczony zakres, C#, który można zinterpretować jako meta-programowanie. Ale tak naprawdę to nic więcej niż rozdzielczość przeciążania. Nazywanie go meta-programowaniem jest naprawdę trudne.

Przykład:

static string SomeFunc<T>(T value) { 
    return "Generic"; 
} 
static string SomeFunc(int value) { 
    return "Non-Generic"; 
} 

static void Example() { 
    SomeFunc(42);   // Non-Generic 
    SomeFunc((object)42); // Generic 
} 
+1

Uwielbiam przegłosowywać bez żadnego powodu ani komentarza. – JaredPar

+2

Pytający tak naprawdę nie określił, co rozumieją przez Metaprogramming, ale myślę, że można bezpiecznie powiedzieć, że jest inny od tego, co masz na myśli. – Anthony

+0

@Anthony, problemem z niejednoznacznymi pytaniami są niepoprawne lub niezamierzone odpowiedzi. Nie mogłem odpowiedzieć na pytanie lub udzielić odpowiedzi, która mogłaby odpowiedzieć na pytanie. Dopóki tu jestem, sądzę, że równie dobrze mogę odpowiedzieć :) – JaredPar

9

rodzaju wygląd szablonów t4

Sorry na iPhone i nie może wskazywać na zasób.

Scott Hansleman pisał w zeszłym tygodniu o tym.

+9

Właśnie dlatego SO potrzebuje specjalnej wersji na iPhone'a. – Kredns

4

Zasadniczą różnicą między .NET Generics i C++ Templates jest to, że specjaliści specjalizują się w środowisku wykonawczym. Szablony są rozszerzane w czasie kompilacji. Dynamiczne zachowanie generycznych sprawia, że ​​możliwe są takie rzeczy jak Linq, drzewa ekspresji, Type.MakeGenericType(), niezależność językowa i ponowne używanie kodu.

Ale jest cena, nie można na przykład używać operatorów na wartościach ogólnego argumentu typu. Nie możesz napisać klasy std :: complex w języku C#. I bez metaprogramowania w czasie kompilacji.

+0

Z doświadczenia wiem, że kod szablonu może być ponownie użyty. I tak zwana "niezależność językowa", o której mówisz, oznacza, że ​​musisz używać języka zgodnego z .net ... Istnieją ograniczenia zarówno dla genericów .net, jak i dla szablonów C++. Ale nie są to poprawne. –

+0

I oczywiście, możesz napisać złożoną klasę liczb (lub jeszcze lepiej, struct) w języku C#, ale biblioteki szablonów, które wykonują obliczenia na parametrach typu numerycznego, są trudne do napisania i użycia, zobacz http://www.codeproject.com /KB/cs/genericnumerics.aspx i http://www.codeproject.com/KB/cross-platform/BenchmarkCppVsDotNet.aspx – Qwertie

+0

"Nie można napisać klasy std :: complex w języku C#". W jakim sensie? –

6

Musisz być ostrożny, mówiąc o kompilacji podczas pracy z językami Java lub .Net. W tych językach można wykonać potężniejsze metaprogamming (w szerszym znaczeniu - refleksja-) niż C++ ze względu na fakt, że "czas kompilacji" (JIT) może być odroczony po "uruchomieniu";)

6

Większość osób domaga się metaprogramu w swoim ulubionym języku. To nie działa, jeśli język nie obsługuje dobrze metaprogramowania; inne odpowiedzi zauważyły, że C# nie.

Sposobem na to jest do zrobienia metaprogramowanie z poza językiem, używając program transformation tools. Takie narzędzia mogą analizować kod źródłowy i przeprowadzać na nim dowolne transformacje (to i tak robi metaprogramowanie), a następnie wypluć zmieniony program.

Jeśli posiadasz uniwersalny system transformacji programów, który może analizować dowolne języki, możesz dokonać metaprogramowania na/w dowolnym języku. Zobacz nasze DMS Software Reengineering Toolkit dla takiego narzędzia, które ma solidne przednie końce dla C, C++, Java, C#, COBOL, PHP i wielu innych języków programowania, i było używane do metaprogramowania na wszystkich z nich.

DMS powiedzie się, ponieważ zapewnia regularną metodę i infrastrukturę wsparcia dla pełnego dostępu do struktury programu jako AST, a w większości przypadków dodatkowe dane, takie jak tabele symboli, informacje o typach, kontrola i analiza przepływu danych, wszystko, co niezbędne do zrobienia wyrafinowanego manipulowanie programami.

EDYCJA (w odpowiedzi na komentarz): Można zastosować DMS do realizacji zadania OP na C#.

+2

-1: Dobra odpowiedź, ale nie odpowiada na to konkretne pytanie. –

+1

@Saunders: Właściwie tak, ale masz trochę pracy domowej. Jeśli chcesz wdrożyć określone zadanie PO, musisz wdrożyć stałe składanie transformacji programu i skupić się na wywołaniach do funkcji Fibonacci. Zauważam, że odstąpiłeś od mojej odpowiedzi, gdy żadna z odpowiedzi nie dotyczyła także konkretnego pytania PO. –

+1

dziękuję, wskazałeś mi w dobrym kierunku na coś nad czym pracuję! –

22

METAPROGRAMOWANIE jest możliwe w .NET (patrz kompilatory kompilator wyrażeń regularnych, kod DOM, odbicie itd.), ale C# nie jest w stanie szablonu METAPROGRAMOWANIE ponieważ nie ma tej funkcji języka.

+1

+1 za krótką i kompleksową odpowiedź na każdy aspekt pytania. –

0

Nie w sposób jesteś pytaniem, ale można korzystać z niektórych starych C++ sztuczek, aby wygenerować klas, których cechy są określone statycznie:

abstract class Integer 
{ 
    public abstract int Get { get; } 
} 

public class One : Integer { public override int Get { return 1; } } } 
public class Two : Integer { public override int Get { return 2; } } } 
public class Three : Integer { public override int Get { return 3; } } } 

public class FixedStorage<T, N> where N : Integer, new() 
{ 
    T[] storage; 
    public FixedStorage() 
    { 
     storage = new T[new N().Get]; 
    } 
    public T Get(int i) 
    { 
     return storage[i]; 
    } 
} 

Używanie tego, można zdefiniować klasy przestrzennych:

public class Vector3 : FixedStorage<float, Three> {} 
public class Vector2 : FixedStorage<float, Two> {} 
public class GridCell : FixedStorage<int, Two> {} 

Używam tej techniki w bibliotece, która ma wiele podklas, gdzie dodanie nowego elementu danych wymaga wielu elementów.

Powiązane problemy