用于序列化的无参数构造函数与具有默认参数的构造函数相结合,为什么它可以工作?

时间:2011-11-23 13:19:10

标签: c# reflection constructor xml-serialization language-design

我写了一些效果很好的代码,但我不明白为什么它有效。我想序列化一个类,让我们说一个整数。所以这是该类的代码。

[Serializable]
public class TestClass
{
    public int Variable;
}

现在我希望能够创建此类的实例并立即设置Variable。所以我创建了一个构造函数,也为序列化器创建了一个私有的默认构造函数。

[Serializable]
public class TestClass
{
    public int Variable;

    private TestClass() {}

    public TestClass(int value)
    {
        Variable = value;
    }     
}

所以在我使用它的代码中,默认参数变得很方便。所以我将该技术应用于公共构造函数。

[Serializable]
public class TestClass
{
    public int Variable;

    private TestClass() {}

    public TestClass(int value = 0)
    {
        Variable = value;
    }     
}

这一切都很好,但为什么呢?我们现在没有两个具有相同定义的构造函数吗?即使我将默认构造函数设为public,一切正常。删除默认构造函数后,它会在序列化时失败。我的第一个猜测是.NET的XmlSerialize不检查具有默认参数的构造函数。但是为什么编译器仍然允许这个代码?

我对此很好奇,但也希望学习并更好地理解内部的工作方式。谷歌搜索没有带来任何有用的东西,可能只是因为我无法想到正确的搜索条件。

1 个答案:

答案 0 :(得分:5)

XmlSerializer特别要求它序列化的类具有无参数构造函数,如果在私有构造函数中放置断点,则会注意到它在反序列化时遇到了问题。具有默认参数的构造函数不是无参数构造函数,它是一个构造函数,它接受编译器为您插入的参数

无参数构造函数与仅具有默认参数(或相同情况下的任何方法)的构造函数的重载分辨率归结为特异性。在众多其他重载解析规则中,C#4.0语言规范(7.5.3.2更好的函数成员)声明:

  

否则,如果MP的所有参数都有相应的参数   而默认参数需要替换至少一个   MQ中的可选参数,然后MP优于MQ。

根据这些信息,我们可以简化并提出有关您拥有的构造函数的问题。当你说new TestClass()时,应该选择哪一个?

  1. 我们已经指定了要传递给调用的所有参数。在 这种情况,它是零。

  2. 是否有一个构造函数,其中包含完全零参数 呼叫者?

  3. 如果是,请拨打电话。

  4. 如果没有,请拨打下一个最好的东西。在这种情况下,它是你的构造函数,它有默认参数。

  5. 请注意,XmlSerializer 不遵循这些规则。它特别知道它想要什么,并且如果你不提供它会抱怨。