【问题标题】:Debug only constructors, not compiled in Release Mode仅调试构造函数,不在发布模式下编译
【发布时间】:2019-04-08 00:50:57
【问题描述】:

有没有办法创建一个不在发布模式下编译的“仅调试”构造函数?

目前我发现的两个解决方案是:

  • 用#if DEBUG 包围构造函数。但是如果你有很多方法/构造函数,这可能会很麻烦
  • 使用 ConditionalAttribute,但它不适用于构造函数,也不适用于返回除 void 之外的任何内容的方法

理想情况下,与 Conditional 相同但具有扩展范围的属性会很棒。

感谢您的帮助。

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){}
}

编辑

正如下面 Cheng Chen 和 Erik Philips 所指出的,这个问题是一个 XY 问题。 更广泛的情况是:我的主要构造函数从 Internet 加载大量资源。但我想用一个加载虚拟值的快速加载构造函数进行调试,只测试特定的函数。我通过创建一个虚拟类而不是工作类的虚拟构造函数来解决它。这个问题可能有更好的解决方案。

所以,底线是:

  • 在构造函数上没有类似 ConditionalAttribute 的属性
  • 您可以使用编译器指令#if DEBUG 来防止在发布模式下编译特定的构造函数/方法。您也可以将它们分组到一个部分类中以获得更好的可读性。
  • 但是,如果您需要这样的构造函数,如果没有其他选择,请三思。

【问题讨论】:

  • 为什么你需要这个? This is an XY Problem,也就是说您认为这样做会解决一些其他问题,而不是询问如何解决该问题,而是希望我们通过您尝试的解决方案来解决问题。
  • 好的,重点。底线:我需要一个快速加载的构造函数来进行调试,而我的常规构造函数需要大量资源。但我不希望这个构造函数在其他任何地方可用。内部可能就足够了
  • 那么为什么你需要一个快速加载的构造函数(你仍然告诉我们你尝试的解决方案,而不是实际的问题)。您在做什么需要在调试期间使用不同的构造函数?
  • 使用默认值而不是其实际值加载数据集(从互联网各地收集)

标签: c# debugging


【解决方案1】:

我觉得这个要求很奇怪。我认为如果您从一开始就解释,您会得到更好的答案,当前的问题更像是对您最初需求的尝试解决方案。

要直接回答您的问题,我们可以在这里使用工厂。

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

    public static Foo FromNormal() { }

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

【讨论】:

  • 你是对的,在编辑中完成。顺便说一句,我认为您缺少工厂构造函数的返回类型:public static Foo FromNormal() { } 和 public static Foo FromDummy(bool dummy) { }。是不是笔误?
  • @XavierAM 谢谢,我直接在浏览器中输入代码,出错了。
【解决方案2】:

您可以尝试使用partial 类。

基本上你把类分成两个文件。一个用于普通实现,另一个用于 Debug Only 实现,它包含在 #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
}

这样你可以将所有不会在发布模式下编译的方法、成员等组织在同一个文件中。

【讨论】:

    【解决方案3】:

    你有更多的问题然后Conditional 属性

    您不能有两个具有相同签名的 构造函数。无论如何,除此之外(我确信这只是一个错字),让我们看看文档:

    Compiler Error CS0592

    属性“属性”在此声明类型上无效。这是 仅对“类型”声明有效。

    当你定义一个属性时,你定义了它可以是什么结构 通过指定 AttributeTargets 值来应用。在下面的 例如,MyAttribute 属性只能应用于接口, 因为 AttributeUsage 属性指定 属性目标。接口。产生错误是因为 属性应用于一个类(A 类)。

    恰好ConditionalAttribute定义如下:

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

    AttributeUsage (C#)

    确定如何使用自定义属性类。 AttributeUsageAttribute 是您应用于自定义属性的属性 定义。 AttributeUsage 属性使您能够控制:

    • 可以应用哪些程序元素属性。除非您限制其使用,否则属性可以应用于以下任何程序元素:程序集、模块、字段、事件、方法、参数、属性、返回、类型
    • 一个属性是否可以多次应用于单个程序元素。
    • 属性是否由派生类继承。

    所以查看文档,您不能在 Constructor 上使用此 Attribute

    但是,您可以做的是使用编译器指令

    #if (C# Reference)

    当 C# 编译器遇到 #if 指令时,最终跟随 通过#endif 指令,它编译指令之间的代码 仅当定义了指定的符号时。

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

    或者

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

    【讨论】:

    • 感谢您发现错字,我更正了构造函数的签名。
    • 您的回答实际上很好地解释了为什么它不起作用,但我的问题是:是否有任何解决方法可以在构造函数上获得“类似条件属性”的行为。
    • @XavierAM 是使用编译器指令,您不能更改属性
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-08-10
    • 1970-01-01
    • 2014-02-18
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多