关于c#:struct – 它的用途是什么?

struct - what is it for?

我对struct型有些了解。但我不明白:这是为了什么?我什么时候用的?类、简单值类型和枚举——这就是我所需要的。

有什么建议吗?

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


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


msdn提供了一个指南:在类和结构之间进行选择:

Consider defining a structure instead of a class if instances of the type are small and commonly short-lived or are commonly embedded in other objects.

Do not define a structure unless the type has all of the following characteristics:

  • It logically represents a single value, similar to primitive types (integer, double, > and so on).
  • It has an instance size smaller than 16 bytes.
  • It is immutable.
  • It will not have to be boxed frequently.


应该是结构的事物(因为它们是值):

  • struct Color
  • struct Point
  • struct Rectangle
  • struct GLVertex(包含位置、颜色、普通和texcoord)
  • struct DateTime

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

  • class RandomGenerator
  • 7
  • class Thread
  • class Window

为什么?考虑下面的代码。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
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感觉应该复制一个值,而不是引用!换句话说,我们认为点是值类型,而不是引用类型。"这里的"值"是用在数学意义上的值。考虑数字5,它是一个抽象的对象,"在外面的某个地方",你只是"指"它。同样,一个简单的点就是。它不在任何地方,我们不能改变它。因此,我们选择将其作为一个结构,因此它具有用户期望的语义。

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

到现在为止,一直都还不错。但这一切对你来说可能太模糊了。你如何真正决定某个"感觉"的东西是参考还是价值?我的经验法则很简单:

Foo a = b; a.Mutate();该怎么办?

  • 如果它看起来应该保持b不变,则使foo成为一个结构。
  • 否则就把它变成一个类。

这里使用最小惊喜原则。


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

struct是一个值类型,您将获得处理值类型的所有特权。

  • 结构按值传递。当你做类似的事情时

    datetime time=new datetime();datetime newtime=时间;//您没有引用时间//而是创建了一个新实例

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

  • 结构在性能上可能更轻,但并非一直如此。考虑将大型结构传递给方法。因为每次向方法传递一个结构时,结构都是值类型,所以会创建结构的新实例,因此每次都要复制该结构。如果您有一个相当大的结构,这将是一个更大的性能冲击。

  • 由于结构是值类型,因此有时可能需要对其进行装箱和取消装箱。

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


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

Struct Usage Guidelines

It is recommended that you use a
struct for types that meet any of the
following criteria:

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

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


结构用于表示某个对象,该对象的标识由存储在其属性中的值定义,而不是由ID或键定义。它们被称为"值类型",而不是被称为"实体类型"的tyo对象,其标识随着时间的推移而保持,并且不依赖于对象属性的值。

例如,一个人类(一个实体)的身份在一个会话到另一个会话之间持续存在,甚至在一年到一年之间,尽管该人的地址、电话号码、雇主等可能会从一个实例更改为另一个实例。如果您无意中在内存中同时有两个代表同一个人/实体的Person类实例,那么它们的属性值相同是很重要的。

calendarMonth对象otah(值类型)只有由指定它是哪个日历月的值定义的标识…不管您可能使用了多少"2009年3月"实例,它们都是可互换的和同等的。另一个例子可能是表示税务计划中财务分析指定的对象。地址对象就是一个很好的例子。(这里不讨论与个人、企业或任何其他实体的地址关联,只讨论地址本身)。更改地址的任何属性都会使其成为不同的地址。一旦您在内存中创建了一个地址对象,它就与其他具有相同属性的地址对象具有同等性和可互换性。这就是为什么这些值类型通常是不可变的。当你需要一个属性值时,用你需要的属性值创建一个新的属性值,当你使用完它后,扔掉它。


当需要具有值(而不是引用)语义的"类"时,可以使用结构。


示例:假设您希望一个数据类型在x y z处表示坐标。您不需要任何功能,只需要三个变量。一个结构可以很好地解决这个问题,一个类可能会被过度杀戮。


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

结构是值类型而不是引用类型。如果你不知道这意味着什么,那么你可能不需要它。


事实上,我认为struct是C的遗产,我不认为我们必须在任何情况下使用它。也许有时候你觉得把东西放在堆栈上而不是堆上会更有效率;但是当Java/C从不把效率作为它的第一站,所以忽略它:这是我的观点。