6
[Serializable]
class MyClass
{
    [NonSerialized] int Foo { get; set; } // error
    [NonSerialized] int bar; // ok
}

Why is this disallowed?

I know about the workarounds such as

  • implementing ISerializable
  • switching to XmlSerializer/XmlIgnore
  • switching to a manually-implemented property

The question is specifically why is [NonSerialized] disallowed on properies, yet allowed on fields.

Stefan Monov
  • 11,332
  • 10
  • 63
  • 120

3 Answers3

12

Properties are actually methods, they are not serialized by the binary serialization process. It's the fields that are serialized. So it only makes sense to specify NonSerialized on a field.

Thomas Levesque
  • 286,951
  • 70
  • 623
  • 758
  • Properties are not mere methods. Semantically they're a combination of methods and an implicit backing field. And all serializers in existence do see the backing field. So it makes sense to control the serialization of the implicit backing field via its property. – Stefan Monov Sep 21 '10 at 13:52
  • 2
    Indeed, they are actually a pair of method. But the backing field is implicit only for auto-properties, and might not exist at all for normal properties. Anyway, when the `NonSerialized` attribute was introduced, auto-properties didn't exist, so they couldn't have taken that consideration into account – Thomas Levesque Sep 21 '10 at 13:58
  • 1
    Ok, and if they were to make NonSerialized valid for properties *now*, they would have to differentiate between auto-properties and normal properties in the AttributeTargets enum. Which I believe can't be done without breaking compatibility. Accepted. – Stefan Monov Sep 21 '10 at 14:03
3

I think this is a case of fine-grained control requiring more effort on your part. In other words, an automatic property will by default have a serializable backing field. If you want anything other than the default, then you can't use an automatic property.

I had thought that using [field:NonSerialized] against the property might work, but it does not. The C# spec does not explicitly call out the serializability of the backing field, but it does include this (10.7.3):

The following example:
 public class Point {
    public int X { get; set; } // automatically implemented
    public int Y { get; set; } // automatically implemented
}
is equivalent to the following declaration:
public class Point {
    private int x;
    private int y;
    public int X { get { return x; } set { x = value; } }
    public int Y { get { return y; } set { y = value; } }
}

Thus, the backing field is serializable (the default).

Kent Boogaart
  • 175,602
  • 35
  • 392
  • 393
0

You may want to look at IgnoreDataMemberAttribute if you're using WCF. This works on auto-properties.

Works even if you don't mark all the other members as DataMember (which I always find to be a pain) and the class with DataContract

Simon_Weaver
  • 140,023
  • 84
  • 646
  • 689