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

5Yr*_*DBA 16 c# struct

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

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

结构类似于类,具有以下主要区别:

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

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

Jon*_*eet 16

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

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

我不会说"类可以做所有结构可以做更多" - 它们的行为不同,应该有不同的想法.


jon*_*onp 9

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

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

例如,假设您要调用CreateProcess()函数.进一步假设您想为lpStartupInfo参数使用STARTUPINFOEX结构.CreateProcess()

那是什么STARTUPINFOEX?这个:

typedef struct _STARTUPINFOEX {
    STARTUPINFO                    StartupInfo;
    PPROC_THREAD_ATTRIBUTE_LIST    lpAttributeList;
} STARTUPINFOEX, *LPSTARTUPINFOEX;
Run Code Online (Sandbox Code Playgroud)

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

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

[StructLayout(LayoutKind.Sequential)]
class STARTUPINFO { /* ... */ }

class STARTUPINFOEX { public STARTUPINFO StartupInfo; /* ... */ }
Run Code Online (Sandbox Code Playgroud)

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

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

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

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

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