5

I was told by someone that a blank constructor was required for serializable objects that included getters and setters, such as below:

[DataContract]
public class Item
{
    [DataMember]
    public string description { get; set; }

    public Item() {}

    public Item(string description)
    {
        this.description = description;
    }
}

And the reason this was told me was that this allowed for construction of objects using the setter. However, I have found that the Item when defined like this:

[DataContract]
public class Item
{
    [DataMember]
    public string description { get; set; }

    public Item(string description)
    {
        this.description = description;
    }
}

Can be constructed without calling the constructor, when made available as a proxy class via a WCF service reference:

Item item = new Item {description = "Some description"};

Questions:

  1. What exactly is that block of code I'm writing after declaring new Item
  2. Is a blank constructor required for [DataContract] classes? If so, what does this blank constructor do?

I have found that I can't create an object without the constructor if the class is NOT a proxy class.

Zach Smith
  • 8,458
  • 13
  • 59
  • 133

1 Answers1

8

What exactly is that block of code I'm writing

Item item = new Item {description = "Some description"};

Is equal and gets compiled to:

Item item = new Item();
item.description = "Some description";

So it requires a parameterless constructor. If the class doesn't have one, but has a parameterized one, you must use that one:

Item item = new Item("Some description");

Using named parameters, it would look like this:

Item item = new Item(description: "Some description");

You can still combine that with the object initializer syntax:

var item = new Item("Some description")
{
    Foo = "bar"
};

Is a blank constructor required for [DataContract] classes?

Yes. The default serializer, DataContractSerializer, doesn't use reflection to instantiate a new instance, but still requires a parameterless constructor.

If it can't find a parameterless constructor, it can't instantiate the object. Well, it can, but it doesn't. So if you were to actually use this Item class in a service operation:

public void SomeOperation(Item item)
{
}

Then WCF will throw an exception once you invoke this operation from a client, because the serializer can't find a parameterless constructor on Item.

Community
  • 1
  • 1
CodeCaster
  • 147,647
  • 23
  • 218
  • 272
  • Thank you. I definitely don't have a parameterless constructor for Item in my service that is consumed via a service reference. Does the proxy class get generated with a blank constructor automatically? – Zach Smith Feb 01 '17 at 10:13
  • 2
    If a class doesn't contain a constructor at all, a parameterless one is generated automatically (see: https://msdn.microsoft.com/en-us/library/aa645608(v=vs.71).aspx). – CodeCaster Feb 01 '17 at 10:13
  • Then I'm not sure what you're asking. – CodeCaster Feb 01 '17 at 10:15
  • On my service I've defined `Item` with a single constructor. On my client I add a service reference to that service, get a proxy class for `Item`, and can create instances of `Item` via constructor with no argument (using the shorthand method)... Why? – Zach Smith Feb 01 '17 at 10:18
  • 1
    Because [on the client a class with only the properties is generated](http://stackoverflow.com/questions/6316118/constructor-in-wcf-datacontract-not-reflected-on-client), without constructors or methods (unless you reference the assembly containing the data contracts and opt to reuse the types when generating the client, but that's another story). If you use `Item` as a service operation parameter (`IService1.Foo(Item item)`), then that will blow up at runtime when you invoke that operation, because the serializer can't find a parameterless constrctor on `Item` at the service side. – CodeCaster Feb 01 '17 at 10:19
  • That answers my question. I would guess since `Item` doesn't have a blank constructor there are use-cases that would cause exceptions on the service... But that's a question for another time. Thanks very much – Zach Smith Feb 01 '17 at 10:23
  • 2
    `Yes. The serializer uses reflection to instantiate a new instance, and does so using the parameterless constructor.` That is not true. In WCF some black magic is used to create instances of objects. See also http://stackoverflow.com/questions/1076730/datacontractserializer-doesnt-call-my-constructor – Jehof Feb 01 '17 at 10:25
  • @Jehof great addition, thanks. I knew that somewhere in the back of my head, yet WCF still requires a parameterless constructor to exist. Updated the answer. – CodeCaster Feb 01 '17 at 10:29