为什么结构不能有析构函数?

你认为对这个问题的采访最好的答案是什么?

我想我在这里找不到这个副本,如果有的话请链接。

另一种看待这种情况的方式 – 而不仅仅是引用说明结构不能/不具有析构函数的规范 – 考虑如果规范被改变以便他们这样做会发生什么 – 或者更确切地说,让我们问一个问题:can can我们猜测为什么语言设计师决定不让结构首先出现“析构函数”?

(不要挂在“析构函数”这个词上;我们基本上是在讨论结构上的一种魔术方法,当变量超出范围时会自动调用。换句话说,语言特征类似于C ++的析构函数。 )

要意识到的第一件事是我们不关心释放记忆。 无论对象是在堆栈上还是在堆上(例如,类中的结构),存储器迟早会以这种或那种方式处理; 通过弹出堆栈或收集。 首先拥有类似析构函数的东西的真正原因是管理外部资源 – 例如文件句柄,窗口句柄或其他需要特殊处理的东西,以便清理CLR本身不知道的东西。

现在假设您允许结构体具有可以执行此清理的析构函数。 精细。 直到你意识到结构作为参数传递时,它们才会被值传递:它们被复制。 现在你有两个具有相同内部字段的结构,他们将尝试清理同一个对象。 一个将首先发生,因此之后使用另一个的代码将开始神秘地失败…然后它自己的清理将失败(希望! – 最坏的情况是它可能成功清理一些其他随机资源 – 这可以例如,在重复使用句柄值的情况下会发生这种情况。)

你可以想象为结构构造一个特殊情况,使它们的’析构函数’不运行(但要小心 – 你现在需要记住,当调用一个函数时,它始终是’拥有’实际资源的外部函数 – 所以现在一些结构与其他结构略有不同……) – 但是你仍然遇到常规结构变量的问题,其中一个可以分配给另一个,制作副本。

您可以通过为分配操作添加一种特殊机制来解决这个问题,该机制以某种方式允许新结构与其新副本协商底层资源的所有权 – 也许它们共享它或将所有权从旧的转移到新的 – 但现在你本质上是进入C ++ – land,你需要复制构造函数,赋值运算符,并添加了一堆细微之处,等待陷阱不知不觉的新手程序员。 请记住,C#的全部意义在于尽可能避免这种类型的C ++风格的复杂性。

并且,正如其他答案所指出的那样,只是为了让事情变得更加混乱,结构不仅仅作为本地对象存在。 对于本地人来说,范围很好并且定义明确; 但结构也可以是类对象的成员。 在这种情况下应该何时调用’析构函数’? 当然,您可以在容器类完成时执行此操作; 但是现在你有一种机制,根据结构所处的位置,行为会有很大不同:如果结构是本地的,它会在范围结束时立即触发; 如果struct在一个类中,它会被懒惰地触发…所以如果你真的关心确保你的某个结构中的某些资源在某个时间被清除,并且你的结构可能最终成为一个成员上课时,你可能需要明确像IDisposable / using()这样的东西,以确保你已经覆盖了你的基础。

因此,虽然我不能声称为语言设计师说话,但我可以很好地猜测他们决定不包含这样一个function的一个原因是因为它会成为一种蠕虫,他们希望保持C#相当简单。

来自Jon Jagger :

“结构体不能有析构函数。析构函数只是对象的覆盖。伪装成最终结构,而作为值类型的结构体不受垃圾收集的影响。”

除了数组和字符串之外的每个对象都以相同的方式存储在堆上:一个标题,提供有关“对象相关”属性的信息(其类型,是否由任何活动监视器锁使用,是否具有非抑制) Finalize方法等)及其数据(意味着所有类型的实例字段的内容(公共,私有和受保护的混合,基类类字段出现在派生类型字段之前)。因为每个堆对象都有一个标题,系统可以引用任何对象并知道它是什么,以及垃圾收集器应该用它做什么。如果系统有一个已经创建并具有Finalize方法的所有对象的列表,它可以检查列表中的每个对象,查看其Finalize方法是否未被抑制,并对其进行适当处理。

存储结构没有任何标题; 像两个整数字段的Point这样的结构只是存储为两个整数。 虽然可以对结构进行ref (当结构作为ref参数传递时会创建这样的东西),但是使用ref的代码必须知道ref指向的结构类型,因为ref结构都没有。结构本身也不包含这些信息。 此外,堆对象可能只能由垃圾收集器创建,这将保证创建的任何对象将始终存在,直到下一个GC循环。 相比之下,用户代码可以自己创建和销毁结构(通常在堆栈上); 如果代码创建了一个struct以及一个ref ,并将它传递给一个被调用的例程,那么代码就无法破坏结构(或根本不做任何事情),直到被调用的例程返回为止,所以保证struct至少存在,直到被调用的例程退出。 另一方面,一旦被调用的例程退出,给出的ref应该被假定为无效,因为调用者可以在此后的任何时间自由地销毁该结构。

因为定义析构函数用于破坏类的实例,而结构体是值类型。

参考: http : //msdn.microsoft.com/en-us/library/66x5fx1b.aspx

用微软自己的话说: "Destructors are used to destruct instances of classes." 所以问一下“为什么你不能使用析构函数( 某些不是类 )的东西,这有点傻了?” ^^