# Creating a lightweight strongly-typed parameter infrastructure

I'm looking for some feedback on some code, designed to allow me to strongly-type parameters, which get passed to functions.

I'm only really looking for comments on making my parameters more strongly typed, as well as the existence of the factory method. The implementation of the FindUser method is not relevant.

At the minute the code base has a number of places where many pieces of data are represented as strings, however in actual fact they may be EmailAddresses, Usernames etc.

This can be awkward, so I am trying to consider a way in which this could be improved.

I have written the below code, as an attempt to address this problem, and allow for the parameters I pass around functions, to be more strongly typed.

Interface used to represent the values

Public Interface IStronglyTypedValue(Of T)
Property Value As T
// We could add IsValid, IsCorrectFormat, etc methods in future
End Interface


Base class to provide functionality around construction (and maybe properties in future such as IsValid, or ToString()).

Public MustInherit Class StronglyTypedValueBase(Of T, TTypeOfThing As {New, IStronglyTypedValue(Of T)})
Implements IStronglyTypedValue(Of T)

Public Property Value As T Implements IStronglyTypedValue(Of T).Value

Public Shared Function Make(data As T) As TTypeOfThing
Return New TTypeOfThing() With {.Value = data}
End Function
End Class


This will then allow for the definition possible parameters to methods, for example:

Public Class EmailAddress
Inherits StronglyTypedValueBase(Of String, EmailAddress)
End Class

Public Class UserName
Inherits StronglyTypedValueBase(Of String, UserName)
End Class


Which could then be used like this

 EmailAddress.Make("my@email.com")
UserName.Make("user123")


Some example ways BEFORE using this functionality (functions grouped into one class for brevity)

Public Class UserFinder
Public Function FindUserByEmailAddress(email As String) As IUser
//Lookup the user
End Function

Public Function FindUserByUsername(username As String) As IUser
//Lookup the user
End Function

Public Sub DoWork()
Dim paul = FindUserByEmailAddress("paul@email.com")
Dim steve = FindUserByUsername("steve1")
End Sub
End Class


Instead, we can now do:

Public Class UserFinder
Public Function FindUser(email As EmailAddress) As IUser
//Lookup the user
End Function

Public Function FindUser(username As UserName) As IUser
//Lookup the user
End Function

Public Sub DoWork()
Dim paul = FindUser(EmailAddress.Make("paul@email.com"))
Dim steve = FindUser(Username.Make("steve1"))
End Sub
End Class


This also means we can now more easily write ExtensionMethods, and refactor some of this functionality into the class.

The main area of concern/review is the Make() method on the StronglyTypeValueBase class.. Is this a dirty approach? Would it be better to have used a Public Constructor than a factory method?

Also, is there a better way of solving the problem of strongly typed parameters to methods, which may not need to have loads of function.

In short, I'm looking to add a compile-time enforcement of type. I want to not allow using a string representing a Username in a function expecting an email address; whilst at the same time not introducing any anti-patterns.

• I've edited the question to clarify what code is the subject of the review, and what code is merely an illustration of the intended usage. – 200_success Jan 29 '16 at 8:12

## 1 Answer

Stop. This way madness lies.

It's great that you want to strongly type these things. They should be! The problem is in your approach. This isn't what generics/interfaces are for. This is what Structures and conversion operators are for.

Public Structure EmailAddress
Private email As String

Public Sub New(ByVal s As String)
' validation code here

email = s
End Sub

Public Shared Narrowing Operator CType(ByVal s As String) As EmailAddress
Return New EmailAddress(s)
End Operator

Public OverRides Function ToString() As String
Return email
End Function
End Structure


Which lets you use it as a strongly typed object, without much fuss and using VB.Net idioms that any VB dev will be familiar with.

Dim email = new EmailAddress("JohnDoe@domain.net")

email = CType("JohnDoe@domain.net", EmailAddress)

Dim value As String = email.ToString()

• Thanks for this @RubberDuck, I can see what you are saying. What reasons are there that would mean the approach I suggested, would not be appropriate? I can see value in your suggestion, but would also help me understand why what I was trying to do, may not be advisable? – Richard Simpson Feb 1 '16 at 10:20
• Mostly because a simpler solution exists. Your approach would absolutely work, and seems to be based on the builder pattern. It does result in more code, and more places for something to go wrong. The biggest issue perhaps is that interfaces should define behavior, not types. You've essentially reinvented static typing for a language that already has it. – RubberDuck Feb 1 '16 at 10:35
• I see, well re-inventing the wheel isn't the most ideal of things. I will give it a go, and see how I get on. I'll report back in a while, for the benefit of others looking to solve this problem. – Richard Simpson Feb 2 '16 at 11:35