为什么 C# 中没有宏?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/1369725/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-06 15:46:15  来源:igfitidea点击:

Why aren't there macros in C#?

c#.netmacrosc-preprocessor

提问by Andrew Garrison

When learning C# for the first time, I was astonished that they had no support for macros in the same capacity that exists in C/C++. I realize that the #define keyword exists in C#, but it is greatly lacking compared to what I grew to love in C/C++. Does anyone know why realmacros are missing from C#?

第一次学习 C# 时,我惊讶地发现它们不支持 C/C++ 中存在的相同容量的宏。我意识到 C# 中存在 #define 关键字,但与我在 C/C++ 中逐渐喜欢的关键字相比,它非常缺乏。有谁知道为什么C# 中缺少真正的宏?

I apologize if this question is already asked in some form or another - I promise I spent a solid 5 minutes looking for duplicates before posting.

如果已经以某种形式提出了这个问题,我深表歉意 - 我保证我在发布之前花了 5 分钟的时间寻找重复的内容。

采纳答案by DouglasH

from the C# faq.

来自 C# 常见问题解答。

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

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

Why doesn't C# support #define macros? In C++, I can define a macro such as:

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

and then use it in code:

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

C# doesn't allow you to do this. Why?

There are a few reasons why. The first is one of readability.

One of our main design goals for C# is to keep the code very readable. Having the ability to write macros gives the programmer the ability to create their own language - one that doesn't necessarily bear any relation to what the code underneath. To understand what the code does, the user must not only understand how the language works, but he must also understand all of the #define macros that are in effect at that point in time. That makes code much harder to read.

In C#, you can use methods instead of macros, and in most cases, the JIT will inline them, giving you the same performance aspect.

There's also a somewhat more subtle issue. Macros are done textually, which means if I write:

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

I would expect to get something that gives me 3 * 7 *11 = 231, but in fact, the expansion as I've defined it gives:

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

which gives me 33. I can get around that by a judicious application of parenthesis, but its very easy to write a macro that works in some situations and not in others.

Although C# doesn't strictly speaking have a pre-processor, it does have conditional compilation symbols which can be used to affect compilation. These can be defined within code or with parameters to the compiler. The "pre-processing" directives in C# (named solely for consistency with C/C++, despite there being no separate pre-processing step) are (text taken from the ECMA specification):

#define and #undefUsed to define and undefine conditional compilation symbols

#if, #elif, #else and #endif

Used to conditionally skip sections of source code

#lineUsed to control line numbers emitted for errors and warnings.

#error and #warningUsed to issue errors and warnings.

#region and #endregion

Used to explicitly mark sections of source code.

See section 9.5 of the ECMA specification for more information on the above. Conditional compilation can also be achieved using the Conditional attribute on a method, so that calls to the method will only be compiled when the appropriate symbol is defined. See section 24.4.2 of the ECMA specifcation for more information on this.

Author: Eric Gunnerson

为什么 C# 不支持 #define 宏?在 C++ 中,我可以定义一个宏,例如:

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

然后在代码中使用它:

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

C# 不允许你这样做。为什么?

有几个原因。第一个是可读性。

我们对 C# 的主要设计目标之一是保持代码的可读性。拥有编写宏的能力使程序员能够创建自己的语言——这种语言不一定与下面的代码有任何关系。要了解代码的作用,用户不仅必须了解语言的工作原理,还必须了解当时有效的所有 #define 宏。这使得代码更难阅读。

在 C# 中,您可以使用方法而不是宏,并且在大多数情况下,JIT 将内联它们,为您提供相同的性能方面。

还有一个更微妙的问题。宏是以文本方式完成的,这意味着如果我写:

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

我希望得到一些给我的东西3 * 7 *11 = 231,但实际上,我定义的扩展给出了:

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

这给了我 33。我可以通过明智地应用括号来解决这个问题,但是编写一个在某些情况下有效而在其他情况下无效的宏非常容易。

尽管 C# 严格来说没有预处理器,但它确实有条件编译符号,可用于影响编译。这些可以在代码中定义或与编译器的参数一起定义。C# 中的“预处理”指令(命名只是为了与 C/C++ 保持一致,尽管没有单独的预处理步骤)是(文本取自 ECMA 规范):

#define and #undef用于定义和取消定义条件编译符号

#if, #elif, #else and #endif

用于有条件地跳过源代码部分

#line用于控制为错误和警告发出的行号。

#error and #warning用于发出错误和警告。

#region and #endregion

用于显式标记源代码部分。

有关上述内容的更多信息,请参阅 ECMA 规范的第 9.5 节。也可以使用方法上的 Conditional 属性来实现条件编译,因此只有在定义了适当的符号时才会编译对该方法的调用。有关更多信息,请参阅 ECMA 规范的第 24.4.2 节。

作者:埃里克·冈纳森

回答by Jon Skeet

C++-style macros add a huge amount of complexity without corresponding benefit, in my experience. I certainly haven't missed them either in C# or Java. (I rarely use preprocessor symbols at all in C#, but I'm occasionally glad they're there.)

根据我的经验,C++ 风格的宏增加了大量的复杂性而没有相应的好处。我当然没有在 C# 或 Java 中错过它们。(我很少在 C# 中使用预处理器符号,但我偶尔很高兴它们在那里。)

Now various people have called for Lisp-style macros, which I know little about but certainly sound rather more pleasant than C++-style ones.

现在很多人都呼吁使用Lisp 风格的宏,我对它知之甚少,但听起来肯定比 C++ 风格的更令人愉快。

What do you particularly want to dowith macros? We may be able to help you think in a more idiomatically C# way...

你特别想用宏什么?我们或许可以帮助您以更惯用的 C# 方式思考...

