В частности, возможно ли иметь код, похожий на этот код C++, выполняемый во время компиляции в 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
}
Вы можете прочитать «Метапрограммирование в .NET manning.com/hazzard» Кевина Хаззарда и Джейсона Бока.
@ Jordão: Boo - совсем другой язык, а Nemerle более или менее мертв, так как Jetbrains наняли мозги. Возможно, стоит упомянуть Script.NET.
попробуйте взглянуть на script.net; больше информации на --orbifold.net/default/?p=2457
как бы искать шаблоны t4 Извините на iphone, но не могу указать на ресурс. Скотт Ханслеман написал об этом на прошлой неделе.





Нет, в C# метапрограммирование невозможно.
В ограниченной степени очень, C# можно интерпретировать как метапрограммирование. Но на самом деле это не более чем разрешение перегрузки. Назвать это метапрограммированием - настоящее натяжение.
Пример:
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
}
Спрашивающий на самом деле не уточнил, что они подразумевают под метапрограммированием, но я думаю, что можно с уверенностью сказать, что это отличается от того, что вы имеете в виду.
@Anthony, проблема с неоднозначными вопросами в том, что они дают неверные или непреднамеренные ответы. Я не мог ответить на вопрос или дать ответ, который может отвечать на вопрос. Пока я здесь, я думаю, что могу ответить :)
Нет, метапрограммирование такой сложности не поддерживается напрямую языком C#. Однако, как сказал @littlegeek, Набор инструментов для преобразования текстовых шаблонов, включенный в Visual Studio, позволит вам добиться генерации кода любой сложности.
нет проблем, маленький гик; Я проголосовал за то, что ты обыграл меня на 4 часа даже без буфера обмена :)
Ссылка "Text Template Transformation Toolkit" не работает, попробуйте вместо этого: wekeroad.com/2008/10/13/…
@GrantPeters, даже этот сейчас сломан
@StanislavProkop Я удалил неработающую ссылку и поднял статью Скотта Хансельмана на главную.
Существенное различие между универсальными шаблонами .NET и шаблонами C++ заключается в том, что универсальные шаблоны специализируются во время выполнения. Шаблоны расширяются во время компиляции. Динамическое поведение универсальных шаблонов делает возможным использование таких вещей, как Linq, деревья выражений, Type.MakeGenericType (), независимость от языка и повторное использование кода.
Но есть цена, вы не можете, например, использовать операторы для значений аргумента универсального типа. Вы не можете написать класс std :: complex на C#. И никакого метапрограммирования во время компиляции.
Я по опыту знаю, что код шаблона можно использовать повторно. И так называемая «языковая независимость», о которой вы говорите, на самом деле означает, что вы должны использовать язык, совместимый с .net ... Существуют ограничения как для обобщенных шаблонов .net, так и для шаблонов C++. Но это не те.
И, конечно же, вы МОЖЕТЕ написать класс комплексных чисел (или, еще лучше, структуру) на C#, но библиотеки шаблонов, которые выполняют вычисления с параметрами числового типа, трудно написать и использовать, см. codeproject.com/KB/cs/genericnumerics.aspx и codeproject.com/KB/cross-platform/BenchmarkCppVsDotNet.aspx
«Вы не можете написать класс std :: complex на C#». В каком смысле?
@JonHarrop В том смысле, что производительность будет отстой, и вы потеряете безопасность времени компиляции. А некоторые части, связанные с преобразованием, вообще невозможны.
@CodeInChaos: почему вы считаете, что производительность будет отстой, какую безопасность во время компиляции вы теряете и какие части преобразования вообще невозможны?
1) Нет общих ограничений для перегруженных операторов. Таким образом, вы теряете безопасность во время компиляции. 2) Без этих ограничений ни один пользовательский оператор не может быть выбран по специализации. Таким образом, вам нужно использовать генерацию методов времени выполнения, и вы получаете накладные расходы на вызов делегата всякий раз, когда вы вызываете оператор. 3) Вы не можете выразить что-то вроде «если T1 неявно конвертируется в T2, то Complex<T1> должен быть неявно конвертируемым в Complex<T2>».
Вы должны быть осторожны, говоря о времени компиляции, когда имеете дело с языками Java или .Net. На этих языках вы можете выполнять более мощный метапрогамминг (в более широком смысле - отражение-), чем C++, из-за того, что «время компиляции» (JIT) может быть отложено после «времени выполнения»;)
Это будет возможно. Посмотрите выступление Андерса Хейлсберга Будущее C#.
Ваш комментарий был написан в 2009 году. Десять лет спустя это все еще невозможно.
Большинство людей настаивают на попытках метапрограммирования изнутри своего любимого языка. Это не сработает, если язык плохо поддерживает метапрограммирование; другие ответы отметили, что C# этого не делает.
Способ обойти это - выполнить метапрограммирование из языка вне, используя инструменты преобразования программ. Такие инструменты могут анализировать исходный код и выполнять в нем произвольные преобразования (в любом случае это то, что делает метапрограммирование), а затем выплевывать исправленную программу.
Если у вас есть система преобразования программ общего назначения, которая может анализировать произвольные языки, вы можете выполнять метапрограммирование на любом языке, который вам нравится. См. Наш Набор инструментов для реинжиниринга программного обеспечения DMS для такого инструмента, который имеет надежные интерфейсы для C, C++, Java, C#, COBOL, PHP и ряда других языков программирования и используется для метапрограммирования на всех этих языках.
DMS преуспевает, потому что обеспечивает регулярный метод и инфраструктуру поддержки для полного доступа к структуре программы в виде AST, и в большинстве случаев дополнительные данные, такие как таблицы символов, информация о типах, управление и анализ потока данных, все необходимое для сложных манипуляций с программой.
РЕДАКТИРОВАТЬ (в ответ на комментарий): можно применить DMS для реализации задачи OP на C#.
-1: Хороший ответ, но он не отвечает на этот конкретный вопрос.
@Saunders: На самом деле это так, но вам нужно сделать домашнее задание. Если вы хотите реализовать конкретную задачу OP, вам необходимо реализовать преобразования программы с постоянным сворачиванием и сосредоточить их на вызовах вашей функции Фибоначчи. Я отмечаю, что вы изменили мой ответ, когда ни один из ответов также не касался конкретного вопроса OP.
спасибо, вы указали мне правильное направление для того, над чем я работаю!
Метапрограммирование возможно в .NET (см. Компиляторы компилятора, регулярные выражения, код DOM, отражение и т. д.), Но C# не поддерживает метапрограммирование шаблон, потому что в нем нет этой языковой функции.
+1 за краткий и исчерпывающий ответ на все аспекты вопроса.
Не так, как вы спрашиваете, но вы можете использовать некоторые из старых приемов C++ для создания классов, черты которых указаны статически:
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> {}
Я использую эту технику в библиотеке с множеством подклассов, где для добавления нового элемента данных требуется много шаблонов.
Хотя это невозможно в C#, это возможно в альтернативных строго типизированных языках .NET, таких как Бу и Nemerle.