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

Почему в С# нет макросов?

При изучении С# в первый раз я был поражен тем, что у них не было поддержки макросов в той же емкости, что и в C/С++. Я понимаю, что ключевое слово #define существует в С#, но оно значительно отсутствует по сравнению с тем, что я полюбил в C/С++. Кто-нибудь знает, почему макросы реального отсутствуют на С#?

Извиняюсь, если этот вопрос уже задан в той или иной форме - я обещаю, что провел целую 5 минут поиска дубликатов перед публикацией.

4b9b3361

Ответ 1

из С# faq.

http://blogs.msdn.com/CSharpFAQ/archive/2004/03/09/86979.aspx

Почему С# не поддерживает макросы #define? В С++ я могу определить макрос, например:

#define PRODUCT(x, y, z) x * y * z

а затем используйте его в коде:

int a = PRODUCT(3, 2, 1);

С# не позволяет вам это делать. Почему?

Есть несколько причин. Первый из них является читабельным.

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

В С# вы можете использовать методы вместо макросов, и в большинстве случаев JIT будет встраивать их, предоставляя вам одинаковый аспект производительности.

Там также несколько более тонкий вопрос. Макросы выполняются в текстовом режиме, что означает, что если я пишу:

int y = PRODUCT (1 + 2, 3 + 4, 5 + 6)

Я бы ожидал получить то, что дает мне 3 * 7 *11 = 231, но на самом деле расширение, как я определил, дает:

int y = 1 + 2 * 3 + 4 * 5 + 6;

который дает мне 33. Я могу обойти это разумным применением скобок, но очень легко написать макрос, который работает в некоторых ситуациях, а не в других.

Хотя С# строго не имеет препроцессора, он имеет условные символы компиляции, которые могут использоваться для изменения компиляции. Они могут быть определены в коде или с параметрами компилятора. Директивы "предварительной обработки" в С# (названные исключительно для согласованности с C/С++, несмотря на отсутствие отдельного этапа предварительной обработки) (текст, взятый из спецификации ECMA):

#define and #undefИспользуется для определения и определения условных символов компиляции

#if, #elif, #else and #endif

Используется для условного пропуска раздела исходного кода

#lineИспользуется для управления номерами строк, испускаемыми для ошибок и предупреждений.

#error and #warningИспользуется для выдачи ошибок и предупреждений.

#region and #endregion

Используется для явного указания разделов исходного кода.

Дополнительную информацию об этом см. в разделе 9.5 спецификации ECMA. Условная компиляция также может быть достигнута с использованием атрибута Conditional для метода, так что вызовы метода будут скомпилированы только при определении соответствующего символа. Дополнительную информацию об этом см. В разделе 24.4.2 спецификации ECMA.

Автор: Эрик Гуннерсон

Ответ 2

Чтобы вы могли весело набирать ЭТО много раз и снова и снова.

// Windows presetation foundation dependency property.
public class MyStateControl : ButtonBase
{
  public MyStateControl() : base() { }
  public Boolean State
  {
    get { return (Boolean)this.GetValue(StateProperty); }
    set { this.SetValue(StateProperty, value); } 
  }
  public static readonly DependencyProperty StateProperty = DependencyProperty.Register(
    "State", typeof(Boolean), typeof(MyStateControl),new PropertyMetadata(false));
}

Очевидно, что разработчики С# и .NET никогда не используют ни одну из библиотек или фреймворков, которые они создают. Если бы они это сделали, они бы поняли, что определенная форма гигенической синтаксической макросистемы определенно в порядке.

Не позволяйте недостаткам макросов C и С++ lame заставлять вас силою кода, разрешающего компиляцию. Компиляция временного разрешения и генерации кода позволяет более эффективно выражать ЗНАЧЕНИЕ и НАМЕРЕНИЕ кода без необходимости излагать всю информацию об исходном коде. Например, что бы вы могли заменить выше:

public class MyStateControl : ButtonBase
{
  public MyStateControl() : base() { }

  [DependencyProperty(DefaultValue=true)] 
  bool State { get; set; }
}

Boo имеет их, OcamML (по крайней мере, Meta ML) имеет их, а C и С++ имеют их (в отвратительной форме, но лучше, чем не иметь их вообще). С# не работает.

Ответ 3

