Приведенный вами пример должен быть из более ранней версии Angular. В Angular 7 вы бы сделали это следующим образом:
в app.module.ts:
import { HttpClientModule } from '@angular/common/http';
и в @NgModule: imports: [ HttpClientModule ]
затем в вашем компоненте: import { HttpClient, HttpHeaders } from '@angular/common/http';
забудьте о карте, HttpClient использует общие вызовы и публикует правильный тип:
this.http.get<Person[]>('url', options).subscribe(persons => this.persons = persons /* ... */);
я заканчиваю тем, что имел необходимость помнить то, что макрос, и замените им в моей голове, когда я читал.
, Который, кажется, отражается плохо над именованием макросов. Я предположил бы, что Вы не должны будете эмулировать препроцессор, если бы это было log_function_entry()
макрос.
Те, что я встретился, которые были интуитивны и легки понять, всегда были похожи на небольшие мини-функции, таким образом, я всегда задавался вопросом, почему они не были просто функциями.
Обычно они должны быть, если они не должны воздействовать на универсальные параметры.
#define max(a,b) ((a)<(b)?(b):(a))
будет работать над любым типом с <
оператор.
В C99, макросы также позволяют Вам вызывать функции variadic, такие как printf
#define log_message(guard,format,...) \
if (guard) printf("%s:%d: " format "\n", __FILE__, __LINE__,__VA_ARGS_);
log_message( foo == 7, "x %d", x)
, В котором формат работает как printf. Если защита верна, она производит сообщение наряду с номером документа и номером строки, который распечатал сообщение. Если бы это был вызов функции, то это не знало бы файл и строку, от которой Вы назвали его, и использование vaprintf
будет немного большим количеством работы.
В то время как я не большой поклонник макросов и не склонен писать много C больше, на основе моего текущего управления задачами, что-то вроде этого (который мог, очевидно, иметь некоторые побочные эффекты), удобно:
#define MIN(X, Y) ((X) < (Y) ? (X) : (Y))
Теперь я не записал ничего как этот в течение многих лет, но 'функции' как этот были на всем протяжении кода, который я поддержал ранее в моей карьере. Я предполагаю, что расширение можно было считать удобным.
Макросы.. поскольку, когда Ваш & # (* $ & компилятор просто отказывается встраивать что-то.
, Который должен быть мотивационным плакатом, нет?
Во всей серьезности, Google злоупотребление препроцессора (можно видеть подобное ТАК вопрос как результат № 1). Если я пишу макрос, который идет вне функциональности, утверждают (), я обычно пытаюсь видеть, встроил ли мой компилятор на самом деле подобную функцию.
Другие приведут доводы против использования #if для условной компиляции.. они быть бы Вы:
if (RUNNING_ON_VALGRIND)
, а не
#if RUNNING_ON_VALGRIND
.. для отладки целей, так как Вы видите если (), но не #if в отладчике. Тогда мы погружаемся в #ifdef по сравнению с #if.
, Если в соответствии с 10 строками кода, попытайтесь встроить его. Если это не может быть встроено, попытайтесь оптимизировать его. Если его слишком глупое, чтобы быть функцией, сделайте макрос.
Одна из очевидных причин - то, что при помощи макроса, код будет расширен во время компиляции, и Вы получаете псевдо вызов функции без вызова наверху.
Иначе, можно также использовать его для символьных констант, так, чтобы Вы не редактировали то же значение в нескольких местах для изменения одной мелочи.
Учитывая комментарии в Вашем вопросе, Вы не можете осознать, это вызывающее функцию может повлечь за собой изрядное количество издержек. Параметры и ключевые регистры, вероятно, придется скопировать в стек на пути в и стек, раскрученный на выходе. Это особенно было верно для более старых процессоров Intel. Макросы позволили программисту сохранить абстракцию функции (почти), но избежали дорогостоящих издержек вызова функции. Встроенное ключевое слово является консультацией, но компилятор не может всегда разбираться в нем. Слава и опасность 'C' состоят в том, что можно обычно изгибать компилятор к желанию.
В Вашем хлебе с маслом, ежедневное прикладное программирование этот вид микрооптимизации (избегающий вызовов функции) обычно хуже тогда бесполезный, но если Вы пишете строго ограниченную во времени функцию, вызванную ядром операционной системы, тогда это может иметь огромное значение.
Это хорошо для встраивания кода и предотвращения вызова функции наверху. А также использование его, если Вы хотите изменить поведение позже, не редактируя много мест. Это не полезно для сложных вещей, но для простых строк кода, которые Вы хотите встроить, это не плохо.
Один из случая, где макросы действительно сияют, при выполнении генерации кода с ними.
я раньше работал над старой системой C++, которая использовала сменную систему с его собственным способом передать параметры плагину (Используя пользовательскую подобную карте структуру). Некоторые простые макросы использовались, чтобы быть в состоянии иметь дело с этой причудой и разрешались нас для использования реальных классов C++ и функций с нормальными параметрами в плагинах без слишком много проблем. Весь код связующего звена, сгенерированный макросами.
Кроме встраивания для эффективности и условной компиляции, макросы могут использоваться для повышения уровня абстракции низкоуровневого C кода. C действительно не изолирует Вас от деталей основных элементов управления памятью и управления ресурсами и точного расположения данных, и поддерживает очень ограниченные формы сокрытия информации и других механизмов для управления большими системами. С макросами Вы больше не ограничиваетесь использованием только основных конструкций на языке C: можно определить собственные структуры данных и кодирующие конструкции (включая классы и шаблоны!) все еще номинально при записи C!
макросы Препроцессора на самом деле предлагают полный по Тьюрингу язык, выполняемый во время компиляции. Один из впечатляющих (и немного страшный) примеры этого закончен на стороне C++: библиотека Boost Preprocessor использует C99 / C++ 98 препроцессор для создания (относительно) безопасных конструкций программирования, которые тогда расширены до любых базовых объявлений и кодируют Вас вход, или C или C++.
На практике, я рекомендовал бы относительно препроцессора, программирующего как последнее прибежище, когда у Вас нет широты для использования конструкций высокого уровня на более безопасных языках. Но иногда хорошо знать то, что можно сделать, если спина против стены, и ласки приближаются...!
Помните, что макросы (и препроцессор) прибывают с самых ранних дней C. Они раньше были ЕДИНСТВЕННЫМ способом сделать встроенные 'функции' (потому что, конечно, встроенный очень недавнее ключевое слово), и они - все еще единственный способ ВЫНУДИТЬ что-то быть встроенным.
кроме того, макросы являются единственным способом, которым можно сделать такие приемы как вставка файла и строки в строковые константы во время компиляции.
В эти дни, многие вещи, которые макросы раньше были единственным способом сделать, лучше обрабатываются через более новые механизмы. Но у них все еще есть свое место, время от времени.
Эта выборка в значительной степени подводит итог моего представления о вопросе путем сравнения нескольких способов, которыми C
макросы используются, и как реализовать их в D
.
скопированный с DigitalMars.com
Обратный, когда
C
был изобретен, технология компилятора была примитивна. Установка текстового препроцессора макроса на фронтэнд была простым и простым способом добавить много мощных опций. Увеличивающийся размер & сложность программ проиллюстрировала, что эти функции идут со многими свойственными проблемами.D
не имеет препроцессора; ноD
обеспечивает более масштабируемое средство решить те же проблемы.
макросы Препроцессора добавляют мощные опции и гибкость к [1 113]. Но у них есть оборотная сторона:
#include
'десятки тысяч луга строк макроопределений, это становится проблематичным для предотвращения непреднамеренных макрорасширений. Вот перечисление общего использования для макросов и соответствующая функция в D:
Определяющие литеральные константы:
C
Препроцессор Путь
#define VALUE 5
D
Путь
const int VALUE = 5;
Создание списка значений или флагов:
C
Препроцессор Путь
int flags:
#define FLAG_X 0x1
#define FLAG_Y 0x2
#define FLAG_Z 0x4
...
flags |= FLAG_X;
D
Путь
enum FLAGS { X = 0x1, Y = 0x2, Z = 0x4 };
FLAGS flags;
...
flags |= FLAGS.X;
соглашения о вызовах функции Установки:
C
Препроцессор Путь
#ifndef _CRTAPI1
#define _CRTAPI1 __cdecl
#endif
#ifndef _CRTAPI2
#define _CRTAPI2 __cdecl
#endif
int _CRTAPI2 func();
D
Путь
Соглашения о вызовах могут быть определены в блоках, таким образом, нет никакой потребности изменить его для каждой функции:
extern (Windows)
{
int onefunc();
int anotherfunc();
}
Простое универсальное программирование:
C
Препроцессор Путь
Выбор, которые функционируют для использования на основе текстовой замены:
#ifdef UNICODE
int getValueW(wchar_t *p);
#define getValue getValueW
#else
int getValueA(char *p);
#define getValue getValueA
#endif
D
Путь
D
включает объявления символов, которые являются псевдонимами других символов:
version (UNICODE)
{
int getValueW(wchar[] p);
alias getValueW getValue;
}
else
{
int getValueA(char[] p);
alias getValueA getValue;
}
существует больше примеров на веб-сайт DigitalMars .
Это язык программирования (более простой) поверх C, поэтому они полезны для выполнения метапрограммирования во время компиляции ... другими словами, вы можете написать код макроса, который генерирует C код занимает меньше строк и занимает меньше времени, чем его написание непосредственно на C.
Они также очень полезны для написания "функционально-подобных" выражений, которые являются "полиморфными" или "перегруженными"; например, макрос max, определенный как:
#define max(a,b) ((a)>(b)?(a):(b))
, полезен для любого числового типа; а в C вы не можете писать:
int max(int a, int b) {return a>b?a:b;}
float max(float a, float b) {return a>b?a:b;}
double max(double a, double b) {return a>b?a:b;}
...
, даже если хотите, потому что вы не можете перегружать функции.
И не говоря уже об условной компиляции и включении файлов (которые также являются частью макроязыка) ...