结构 - 它的用途是什么?

时间:2009-12-28 18:40:46

标签: c# struct

我对struct类型有所了解。但我无法理解:它是为了什么?我什么时候用它?类,简单的值类型和枚举 - 这就是我所需要的。

有什么建议吗?

UPD:请!不要告诉我结构在堆栈中(我知道这个:)。什么结构用于?

10 个答案:

答案 0 :(得分:22)

如果需要值类型语义,则选择结构。如果需要引用类型语义,则选择一个类。所有其他问题都是次要问题。

答案 1 :(得分:9)

MSDN提供了指南:Choosing Between Classes and Structures

  

如果类型的实例很小并且通常是短暂的或者通常嵌入在其他对象中,请考虑定义结构而不是类。

     

除非类型具有以下所有特征,否则不要定义结构:

     
      
  • 它逻辑上表示单个值,类似于基本类型(整数,双精度,>等)。
  •   
  • 实例大小小于16个字节。
  •   
  • 这是不可改变的。
  •   
  • 不必频繁装箱。
  •   

答案 2 :(得分:5)

应该是结构的东西(因为它们是值):

  • struct Color
  • struct Point
  • struct Rectangle
  • struct GLVertex(包含位置,颜色,法线和texcoord)
  • struct DateTime

应该是一个类的东西(因为它们是你所指的东西):

  • class RandomGenerator
  • class Socket
  • class Thread
  • class Window

为什么呢? 请考虑以下代码。

class Button
{
    public Point Location { get; set; }
}

class Program
{
    public static void Main()
    {
        var button = Util.GetButtonFromSomewhere();
        var location = button.Location;
        Util.DrawText("one", location);
        location.Y += 50;
        Util.DrawText("two", location);
        location.Y += 50;
        Util.DrawText("three", location);
    }
}

这将绘制3个垂直对齐的文本标签。但是如果Point是一个类,这也会移动按钮,这是非常意外的:var location = button.Location感觉它应该复制一个值,而不是一个引用!换句话说,我们将Point视为值类型而不是引用类型。这里的“值”用于数学意义上。考虑数字5,它是一个抽象对象“在那里的某个地方”,你只是“引用”它。同样,Point只需。它不会驻留,我们无法更改它。因此我们选择使它成为一个结构,因此它具有用户期望的语义。

另一方面,我们可以class Button { public Window Parent { get; set; } }。在此处,Parent实体,因此我们使用引用类型Window来表示它。使用像myButton.Parent.Redraw();这样的代码可能是有意义的。所以Window应该是一个类。

到目前为止一切顺利。但这一切对你来说可能听起来太模糊了。你如何真正决定某些东西“感觉”像参考或价值?我的经验法则很简单:

Foo a = b; a.Mutate();应该做什么?

  • 如果它看起来应该保持不变,那就让Foo成为一个结构。
  • 否则请上课。

在此处使用principle of least surprise

答案 3 :(得分:4)

简单值类型最好通过struct实现。

  

结构使用指南

     

建议您使用   结构符合任何类型的结构   以下标准:

* Act like primitive types.
* Have an instance size under 16 bytes.
* Are immutable.
* Value semantics are desirable.

您还必须了解在堆上分配了一个类实例。 结构 - 是一个vallue类型 - 并在堆栈上分配。

答案 4 :(得分:4)

首先,您必须了解值类型和引用类型之间的区别。我会假设,因为你说跳过那部分,你明白它是什么。

Struct是一种值类型,您将获得使用值类型的所有权限。

  • 结构按值传递。当你做

    之类的事情

    DateTime time = new DateTime();    DateTime newTime = time;    //你没有引用时间    //相反,您已经创建了一个新实例

  • 结构不是轻量级类,它们可能有很多方法,只需查看DateTime结构。

  • 结构可能性能较轻,但并非总是如此。考虑将大型结构传递给方法。因为每次将结构传递给方法时结构都是值类型,所以创建了结构的新实例,因此每次都复制结构。如果你有一个相当大的结构,这将是一个更大的性能命中。

  • 您可能偶尔会使用box和unbox结构,因为它们是值类型。

简而言之,使用结构来表示内存中的原子值。

答案 5 :(得分:3)

当你想要一个带有值(而不是引用)语义的“类”时,你可以使用结构。

答案 6 :(得分:3)

结构体用于表示某些内容的对象,该内容的标识由存储在其属性中的值定义,而不是由Id或键定义。这些称为“值类型”,而不是称为“实体类型”的对象,其身份随着时间的推移而持续存在,并且不依赖于对象属性的值。

作为示例,Person类(实体)具有从一个会话到另一个会话持续存在的身份,即使是年复一年,尽管人的地址,电话号码,雇主等可能会从一个实例发生变化到另一个。如果您无意中同时在内存中有两个Person类实例(代表相同的个体/实体),那么它们的属性具有相同的值非常重要。

CalendarMonth对象otoh(值类型)只有由该值定义的标识,该值指定它是哪个日历月...无论您使用多少个“March 2009”实例,它们都是可互换的equivilent。另一个例子可能是表示税收计划中的财政年度指定的对象。一个很好的例子是地址对象。 (这里不是谈论地址与个人或企业或任何其他实体的关联,而只是地址本身)。更改地址的任何属性使其成为不同的地址。在内存中创建地址对象后,它与每个具有相同属性的其他地址对象是等效的并且可以互换。这就是为什么这些值类型通常应该是不可变的。如果需要,可以使用所需的属性值创建一个新的,并在完成使用后将其丢弃。

答案 7 :(得分:1)

如果你不知道为什么需要它,你可能不会。

struct是值类型而不是引用类型。如果您不知道这意味着什么,那么您可能根本不需要它。

答案 8 :(得分:1)

示例:假设您希望数据类型表示X Y Z处的坐标。您实际上不需要任何功能,只需要三个变量。一个结构对此有好处,一个类可能有点矫枉过正。

答案 9 :(得分:0)

实际上,我认为struct是来自C的遗产。我认为我们必须在任何条件下使用它。也许有时候你觉得把东西放在堆栈而不是堆上更有效率;但是由于Java / C#永远不会像第一站一样高效,所以只是忽略它:)这是我的观点。