Last active
December 21, 2015 14:19
-
-
Save aasmundeldhuset/6318964 to your computer and use it in GitHub Desktop.
An approximate C# implementation of a piece of Scala code that showed how to make builders that enforce (at compile-time) that certain properties must be set.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| using System; | |
| public class Demo | |
| { | |
| public static void Main() | |
| { | |
| Person p = CreateA.Person().WithAge(23).WithName(""); | |
| Person q = CreateA.Person().WithName("").WithAge(23); | |
| Person r = CreateA.Person().WithName(""); | |
| // The next two don't compile because the name is not set | |
| Person s = CreateA.Person().WithAge(23); | |
| Person t = CreateA.Person(); | |
| } | |
| } | |
| public class Person | |
| { | |
| public string Name { get; private set; } | |
| public int Age { get; private set; } | |
| public Person(string name, int age) | |
| { | |
| Name = name; | |
| Age = age; | |
| } | |
| // Not necessary if you don't want any references to the builder assembly; just add .Build() at the end of each builder invocation | |
| public static implicit operator Person(CheckedPersonBuilder<NameIsSet> builder) | |
| { | |
| return builder.Build(); | |
| } | |
| } | |
| public abstract class NameStatus | |
| { | |
| } | |
| public abstract class NameIsSet : NameStatus | |
| { | |
| } | |
| public abstract class NameNotSet : NameStatus | |
| { | |
| } | |
| public class CheckedPersonBuilder<TNameStatus> | |
| where TNameStatus : NameStatus | |
| { | |
| public String Name { get; private set; } | |
| public int? Age { get; private set; } | |
| public static CheckedPersonBuilder<NameNotSet> New() | |
| { | |
| return new CheckedPersonBuilder<NameNotSet>(null, null); | |
| } | |
| private CheckedPersonBuilder(string name, int? age) | |
| { | |
| Name = name; | |
| Age = age; | |
| } | |
| public CheckedPersonBuilder<NameIsSet> WithName(string name) | |
| { | |
| return new CheckedPersonBuilder<NameIsSet>(name, Age); | |
| } | |
| public CheckedPersonBuilder<TNameStatus> WithAge(int age) | |
| { | |
| return new CheckedPersonBuilder<TNameStatus>(Name, age); | |
| } | |
| } | |
| public static class CreateA | |
| { | |
| public static CheckedPersonBuilder<NameNotSet> Person() | |
| { | |
| return CheckedPersonBuilder<NameNotSet>.New(); | |
| } | |
| public static Person Build(this CheckedPersonBuilder<NameIsSet> builder) | |
| { | |
| return new Person(builder.Name, builder.Age ?? 18); | |
| } | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment