48 votes

Pourquoi n'y a-t-il pas de macros en C #?

Lorsque j'ai appris le C # pour la première fois, j'ai été surpris de constater qu'ils ne supportaient pas les macros de la même capacité que celle utilisée en C / C ++. Je me rends compte que le mot clé #define existe en C #, mais il fait grandement défaut par rapport à ce que j'ai appris à aimer en C / C ++. Est-ce que quelqu'un sait pourquoi les vraies macros manquent dans C #?

Je m'excuse si cette question a déjà été posée, sous une forme ou une autre. Je vous promets que j'ai passé 5 bonnes minutes à chercher des doublons avant de poster.

67voto

DouglasH Points 923

le C# faq.

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

Pourquoi ne pas C# soutien #définir des macros? En C++, je peux définir une macro tels que:

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

et puis l'utiliser dans le code:

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

C# ne vous permettra pas de le faire. Pourquoi?

Il ya quelques raisons pourquoi. La première est l'une des raisons de lisibilité.

L'un de nos principaux objectifs de conception pour le C# est pour avoir un code très lisible. Avoir la capacité à écrire des macros donne au programmeur la possibilité de créer leur propre langage - celui qui n'a pas nécessairement avoir aucune relation avec ce que le code en dessous. Pour comprendre ce que fait le code, l'utilisateur ne doit pas seulement comprendre comment la langue fonctionne, mais il faut aussi comprendre tous les #définir des macros qui sont en vigueur à ce point dans le temps. Qui rend le code beaucoup plus difficile à lire.

En C#, vous pouvez utiliser les méthodes au lieu de macros, et dans la plupart des cas, l'équipe inline, et vous donne le même aspect performance.

Il y a aussi un peu le problème plus subtil. Les Macros sont fait sous forme de texte, ce qui signifie que si j'écris:

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

Je m'attends à quelque chose qui me donne l' 3 * 7 *11 = 231, mais en fait, l'extension, j'ai défini il donne:

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

ce qui me donne 33. Je peux contourner en une application judicieuse de la parenthèse, mais il est très facile à écrire une macro qui fonctionne dans certaines situations et pas dans d'autres.

Bien que le C# n'est pas à proprement parler un pré-processeur, il comporte des symboles de compilation conditionnelle qui peut être utilisée pour affecter la compilation. Ceux-ci peuvent être définies dans le code ou avec des paramètres pour le compilateur. Le "pré-traitement" directives en C# (nommé uniquement pour des raisons de cohérence avec le C/C++, malgré l'absence de séparer les pré-étape de traitement) sont (texte de la spécification ECMA):

#define and #undef Utilisé pour définir et d'annuler la définition des symboles de compilation conditionnelle

#if, #elif, #else and #endif

Utilisé pour conditionnellement ignorer des sections de code source

#line Utilisé pour contrôler les numéros de ligne émis des erreurs et des avertissements.

#error and #warning Utilisé pour émettre des erreurs et des avertissements.

#region and #endregion

Utilisé pour marquer explicitement les sections de code source.

Voir la section 9.5 de la spécification ECMA pour plus d'informations sur le dessus de. Compilation conditionnelle peut également être réalisé à l'aide de l'attribut Conditionnel sur une méthode, de sorte que les appels à la méthode ne pourra être compilé lorsque le symbole est défini. Voir la section 24.4.2 de l'ECMA caractéristiques pour plus d'informations sur cette.

Auteur: Eric Gunnerson

36voto

bencooley Points 151

De sorte que vous pouvez vous amuser à taper CE plus de et plus et plus de nouveau.

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

Bien évidemment, les designers de C# et de .NET jamais utiliser les bibliothèques ou les cadres qu'ils créent. S'ils le faisaient, ils se rendraient compte qu'une certaine forme de hygenic syntaxique système de macro est certainement dans l'ordre.

Ne laissez pas les lacunes de C et de C++boiteux macros aigre-vous sur la puissance de la compilation résolu code. Moment de la compilation, de la résolution et de la génération de code permet de plus d'exprimer le SENS et l'INTENTION de code sans avoir à préciser les tatillonne des détails de la source code. Par exemple, si vous pouviez remplacer le ci-dessus avec ceci:

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

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

Boo a eux, OcamML (au moins Meta ML) de a, et C et le C++ a eux (dans une mauvaise forme, mais c'est mieux que ne pas en avoir du tout). C# n'a pas.

28voto

Jon Skeet Points 692016

C++-style macros ajouter une énorme quantité de complexité sans prestation correspondante, dans mon expérience. Je n'ai certainement pas manqué, que ce soit en C# ou Java. (J'utilise rarement des symboles de préprocesseur à tous en C#, mais je suis parfois heureux, ils sont là.)

Maintenant, plusieurs personnes ont appelé pour Lisp-style macros, que je connais peu, mais certainement son plus agréable que de C++-style.

Que pensez-vous en particulier à faire avec des macros? Nous pouvons être en mesure pour vous aider à penser plus idiomatique C# chemin...

9voto

Agent_L Points 1583

C# est destiné au plus large public (ou en d'autre terme, la consommation de base) qu'en C++, en C ou en ASM. La seule façon d'atteindre cet objectif est d'atteindre les programmeurs considérablement moins qualifiés. Par conséquent, toutes les puissant mais dangereux sont les outils de prise de distance. I. e. les macros, l'héritage multiple, de contrôle sur la durée de vie des objets ou de type indépendant de la programmation.

Dans un très même façon allumettes, couteaux et nailguns sont utiles et nécessaires, mais ils doivent être tenus hors de la portée des enfants. (malheureusement, arsons, les meurtres, les fuites de mémoire et illisible code de toujours arriver).

Et avant de m'accusant de ne pas penser en C#, combien de fois avez-vous écrit que:

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

Avec des macros, chaque fois que ces 16 lignes ressembleraient à ça:

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

4voto

Seth Points 18568

Les macros en C / C ++ ont été utilisées pour définir des constantes, produire de petites fonctions inline et pour diverses choses directement liées à la compilation du code (#ifdef).

En C #, vous avez des constantes fortement typées, un compilateur assez intelligent pour intégrer des fonctions en ligne lorsque cela est nécessaire, et vous savez comment compiler correctement (sans en-tête non-sens précompilé).

Mais il n'y a pas de raison particulière pour laquelle vous ne pouvez pas exécuter votre fichier CS via le préprocesseur C si vous le souhaitez vraiment :)

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X