C#为什么需要struct,如果类可以覆盖它?

只是想知道为什么我们需要struct如果类可以做所有结构可以和更多吗? 我认为,在课堂上放置值类型没有副作用。

编辑:看不到使用struct的任何强有力的理由

结构类似于类,具有以下主要差异:

  • 结构是值类型,而类是引用类型。
  • 结构不支持inheritance(除了隐式派生自对象)。
  • 结构可以包含类可以包含的所有成员,但以下内容除外:
  • 无参数构造函数
  • 终结者
  • 虚拟会员

当需要值类型语义时,使用结构而不是类。 结构的好例子是数字类型,其中赋值复制值而不是引用更自然。 因为struct是值类型,所以每个实例都不需要实例化堆上的对象。 在创建类型的许多实例时,这可能很重要。

自定义值类型不是绝对必要的 – 例如,Java没有它们。 但是,它们仍然有用。

例如,在Noda Time中,我们非常广泛地使用它们,作为一种有效的方式来表示像瞬间这样的东西,而不需要涉及对象的开销。

我不会说“类可以做所有结构可以做更多” – 它们表现不同,应该有不同的想法。

为什么在class有效时使用struct ? 因为有时一个class不起作用。

除了Reed Copsey提到的性能原因(简短版本:GC需要跟踪的对象越少,允许GC做得更好),还有一个地方必须使用结构:P /调用需要的函数按价值结构或结构成员。

例如,假设您要调用CreateProcess()函数。 进一步假设您希望将lpStartupInfo参数的STARTUPINFOEX结构用于CreateProcess()

什么是STARTUPINFOEX ? 这个:

 typedef struct _STARTUPINFOEX { STARTUPINFO StartupInfo; PPROC_THREAD_ATTRIBUTE_LIST lpAttributeList; } STARTUPINFOEX, *LPSTARTUPINFOEX; 

请注意, STARTUPINFOEX包含STARTUPINFO作为其第一个成员。 STARTUPINFO是一种结构。

由于类是引用类型,如果我们声明相应的C#类型:

 [StructLayout(LayoutKind.Sequential)] class STARTUPINFO { /* ... */ } class STARTUPINFOEX { public STARTUPINFO StartupInfo; /* ... */ } 

相应的内存中布局是错误的 ,因为STARTUPINFOEX.StartupInfo将是一个指针 (ILP32平台上的4个字节),而不是一个结构(根据需要,ILP32平台上的大小为68字节)。

因此,为了支持调用接受任意结构的任意函数(这就是P / Invoke的全部内容),需要做以下两件事之一:

  1. 完全支持值类型。 这允许C#为STARTUPINFO声明一个值类型,它将具有正确的内存布局以进行编组(即struct支持,如C#所示)。

  2. P / Invokeable结构中的一些替代语法,它将通知运行时封送程序,该成员应该作为值类型而不是指针布局。

(2)是一个可行的解决方案(可能已在Visual J ++中用于J / Direct;我不记得了),但鉴于正确的值类型更灵活,启用许多性能优化,否则无法实现,并使在P / Invoke场景中合理使用,C#支持值类型也就不足为奇了。

出于性能原因,通常还需要结构。 结构数组占用的内存要少得多,并且比对象引用数组获得更好的高速缓存一致性。 如果您正在使用类似渲染系统的东西,并且需要生成500万个顶点,这一点非常重要。

有关详细信息,请参阅Rico Mariani的Performance Quiz + Answers 。

结构很有用,因为它们是通过值传递的,这在某些算法中实际上是有用的。 这实际上是类不能做的事情。

 struct ArrayPointer { public T[] Array; public int Offset; } 

您可以将此结构传递给方法,并且该方法可以根据自己的需要更改Offset的值。 同时,一旦从方法返回,它将表现为Offset永远不会改变。

一般来说 ,使用一个类。

只有在绝对需要值类型语义时才使用结构。

  • C#中的Struct Vs类
  • C#Struct使用技巧?
  • 为什么我们需要结构? (C#)

对于普通的应用程序开发人员来说,使用类是常态。 从表面上看,类似的结构似乎是不必要的,但是当你深入研究细节时,它们实际上是完全不同的。

请参阅此处了解结构和类之间的一些差异。

最着名的区别是类是引用类型,而结构是值类型。 这很重要,因为它允许库开发人员控制如何使用数据类型的实例。

1,表现。 在某些使用结构的情况下,我们会获得更好的性能。
2,数据不变性。 通过更改结构的某些属性,您将获得一个新结构。 这在某些情况下非常有用
3,更好地控制内存表示。 我们可以准确地定义结构在内存中的位置,这使我们能够快速有效地序列化和反序列化某些二进制数据。

使用win32 API使用的底层数据结构几乎是必须的。 我想在.net中有一个很大的理由可能是由于这个原因。