XSerializer
XSerializer copied to clipboard
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.