Friday, February 14, 2014

Generating immutable instances in C# with FsCheck

If you do any functional programming in C# you’ll probably have lots of classes that look like this:

class Person {
    private readonly string name;
    private readonly DateTime dateOfBirth;

    public Person(string name, DateTime dateOfBirth) {
        this.name = name;
        this.dateOfBirth = dateOfBirth;
    }

    public string Name {
        get { return name; }
    }

    public DateTime DateOfBirth {
        get { return dateOfBirth; }
    }

    // equality members...
}

I.e. immutable classes, similar to F# records.
Now let’s say we want to test some property involving this Person class. For example, let’s say we have a serializer:

interface IPersonSerializer {
    string Serialize(Person p);
    Person Deserialize(string source);
}

Never mind the unsafety of this serializer, we want to test that roundtrip serialization works as expected. So we grab FsCheck and write:

Spec.ForAny((Person p) => serializer.Deserialize(serializer.Serialize(p)).Equals(p))
    .QuickCheckThrowOnFailure();

Only to be greeted with:

System.Exception: Geneflect: type not handled Person

Ok, so we write the generator explicitly:

var personGen =
    from name in Any.OfType<string>()
    from dob in Any.OfType<DateTime>()
    select new Person(name, dob);

Spec.For(personGen, p => serializer.Deserialize(serializer.Serialize(p)).Equals(p))
    .QuickCheckThrowOnFailure();

And all is fine.

But the generator code is trivially derivable from the class definition. And when you have lots of immutable classes, this boilerplate becomes really annoying. Couldn’t we automatize that somehow?

As it turns out, FsCheck already does this for F# records, using reflection. With a bit of code we can extend the reflection-based generator (built into FsCheck) to make it generate instances of immutable classes. With this change, we can go back to writing Spec.ForAny and FsCheck will automatically derive the generator for our Person class!

The restrictions on the classes to make them generable by FsCheck are:

  • Must be a concrete class. No interfaces or abstract classes; FsCheck can’t guess a concrete implementation.
  • It has to have only one public constructor. Otherwise, which one would FsCheck choose?
  • All public fields and properties must be readonly. Otherwise, it creates the ambiguity of which ones to set and which ones not.
  • Must not be recursively defined. FsCheck doesn’t generate recursively defined F# records by reflection either. I assume this is to keep the implementation simple.
  • Must not have type parameters. This restriction could probably be relaxed, but since I haven’t needed it so far, I decided to play it safe. Left as an exercise for the reader :-)

This is available in FsCheck as of version 0.9.2.

Happy FsChecking in C# and VB.NET !

13 comments:


  1. Hii,
    My name is Shivani arora. Your article is Very amazing.
    Thanks for sharing wonderful Information. In this article I learn a lot. And if you want to know about wedding or matrimonial services visit:- Truelymarry
    It's one of the best Indian Matrimonial site and profiles are handled personally.
    Our site helps you in providing matchmaking service in India like:-
    Kanpur , Rajput , Brahmin

    ReplyDelete
  2. Read about Alteza which is a online pharmacy app development company that builds custom pharmacy app for your requirements and we also provide readymade pharmacy app development solutions for every pharmacy needs. We relay our services and solutions that can benefit your business in the most correct way. Our solutions will manage and expand your business in the most seamless way.

    ReplyDelete
  3. slot168 เว็บสล็อตออนไลน์ โบนัสเเตกง่าย ได้เงินจริง โปรโมชั่นเยอะ ต้องเกม PG SLOT เท่านั้น ยิ่งเล่น ยิ่งรวย ได้เงินจริง อัตราการจ่ายเงินรางวัลสูง คุ้มค่ากับการลงทุนแน่นอน ที่ได้รับความนิยมมากที่สุด

    ReplyDelete
  4. Are you searching for best matrimonial site for your perfect couple match? Atootdor can be a best option because Atootdor is a Best Matrimonial site in nagpur must try once.

    ReplyDelete
  5. รีวิวสล็อต วิดีโอสล็อตโจ๊กเกอร์ และวิดีโอสล็อตสร้างรายได้ออนไลน์ สิ่งประดิษฐ์โบราณที่มาพร้อมกับธีมของสิ่งศักดิ์สิทธิ์ ความเชื่อของจีนเรื่องเทพเจ้าแห่งโชคลาภที่นำความมั่งคั่งมาให้ทุกคนได้เล่น วิดิโอเกมสล็อต Ancient Artifacts

    ReplyDelete
  6. If you supply goods or services in events/exhibition & you don’t have a permanent place of business, you need to get online GST Registration. The validity of causal GST Registration is 90 days. If you need GST Registration Consultants
    then we are here to help you.Just Click and ask them

    ReplyDelete
  7. Are you searching for a GST registration consultant in India? Contact us today for all services related to GST Registration, GST Filing, GST E-Way Bill, and many more.

    ReplyDelete
  8. If you want to get free credits to spin and spin slot games, invite to join the free credit giveaway event with PG camp today, only one day. Free credit is limited. If you want, please come and join at ทดลองเล่นสล็อต คลิกที่นี้ first come first serve if anyone has never played slots, we have one Try Slots Let's try to play first.

    ReplyDelete
  9. I have really inspected your post, it is extremely valuable and just as helpful for me. I like the significant data you supply in your short articles. Thanks for sharing.water based lubricant
    masturbator cup

    ReplyDelete
  10. This comment has been removed by the author.

    ReplyDelete
  11. If you are looking for digital marketing services in ghaziabad then please contact us for more information.

    ReplyDelete
  12. Discover Aula's exceptional gaming keyboards, designed for performance and style. With customizable RGB lighting, responsive mechanical switches, and ergonomic layouts, these keyboards provide the ultimate gaming experience. Whether you’re a casual player or a pro, elevate your gameplay with reliable, high-quality keyboards that meet all your gaming needs.



    ReplyDelete