7

我阅读了与该主题相关的所有问题,它们都给出了为什么struct在 C# 中没有默认构造函数的原因,但我还没有找到任何人在遇到这种情况时提出一般的行动方案。

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

还有其他选择可以保留它struct吗?

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

我认为如果我们要将对象保留为 a struct,则应该引入一种检查状态有效性的机制(类似于IsValid属性)。我遇到了很多阻力,并且对“任何使用 API 的人都不应使用默认构造函数”的解释,无疑让我大吃一惊。(注意:有问题的对象是通过静态工厂方法“正确”构造的,所有其他构造函数都是internal。)

是不是大家都在这种情况下不假思索地把structs转成es?class

编辑:我想看到一些关于如何将这种类型的对象保留为 a 的建议struct——上面有问题的对象更适合作为 astruct而不是作为 a class

4

3 回答 3

4

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

我的建议:

  • 确保使用 a 的原因struct是有效的([真正的] 分析器揭示了由于对非常轻量级对象进行大量分配而导致的重大性能问题)。
  • 设计类型,使默认构造的实例有效。
  • 如果类型的设计是由本机/COM 互操作约束决定的,则包装功能并且不要暴露struct包装器的外部(私有嵌套类型)。这样,您可以轻松记录和验证约束类型要求的正确使用。
于 2009-09-15T21:18:12.717 回答
1

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

您可以通过两种方式解决此问题:

  1. 创建一个像 IsValid 这样的属性来指示它是否是一个有效的结构,就像你指出的那样
  2. 在 .Net 2.0 中考虑使用 Nullable<T> 来允许未初始化的(空)结构。

将结构更改为类可能会产生一些非常微妙的后果(就内存使用和对象标识而言,这在多线程环境中出现得更多),并且不那么微妙但难以调试未初始化对象的 NullReferenceExceptions。

于 2009-09-15T20:45:56.450 回答
0

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

new MyStruct[1000];

您在这里有 3 个选项

  1. 调用默认构造函数 1000 次,或
  2. 创建损坏的数据(请注意,结构可以包含引用;如果您不初始化或清除引用,您可能会访问任意内存),或者
  3. 用零(在字节级别)将分配的内存清空。

.NET 对结构和类执行相同的操作:字段和数组元素用零清除。这也使结构和类之间的行为更加一致,并且没有不安全的代码。它还允许 .NET 框架不专门化new byte[1000].

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

现在,要处理这个问题,您有几个选择:

  • 将 Am-I-Initialized 属性添加到结构(如HasValueon Nullable)。
  • 允许归零的结构是有效值(如 0 是小数的有效值)。
于 2009-09-15T21:18:54.620 回答