代码之家  ›  专栏  ›  技术社区  ›  Jon Seigel

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

  •  7
  • Jon Seigel  · 技术社区  · 16 年前

    我阅读了与此主题相关的所有问题,它们都给出了为什么 struct 在C中不可用,但我还没有找到任何人在遇到这种情况时建议采取一般行动。

    显而易见的解决方案是简单地转换 结构 到A class 处理后果。

    还有其他的选择吗? 结构 ?

    我使用我们的一个内部商业API对象遇到了这种情况。设计师把它从 到A 结构 ,现在默认构造函数(以前是私有的)使对象处于无效状态。

    我想如果我们要把这个物体 结构 ,应该引入一种检查状态有效性的机制(类似于 IsValid 财产)。我遇到了很多阻力,一个关于“谁使用API就不应该使用默认构造函数”的解释,这无疑引起了我的注意。(注:所讨论的对象是通过静态工厂方法“正确地”构造的,而所有其他构造函数都是 internal )

    每个人都只是在转换他们的 结构 S至 在这种情况下,不需要再考虑吗?

    编辑:我想看看关于如何将这种类型的对象作为 结构 --上面讨论的对象更适合作为 结构 比A .

    3 回复  |  直到 16 年前
        1
  •  4
  •   Sam Harwell    16 年前

    对于一个 struct ,则设计类型,使默认构造实例(字段均为零)为有效状态。你不知道。 不得 ]任意使用 结构 而不是 class 没有好的理由-使用不可变的引用类型没有任何错误。

    我的建议是:

    • 确保使用 结构 是有效的(一个[真实的]探查器揭示了由于一个非常轻量的对象的大量分配而导致的显著性能问题)。
    • 设计类型,使默认构造实例有效。
    • 如果类型的设计是由本机/COM互操作约束决定的,请包装该功能,不要公开 结构 在包装器(私有嵌套类型)之外。这样,您就可以轻松地记录和验证约束类型需求的正确使用。
        2
  •  1
  •   codekaizen    16 年前

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

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

    1. 创建一个类似is valid的属性来指示它是否是有效的结构,就像您指示和
    2. 在.NET 2.0中,考虑使用可为空的<t>来允许未初始化(空)结构。

    将结构更改为类可能会产生一些非常微妙的结果(在多线程环境中,内存使用情况和对象标识会更常见),而且对于未初始化的对象来说,这是非常微妙但很难调试nullreferenceexceptions的。

        3
  •  0
  •   Ruben    16 年前

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

    new MyStruct[1000];
    

    这里有3种选择

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

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

    这是structs.net要求的默认构造函数,它自己负责:将所有字节归零。

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

    • 向结构添加am-i-initialized属性(如 HasValue Nullable )
    • 允许零出结构为有效值(例如0是十进制的有效值)。