FormatterServices.GetUninitializedObject在内部是如何工作的?

17
我的问题相对简单,我有一种感觉,即方法GetUninitializedObject(type)不会调用任何构造函数生成给定类型的新实例,而是生成一个像正确实例一样(具有相同结构)且表面上具有相同类型(但在内部仍然保持为对象)的新对象。
我这么说是因为最近我尝试使用GetUninitializedObject克隆Form.Button来生成我需要的类型的新实例(我在源对象上递归操作),我的结果具有正确的结构(并且立即窗口也显示它具有正确的类型),但如果我尝试执行MyForm.Components.Add(clonedButton),我会收到一个异常消息:“无法将类型为'System.Object'的对象强制转换为类型'ControlCollection'”(但我已检查了clonedButton的类型为Button以及其继承关系也是正确的,我手动检查了几乎所有结构,在克隆的按钮中,并与源Button对象匹配,并访问了公共和私有字段)。
所以这就是我的问题所在(因为在JavaScript中我遇到过类似的问题,当在相同的克隆上下文中从基本Object生成对象,然后添加具有正确名称和结构的字段时,编译器会通过观察每个实例的调用构造函数来发现我的技巧,因此我认为这可能是类似情况),如果有人能解释一下GetUninitializedObject()背后的实现原理,那将非常有帮助(提前致谢)。

我相信你也无法将按钮转换为ControlCollection ;) 请展示有问题的代码行。 - Ralf
它严重违反了适用于任何你可能在C#中编写的代码的规则。它创建一个对象而不调用构造函数。这在托管代码中是非常不好的,但却是支持二进制反序列化所必需的。 - Hans Passant
@Vitor,你是对的,我把方法名打错了,写到了问题描述里。 - Skary
1个回答

25
不,它们并不是。你已经为你所看到的行为想出了一个合理的解释,但那不是正确的解释。
FormatterServices.GetUninitializedObject(typeof(Button))获取的Button是一个真正的Button,在除了其构造函数未被调用之外的所有方面都像任何其他Button一样运作。问题在于Button没有设计成在其构造函数未被调用时工作,而你试图伪造它并不足以接近真实情况。
你可以通过在未初始化的对象上显式调用构造函数来看到该按钮是一个真正的Button
var button = (Button)FormatterServices.GetUninitializedObject(typeof(Button));
var constructor = typeof(Button).GetConstructor(Type.EmptyTypes);
constructor.Invoke(button, null);

通过这个按钮,您可以做任何其他方式可以做的事情。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接