Not sure what the point of the implicit operator overloads was. Why not just have:
public class CreateBooking {
public int TypeId { get; private set; }
...
public CreateBooking(BookingTypeId typeId, ..., ...) {
TypeId = typeId.Value;
...
}
}
public struct BookingTypeId {
private readonly int _value;
private BookingTypeId (int value) {
//...some simple validation logic...
_value = value;
}
public int Value { get { return _value; } }
public static BookingTypeId Custom(int value) {
return new BookingTypeId(value);
}
public static BookingTypeId Gold() {
return new BookingTypeId(3);
}
public static BookingTypeId Silver() {
return new BookingTypeId(2);
}
public static BookingTypeId Bronze() {
return new BookingTypeId(1);
}
}
With the added bonus that you're using less fancy stuff, so you don't need to explain to the junior dev that gets to maintain it what's going on.