There are numerous times you have an interface that accepts similar type arguments that have a separate domain logic meaning:
public static class Database { public static bool HasAccess(string userId, string documentId) { return true; } }
Now it’s quite easy to have someone key documentId instead of userId and vice versa. One could prevent that by abstracting the data type of the arguments:
public class UserId { public string Value { get; internal set; } public static implicit operator string(UserId id) { return id.Value; } } public class DocumentId { public string Value { get; internal set; } public static implicit operator string(DocumentId id) { return id.Value; } } public static class Database { public static bool HasAccess(UserId userId, DocumentId documentId) { return true; } }
This way you get a nice compiler warning if you type in arguments out of order:
UserId e = new UserId() { Value = 'a' }; DocumentId d = new DocumentId() { Value = 'b' }; Database.HasAccess(d, e);
You also get the ability to change abstracted type in without affecting the rest of the system but that’s not very likely. Would abstracting type be a good idea to get more type safety?
The question relates to C# solutions but short descriptions in other languages is welcome.
EDIT: Removed the implicit cast from string and pointing finger at the C# tag.
Interesting, but I suspect that in many cases (particularly seialization / RPC APIs) this will only add confustion/overhead. Also – a minor implementation detail, but given this approach I’d make the wrappers fully immutable, not just ‘internal set’ immutable.
TBH – I’d probably rather use unit tests for most of this… sometimes simple is beautiful. The other problem is that since you have implicit operators, it won’t stop you doing the much more likely:
That should compile; the implicit operator undoes all your good work…