Inconsistent behavior for non-default constructors
Various combinations of constructors produce different results.
Example class
This is the class used for examples below.
public class Foo
{
private readonly int _bar;
private readonly string _baz;
// TODO: Add constructor(s) here
public int Bar { get { return _bar; } }
public string Baz { get { return _baz; } }
}
And this is the xml document that we'll be using for the examples. We'll be removing the <Bar> and <Baz> tags to highlight differences in behavior.
<Foo>
<Bar>123</Bar>
<Baz>abc</Baz>
</Foo>
Single, non-default constructor
public Foo(int bar, string baz)
{
_bar = bar;
_baz = baz;
}
If our example class has a single, non-default constructor, deserialization behaves correctly. It successfully handles an xml document that has or doesn't have <Bar> and <Baz> tags in any combination.
Default constructor + non-default constructor
public Foo()
{
}
public Foo(int bar, string baz)
{
_bar = bar;
_baz = baz;
}
When deserializing, the default constructor is always chosen, and _bar and _baz are left uninitialized.
Two non-default constructors with equal number of parameters
public Foo(int bar)
{
_bar = bar;
}
public Foo(string baz)
{
_baz = baz;
}
Things get a little weird here. If the xml that we deserialize includes both a <Bar> and a <Baz> element, then we get an InvalidOperationException. But, if we only include a <Bar> element, then the constructor that takes an int is called. And if we only include a <Baz> element, then the constructor that takes a string is called. If we included neither <Bar> nor <Baz>, then the constructor that takes an int is called.
Two non-default constructors with unequal number of parameters
public Foo(int bar, string baz)
{
_bar = bar;
_baz = baz;
}
public Foo(string baz)
{
_baz = baz;
}
This situation makes more sense. If neither <Bar> nor <Baz> are provided, then the single-parameter constructor is called. If <Bar> but not <Baz> is provided, then the two-parameter constructor is called. If <Baz> but not <Bar> is provided, then the single-parameter constructor is called. And if both <Bar> and <Baz> are provided, then the two-parameter constructor.