New C# 6 Features – Auto Property Initializers

Recently, I presented thirteen planned C# 6 features to my peers in one of our lunchtime ‘Brown Bag‘ talks. The format was informal, and included a ‘panel’ of judges formed of some of the more experienced developers on the team. After each feature was demonstrated, each member of the panel held aloft their score out of 10.

Some of the feedback on the features was quite interesting, enough so to present them in a series of blog posts.

There’s plenty of information already out there, a good selection contained in the following articles.

Anyhow, let’s dive into the first feature, Auto Property Initializers.

So, up until C# 5, this is how we declare and initialise auto properties:

class AutoPropertyInitializerOld
{
    public int Prop1 { get; set; }
    public string Prop2 { get; set; }

    //public string Prop3 { get; } //Error: "Auto-implemented properties must have set accessors."
    private string field3;
    public string Prop3 { get { return field3; } }

    public AutoPropertyInitializerOld()
    {
        Prop1 = 0;
        Prop2 = "Hello";
        field3 = "SomeVal";
    }
}

Note that:

  • Our declaration and assignment are in different places.
  • We can’t have a ‘get’ only auto-property

However with C#6 we can now say:

class AutoPropertyInitializerNew
{
    public int Prop1 { get; set; } = 1;
    public string Prop2 { get; set; } = "Goodbye";

    //Can have an initializer on a read-only property - now we can have auto-properties on immutable types.
    public string Prop3 { get;  } = "I can still be set";
}

So what are the benefits of this? Well, we now have some short hand for declaring properties, which is nice, but the best thing about this is something I’ve alluded to in the comments:

Currently, if we want an immutable type, we cannot have an auto-property, as an auto-property must have a get and set accessor on it. Some will argue that private set makes a type immutable:

class UsingPrivateSet
{
    //Can have an initializer on a read-only property - now we can have auto-properties on immutable types.
    public string ImmutableProp3 { get;  private set; } 
}

This is true for simple types with no internal functionality that modifies state, however, more complex types classes may mutate the state of the object from private or even public methods. Inherently, use of private set does makes a class’ immutability dependent on other implementation factors.

Now we can have a get-only auto-property:

class GetterOnlyDemo
{
    //Can have an initializer on a read-only property - now we can have auto-properties on immutable types.
    public string ImmutableProp3 { get;  } = "I can still be set";
}

And the compiler is smart enough to enforce the assignment of an auto-property, throwing an error if it is not set.

Panel score: This was presented in conjunction with Primary Constructors (next), so we’ll see the score there.

Introducing Data Contract Serialize-Encrypt

Two previous posts of mine focused on Encrypting and Decrypting streams with the BCL class DataContractSerializer

After writing these, I realised that it would be quite nice to build these into a small open source library, and publish it to the world.

So, without further ado, I’d like to introduce the imaginatively titled SerializeEncrypt.

Data Contract Serializer

Recall that to serialize a class instance with DataContractSerializer we need to ensure that the class decorated appropriately with the correct attributes:

[DataContract]
public sealed class SerializableType
{
    [DataMember]
    public int Id { get; set; }

    [DataMember]
    public string Name { get; set; }
}

Then we create a new instance of DataContractSerializer and call .WriteObject(), passing in a stream and the serializable type instance.

var graph = new SerializableType {Id = 1, Name="James"};
var dcs = new DataContractSerializer(graph.GetType());
dcs.WriteObject(stream, graph);

Encrypting With Serialize-Encrypt

The new library decorates DataContractSerializer applying encryption or decryption to the process:

//Setup serializable object and data contract serializer as before
var graph = new SerializableType {Id = 1, Name="James"};
var dcs = new DataContractSerializer(graph.GetType());

//now setup encryptor and apply:
serializerEncryptor = new DataContractSerializerEncrpytor(dcs);
serializerEncryptor.WriteObjectEncrypted(stream, graph);

Decrypting with Serialize-Encrypt

Decrypting a source is a simple case of passing that source as a stream to the decryptor ReadObjectEncrypted():

//Setup DataContractSerializer and DataContractSerializerEncrpytor
var dcs = new DataContractSerializer(typeof(SerializableClass));
var dcsEncryptor = new DataContractSerializerEncrpytor(dcs);

//Setup stream to decrypt and pass this into our encryptor
var stream = new MemoryStream(encrpytedBytes);  //could be a file stream
var decryptedObject = 
    (SerializableClass)dcsEncryptor.ReadObjectEncrypted(stream);

Overriding Default Encryption

By default, the functionality uses AesCryptoServiceProvider with a default encryption key and IV (Initialization Vector). At the very least, it’s advisable to override the Key and IV. There are three overridable items. in the in the following configuration:

  • Override Key and IV
  • Override Key, IV and Algorithm.

To override the default algorithm provider, we must specify one based upon SymmetricAlgorithm. If we do override the default (AesCryptoServiceProvider) we are required to stipulate a different Key and IV. This is because different algorithms require different key sizes. The .LegalKeySizes property of the CryptoServiceProvider instance tells you which key sizes are allowed.

The following code shows how we override all three:

serializerEncryptor.OverrideEncryption(
    new byte[] { 1, 2, 3, 4, 5, 6, 7, 8 },
    new byte[] { 1, 2, 3, 4, 5, 6, 7, 8 },
    new DESCryptoServiceProvider());

We can also do this from the constructor:

var serializerOverriddenEncryptor = new DataContractSerializerEncrpytor(
    dataContractSerializer,
    new byte[] { 1, 2, 3, 4, 5, 6, 7, 8 },
    new byte[] { 1, 2, 3, 4, 5, 6, 7, 8 },
    new DESCryptoServiceProvider());

Naturally, you’ll want to source the Key and IV from elsewhere, as you’ll need them to decrypt, and it’ll not necessarily be part of the same process.

GitHub and NuGet Locations

The source code is hosted on GitHub and is also available through NuGet package manager: