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的全部内容),需要做以下两件事之一:
-
完全支持值类型。 这允许C#为
STARTUPINFO
声明一个值类型,它将具有正确的内存布局以进行编组(即struct
支持,如C#所示)。 -
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中有一个很大的理由可能是由于这个原因。