Макросы в стиле C++ добавляют огромную сложность без соответствующей выгоды, по моему опыту. Я, конечно, не пропустил их ни на С#, ни на Java. (Я редко использую символы препроцессора вообще на С#, но иногда я рад, что они там.)

Теперь разные люди призывают Lisp -строчные макросы, о которых я мало что знаю, но, конечно, звучит довольно приятнее, чем С++-стиль из них.

Что вы особенно хотите делать с макросами? Возможно, мы сможем помочь вам мыслить более идиоматически с помощью С#...

Ответ 4

С# нацелена на более широкую аудиторию (или, в другом смысле, на потребительскую базу), чем на С++, C или ASM. Единственный способ достижения этой цели - добиться того, чтобы программисты стали значительно менее квалифицированными. Поэтому все мощные, но опасные инструменты отбираются. То есть макросы, множественное наследование, управление временем жизни объекта или типом агностического программирования.

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

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

protected int _PropOne;
public int PropOne
{
    get
    {
        return _PropOne;
    }
    set
    {
        if(value == _PropOne) { return; }
        NotifyPropertyChanging("PropOne");
        _PropOne = value;
        NotifyPropertyChanged("PropOne");
    }
}

С макросами каждый раз, когда эти 16 строк будут выглядеть так:

DECLARE_PROPERTY(int, PropOne)
DECLARE_PROPERTY(string, PropTwo)
DECLARE_PROPERTY(BitmapImage, PropThree)

Ответ 5

Макросы в C/С++ использовались для определения констант, создания небольших встроенных функций и для различных вещей, непосредственно связанных с компиляцией кода (#ifdef).

В С# у вас есть строго типизированные константы, достаточно умный компилятор для встроенных функций, когда это необходимо, и знает, как правильно скомпилировать материал (без предварительного сбитого заголовка).

Но нет особой причины, по которой вы не могли запустить свой CS файл с помощью препроцессора C, если вы действительно захотите:)

Ответ 6

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

Мне бы очень хотелось увидеть поддержку макросов, которая была внедрена в Nemerle в С#. Кажется, он добавляет очень естественную и мощную возможность расширения языка. Если вы не посмотрели на это, я действительно рекомендую это сделать.

Есть несколько отличных примеров на Wikipedia.

Ответ 7

Макросы используются в C++, но у них все еще есть их использование, однако большинство из этих применений не имеют значения в C# из-за отражения и лучшего интегрированного использование исключений для сообщений об ошибках.

Ответ 8

В этой статье сравниваются макросы perl и lisp, но точка остается неизменной: макросы уровня текста (perl/С++) вызывают массовые проблемы по сравнению с макросами исходного уровня (lisp)

http://lists.warhead.org.uk/pipermail/iwe/2005-July/000130.html

Уверенные люди, чем я, свернули свой собственный макрос как система в С# http://www.codeproject.com/KB/recipes/prepro.aspx

Ответ 9

Макросы - это инструмент для тех дней, когда большинство программистов были умнее компилятора. В C/С++ все еще есть случаи, когда это верно.

В настоящее время большинство программистов не так умны, как компилятор/время выполнения С#.

Ответ 10

Любой, кто согласен с идеей о том, что макросы плохи, должен прочитать книгу "Сложенными руками". http://en.wikipedia.org/wiki/With_Folded_Hands В нем рассказывается история о том, как мы можем заставлять людей делать глупые вещи до такой степени, чтобы мешать им делать очень мудрые вещи,

В то время как мне нравится С#, я действительно ненавижу, что это способствует глупости реальных инженеров-программистов. Итак, да, оставьте макросы профессионалам. Пока мы на нем, оставьте именование переменных профессионалам. Это может сделать какой-то действительно нечитаемый код. Чтобы следовать полной формулировке "код должен быть в конечном счете доступен для чтения", все переменные должны быть названы A-Z, за ними следует a-z (или какая-либо другая произвольная конструкция, например, только существительные). Потому что некоторые неквалифицированные люди могут назвать свою переменную "SomethingUsefulButNotAllowedByTheCompilerBecauseSomeUsersMayDoDumbThings".

Ответ 11

Вы можете сделать что-то, что делаете с макросами, такими как PropertyChanged, такими способами, как this

Если это лучше, чем макросы? Это вопрос, который вы должны решить:)