I am trying to create an efficient class with minimum code-duplication.
I have this defined:
Public Class Foo
Private _firstName as string = ""
Private _lastName as string = ""
Public Sub New(ByVal userGUID As Guid)
'query DB to get firstName and lastName
Me.New(dt.Rows(0)("FirstName").ToString(),dt.Rows(0)("LastName").ToString())
End Sub
Public Sub New(ByVal firstName As String, ByVal lastName As String)
_firstName = firstName.toUpper()
_lastName = lastName.toUpper()
Validate()
End Sub
Private Sub Validate()
' Throw error if something is wrong
End Sub
End Class
The Constructor with firstName and lastName parameters is the end-point constructor that does validation. A constructor with userGUID as a parameter would query DB to obtain name and call the final constructor. This way all execution should be directed towards one of the constructors that actually does all validation etc etc. The idea behind it is that if I add new contructors, I only have to pull necessary data (firstname/lastname) and call the final constructor that does validation.
However, there is a compilation error preventing me from using this system on line Me.New(dt.Rows(0)("FirstName").ToString(),dt.Rows(0)("LastName").ToString())
. Apparently this line has to be the first line in the constructor. But If I have this as first line, it will break the validation process because validation will throw an error due to no firstname/lastname. I have to query the DB in order to pull that info.
I am aware that I can assign values here and call validation from this constructor too, but this will effectively isolate this constructor from the final one, thus duplicating code and adding to maintenance a bit. FYI, in the example below I only have 2 constructors, but in reality i have several more. If each will do its own assignment it just adds up to maintenance that much.
So, is there a way to achieve my task by executing some code and THEN calling an overloaded constructor?
Thank you for any insight
UPDATE 1:
Per the_lotus comment, I am including dt definition. There is a workaround for this issue. Basically I would take the validation and assignment out of the final constructor and put it into a function. All constructors would call this function, thus eliminating the need to chain constructors. It doesn't look bad, but I would like to understand why in order to chain constructors I have to put constructor calls on the first line.
Here is new code:
Public Class Foo Private _firstName As String = "" Private _lastName As String = ""
Public Sub New(ByVal userGUID As Guid)
Dim dt As New DataTable
' query DB to get firstName and lastName
' Assume I populate dt with at least one DataRow
AssignAndValidate(dt.Rows(0)("FirstName").ToString(), dt.Rows(0)("LastName").ToString())
'Me.New(dt.Rows(0)("FirstName").ToString(), dt.Rows(0)("LastName").ToString())
End Sub
Public Sub New(ByVal firstName As String, ByVal lastName As String)
AssignAndValidate(firstName, lastName)
End Sub
Private Sub Validate()
' Throw error if something is wrong
End Sub
Private Sub AssignAndValidate(ByVal firstName As String, ByVal lastName As String)
_firstName = firstName.ToUpper()
_lastName = lastName.ToUpper()
Validate()
End Sub
End Class
One curious not to mention: online code converters (vb.net to C#) have no issues converting chained constructor calls NOT on the first line. The C# code comes back as this.#ctor(dt.Rows(0)("FirstName").ToString(), dt.Rows(0)("LastName").ToString());
However, If I try to convert back to VB.NET, it fails.