回答by Seth

Macros in C / C++ were used to define constants, produce small inline functions, and for various things directly related to compiling the code (#ifdef).

C / C++ 中的宏用于定义常量、生成小的内联函数,以及用于与编译代码 (#ifdef) 直接相关的各种事情。

In C#, you have strongly typed constants, a smart enough compiler to inline functions when necessary, and knows how to compile stuff the right way (no precompiled header nonsense).

在 C# 中,你有强类型常量,一个足够聪明的编译器可以在必要时内联函数,并且知道如何以正确的方式编译东西(没有预编译头废话)。

But there's no particular reason why you couldn't run your CS file through the C preprocessor first if you really wanted to :)

但是,如果您真的想先通过 C 预处理器运行您的 CS 文件,没有什么特别的原因:)

回答by Motti

Macros are overused in C++but they still have their uses, however most of these uses are not relevant in C#due to reflection and the better integrated use of exceptions for error reporting.

宏在 中被过度使用,C++但它们仍然有其用途,但是C#由于反射和错误报告异常的更好集成使用,这些用途中的大多数都不相关。

回答by Imagist

Macros are a tool for the days when most programmers were smarter than the compiler. In C/C++, there are still some cases where this is true.

在大多数程序员比编译器更聪明的时代,宏是一种工具。在 C/C++ 中,仍有一些情况是这样。

Nowdays, most programmers aren't as smart as the C# compiler/runtime.

现在,大多数程序员都没有 C# 编译器/运行时那么聪明。

回答by Matthew Lock

This article compares perl and lisp macros but the point is still the same: Text level macros (perl/c++) cause massive problems compared to source level macros (lisp)

这篇文章比较了 perl 和 lisp 宏,但要点仍然相同:与源级宏 (lisp) 相比,文本级宏 (perl/c++) 会导致大量问题

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

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

Braver people than me have rolled their own macro like system in c# http://www.codeproject.com/KB/recipes/prepro.aspx

比我更勇敢的人在 c# http://www.codeproject.com/KB/recipes/prepro.aspx 中推出了自己的类似宏的系统

回答by bencooley

So that you can have fun typing THIS over and over and over again.

这样你就可以一遍又一遍地玩这个。

// 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));
}

Obviously the designers of C# and .NET never actually use any of the libraries or frameworks they create. If they did, they would realize that some form of hygenic syntactic macro system is definitely in order.

显然,C# 和 .NET 的设计者从未真正使用过他们创建的任何库或框架。如果他们这样做了,他们就会意识到某种形式的卫生句法宏系统肯定是合适的。

Don't let the shortcomings of C and C++'s lame macros sour you on the power of compile time resolved code. Compile time resolution and code generation allows you to more effectively express the MEANING and INTENT of code without having to spell out all of the niggling details of the source code. For example, what if you could replace the above with this:

不要让 C 和 C++ 的蹩脚宏的缺点让您对编译时解析代码的能力感到厌烦。编译时解析和代码生成使您可以更有效地表达代码的含义和意图,而无需详细说明源代码的所有琐碎细节。例如,如果您可以将上述内容替换为:

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

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

Boo has them, OcamML (at least Meta ML) has them, and C and C++ has them (in a nasty form, but better than not having them at all). C# doesn't.

Boo 有它们,OcamML(至少是 Meta ML)有它们,C 和 C++ 有它们(以令人讨厌的形式,但总比没有它们好)。C# 没有。

回答by Agent_L

C# is aimed at wider audience (or in other term, consumer base) than C++, C or ASM. The only way of achieving this goal is reaching programmers considerably less skilled. Therefore, all the powerful but dangerous tools are taken away. I.e. macros, multiple inheritance, control over object lifetime or type-agnostic programming.

C# 面向比 C++、C 或 ASM 更广泛的受众(或换言之,消费者群)。实现这一目标的唯一方法是接触到技术水平低得多的程序员。因此,所有强大但危险的工具都被带走了。即宏、多重继承、控制对象生命周期或类型不可知的编程。

In a very same way matches, knives and nailguns are useful and necessary, but they have to be kept out of reach of children. (sadly, arsons, murders, memory leaks and unreadable code still do happen).

同样,火柴、刀和钉枪是有用和必要的,但它们必须放在儿童接触不到的地方。(遗憾的是,纵火、谋杀、内存泄漏和不可读的代码仍然会发生)。

And before accusing me of not thinking C#, how many times have you wrote that:

在指责我没有考虑 C# 之前,你写了多少次:

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

With macros, every time those 16 lines would look like that:

使用宏,每次这 16 行看起来像这样:

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

回答by Drew Noakes

As a long time C# programmer who went off to learn C++ for a while, I now miss rich support for metaprogramming C#. At least, I now have a more expansive appreciation for what metaprogramming can mean.

作为一个长期学习 C++ 的 C# 程序员,我现在想念对元编程 C# 的丰富支持。至少,我现在对元编程的含义有了更广泛的了解。

I would really like to see the kind of macro support that's instilled in Nemerlein C#. It seems to add a very natural and powerful extension capability to the language. If you haven't looked at it, I really recommend doing so.

我真的很想看到在 C#中的Nemerle中灌输的那种宏支持。它似乎为语言添加了非常自然和强大的扩展能力。如果你还没有看过它,我真的建议你这样做。

There are some great examples on Wikipedia.

维基百科上有一些很好的例子。

回答by Chaka

You can do some thing you do with macros like PropertyChanged with ways like this

你可以用像这样的方式用像 PropertyChanged 这样的宏做一些你做的事情

If thats better than macros ? Thats a question YOU must decide :)

如果那比宏更好?这是一个你必须决定的问题:)