0
votes

Déboguer uniquement les constructeurs, non compilés en mode Release

Existe-t-il un moyen de créer un constructeur "Debug Only" qui n'est pas compilé en mode version?

Les deux solutions que j'ai trouvées jusqu'à présent sont:

  • entoure le constructeur d'un #if DEBUG. Mais cela peut être assez fastidieux si vous avez de nombreuses méthodes / constructeurs
  • Utilisez le ConditionalAttribute mais il ne s'applique pas aux constructeurs, ni aux méthodes retournant autre chose que void

Idéalement, un attribut identique à Conditionnel mais avec une portée étendue serait génial.

Merci de votre aide.

public class Foo
{

/// <summary>
/// Main constructor
/// </summary>
public Foo(){}

/// <summary>
/// Debug only constructor
/// </summary>
[Conditional("DEBUG")] //does not compile, wished behavior
internal Foo(bool dummy){}
}

ÉDITER

Comme indiqué ci-dessous par Cheng Chen et Erik Philips, cette question était un problème XY. Le tableau plus large était: mon constructeur principal charge de lourdes ressources d'Internet. Mais je voulais déboguer avec un constructeur à chargement rapide chargeant des valeurs factices, testant uniquement des fonctions spécifiques. Je l'ai résolu en créant une classe factice au lieu d'un constructeur factice d'une classe ouvrière. Il existe peut-être de meilleures solutions à ce problème.

Donc, l'essentiel est:

  • Il n'y a pas d'attribut fonctionnant sur les constructeurs similaires à ConditionalAttribute
  • Vous pouvez entourer avec une directive de compilation #if DEBUG pour empêcher la compilation d'un constructeur / méthode spécifique en mode Release. Vous pouvez également les regrouper dans une classe partielle pour une meilleure lisibilité.
  • Mais, si vous avez besoin d'un tel constructeur, réfléchissez à deux fois s'il n'y a pas d'autres options.


4 commentaires

Pourquoi en avez-vous besoin? Ceci est un problème XY , c'est-à-dire que vous pensez que cela résoudra un autre problème et au lieu de demander comment résoudre ce problème, vous voulez que nous résolvions le problème avec votre tentative de solution.


Très bien, point pris. Bottom line: j'ai besoin d'un constructeur à chargement rapide pour le débogage, alors que mon constructeur habituel prend beaucoup de ressources. Mais je ne veux pas que ce constructeur soit disponible ailleurs. Interne peut-être suffisant


Eh bien, pourquoi avez-vous besoin d'un constructeur à chargement rapide (vous nous parlez toujours de votre tentative de solution, plutôt que du problème réel). Que faites-vous qui nécessite un constructeur différent pendant le débogage?


Chargement d'un ensemble de données avec des valeurs par défaut au lieu de leurs valeurs réelles (collectées à partir des lieux partout sur Internet)


3 Réponses :


0
votes

Vous avez plus de problèmes que l' attribut Conditional .

Vous ne pouvez pas avoir deux constructeurs avec la même signature. Quoi qu'il en soit, cela mis à part (car je suis sûr que ce n'est qu'une faute de frappe), regardons la documentation:

Erreur du compilateur CS0592

L'attribut 'attribut' n'est pas valide sur ce type de déclaration. Il n'est valable que pour les déclarations de type.

Lorsque vous définissez un attribut, vous définissez les constructions auxquelles il peut être appliqué en spécifiant une valeur AttributeTargets. Dans l'exemple suivant, l'attribut MyAttribute peut être appliqué uniquement aux interfaces, car l'attribut AttributeUsage spécifie AttributeTargets.Interface. L'erreur est générée car l'attribut est appliqué à une classe (classe A).

Il se trouve que le ConditionalAttribute est défini comme suit:

public class Foo
{
#if DEBUG
   public Foo() { }
#else
   public Foo() { }
#endif
}

AttributeUsage (C #)

Détermine comment une classe d'attributs personnalisée peut être utilisée. AttributeUsageAttribute est un attribut que vous appliquez aux définitions d'attributs personnalisés. L'attribut AttributeUsage vous permet de contrôler:

  • À quel attribut des éléments de programme peut être appliqué. Sauf si vous restreignez son utilisation, un attribut peut être appliqué à l'un des éléments de programme suivants: assembly, module, field, event, method, param, property, return, type
  • Indique si un attribut peut être appliqué plusieurs fois à un seul élément de programme.
  • Indique si les attributs sont hérités par les classes dérivées.

Donc, en regardant la documentation, vous ne pouvez tout simplement pas utiliser cet attribut sur un constructeur .

Cependant, vous pouvez utiliser une directive du compilateur :

#if (référence C #)

Lorsque le compilateur C # rencontre une directive #if , suivie éventuellement d'une directive #endif , il compile le code entre les directives uniquement si le symbole spécifié est défini.

public class Foo
{    
   public Foo() { }
   
#if DEBUG
   internal Foo2(Something something) { }
#endif
}

Ou

 [AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = true)]


3 commentaires

Merci d'avoir repéré la faute de frappe, j'ai corrigé la signature du constructeur.


Votre réponse explique en fait bien pourquoi cela ne fonctionne pas, mais ma question était: y a-t-il une solution de contournement pour obtenir un comportement "ConditionalAttribute like" sur les constructeurs.


@XavierAM oui utilisez une directive de compilation, vous ne pouvez pas changer l'attribut



0
votes

Vous pouvez essayer d'utiliser des classes partielles .

En gros, vous divisez la classe en deux fichiers. Un pour l'implémentation normale et l'autre pour l'implémentation Debug Only , qui est encapsulée dans la directive du compilateur #if DEBUG .

// Foo.cs
public partial class Foo
{

   /// <summary>
   /// Main constructor
   /// </summary>
   public Foo(){}
}

// Foo.Debug.cs
public partial class Foo
{
  #if DEBUG

  /// <summary>
  /// Debug only constructor
  /// </summary>
  internal Foo(bool dummy){}

  #endif
}

De cette façon, vous pouvez organiser toutes les méthodes, membres, etc. qui ne seront pas compilés en mode version dans le même fichier.


0 commentaires

0
votes

L'exigence me semble étrange. Je pense que vous obtiendrez de meilleures réponses si vous expliquez dès le début, la question actuelle ressemble beaucoup plus à une tentative de solution à votre exigence initiale.

Pour répondre directement à votre question, nous pouvons utiliser une usine ici.

public class Foo
{
    private Foo(){}
    private Foo(bool dummy){}

    public static Foo FromNormal() { }

#if DEBUG
    public static Foo FromDummy(bool dummy) { }
#endif
}


2 commentaires

Vous avez raison, fait dans un Edit. Btw, je pense qu'il vous manque le type de retour pour les constructeurs Factory: public static Foo FromNormal () {} et public static Foo FromDummy (bool dummy) {}. Est-ce une faute de frappe?


@XavierAM Merci, j'ai tapé le code directement dans le navigateur, fait une erreur.