盲目地将结构转换为类来隐藏默认构造函数?

时间:2009-09-15 20:40:44

标签: c# .net constructor struct default-constructor

我阅读了与此主题相关的所有问题,并且它们都说明了为什么struct上的默认构造函数在C#中不可用的原因,但我还没有找到任何建议采取一般行动的人面对这种情况。

显而易见的解决方案是简单地将struct转换为class并处理后果。

还有其他选项可以将其保留为struct吗?

我使用我们的一个内部商务API对象遇到了这种情况。设计者将它从class转换为struct,现在默认构造函数(之前是私有的)使对象处于无效状态。

我认为如果我们要将对象保持为struct,应该引入一种检查状态有效性的机制(类似于IsValid属性)。我遇到了很多阻力,并解释“使用API​​的人不应该使用默认构造函数”,这一评论肯定引起了我的注意。 (注意:有问题的对象是通过静态工厂方法“正确”构造的,而所有其他构造函数都是internal。)

在这种情况下,每个人都只是简单地将他们的struct转换为class而没有经过深思熟虑吗?

修改:我想看到一些关于如何将此类对象保留为struct的建议 - 上面讨论的对象更适合作为struct而非class 1}}。

3 个答案:

答案 0 :(得分:4)

对于struct,您可以设计类型,以便默认构造的实例(字段全为零)是有效状态。你没有[不会]在没有充分理由的情况下任意使用struct而不是class - 使用不可变引用类型没有任何问题。

我的建议:

  • 确保使用struct的原因是有效的([真实]分析器显示由于非常轻量级的对象的大量分配导致的重大性能问题。)
  • 设计类型,以便默认构造的实例有效。
  • 如果类型的设计由本机/ COM互操作约束决定,请包装功能,不要在包装器外部公开struct(私有嵌套类型)。这样,您就可以轻松记录并验证对约束类型要求的正确使用。

答案 1 :(得分:1)

这样做的原因是CLR特别处理了一个struct(System.ValueType的一个实例):它被初始化,所有字段都是0(或默认值)。你甚至不需要创建一个 - 只需声明它。这就是需要默认构造函数的原因。

你可以通过两种方式解决这个问题:

  1. 创建一个像IsValid这样的属性来指示它是否是一个有效的结构,就像你指示和
  2. 一样
  3. in .Net 2.0考虑使用Nullable< T>允许未初始化(null)结构。
  4. 将结构体更改为类可能会产生一些非常微妙的结果(在多线程环境中更多地出现在内存使用和对象标识方面),并且对于未初始化的对象,非如此微妙但很难调试NullReferenceExceptions。 / p>

答案 2 :(得分:0)

以下表达式说明了无法定义默认构造函数的原因:

new MyStruct[1000];

这里有3个选项

  1. 调用默认构造函数1000次,或
  2. 创建损坏的数据(请注意,结构可以包含引用;如果不初始化或删除引用,则可能会访问任意内存),或者
  3. 用零填充分配的内存(在字节级别)。
  4. .NET对结构体和类执行相同的操作:字段和数组元素用零标记。这也使结构和类之间的行为更加一致,并且没有不安全的代码。它还允许.NET框架不专门化new byte[1000]

    之类的东西

    这是结构.NET需要的默认构造函数并自行处理:将所有字节清零。

    现在,为了解决这个问题,你有几个选择:

    • 向结构添加Am-I-Initialized属性(如HasValue上的Nullable)。
    • 允许归零结构为有效值(如0是小数的有效值)。