Подтвердить что ты не робот

Возможно ли метапрограммирование в С#?

В частности, возможно ли иметь код , похожий на этот код С++, выполняемый во время компиляции в С#?

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
}
4b9b3361

Ответ 2

Метапрограммирование возможно в .NET(см. компиляторы компилятора, регулярные выражения, код DOM, отражение и т.д.), но С# не способен к метапрограммированию шаблонов, потому что у него нет этой языковой функции.

Ответ 3

вид поиска шаблонов t4

Извините за iphone и не могу указать на ресурс.

Скотт Ханслеман опубликовал на прошлой неделе об этом.

Ответ 4

Нет, метапрограммирование в С# невозможно.

Ответ 5

Вы должны быть осторожны, когда говорите о времени компиляции при работе с Java или .Net-языками. На этих языках вы можете выполнять более мощные метапрограммирование (в более широком смысле - отражение), чем С++, из-за того, что "время компиляции" (JIT) можно отложить после "времени выполнения";)

Ответ 6

Большинство людей настаивают на попытке метапрограмм изнутри своего любимого языка. Это не работает, если язык не поддерживает метапрограммирование; другие ответы заметили, что С# не делает.

Для этого нужно выполнить метапрограммирование извне языка, используя инструменты преобразования программы. Такие инструменты могут анализировать исходный код и выполнять на нем произвольные преобразования (то, что метапрограммирование делает в любом случае), а затем выплевывать пересмотренную программу.

Если у вас есть система преобразования общей цели, которая может анализировать произвольные языки, вы можете выполнить метапрограммирование на любом языке, который вам нравится. См. Наш DMS Software Reengineering Toolkit для такого инструмента, который имеет надежные интерфейсы для C, С++, Java, С#, COBOL, PHP и количество других языков программирования и было использовано для метапрограммирования по всем этим.

DMS преуспевает, потому что он обеспечивает регулярный метод и поддерживает инфраструктуру для полного доступа к структуре программы как АСТ, и в большинстве случаев дополнительные данные, такие как таблицы символов, информация о типе, управление и анализ потока данных, все необходимое для выполнения сложной программы манипуляция.

EDIT (в ответ на комментарий): можно применить DMS для выполнения задачи OP на С#.

Ответ 7

Существенное различие между .NET Generics и С++ Templates заключается в том, что generics специализируются во время выполнения. Шаблоны расширяются во время компиляции. Динамическое поведение дженериков делает такие вещи, как Linq, деревья выражений, Type.MakeGenericType(), независимость языка и повторное использование кода.

Но есть цена, вы не можете, например, использовать операторы для значений аргумента generic type. Вы не можете написать класс std:: complex в С#. И не метапрограммирование времени компиляции.

Ответ 9

Для очень ограниченной степени, С#, что может быть интерпретировано как метапрограммирование. Но на самом деле это не что иное, как перегрузка. Это реальный этап, чтобы назвать это мета-программированием.

Пример:

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
}

Ответ 11

Не так, как вы просите, но вы можете использовать некоторые из старых трюков С++ для генерации классов, чьи черты указаны статически:

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];
    }
}

Используя это, вы можете определить пространственные классы:

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

Я использую эту технику в библиотеке с множеством подклассов, где для добавления нового элемента данных требуется много шаблонов.