Я пытаюсь создать эффективный класс с минимальным дублированием кода.
Я определил это:
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
Конструктор с параметрами firstName и lastName - это конструктор конечной точки, который выполняет проверку. Конструктор с userGUID в качестве параметра запросит у БД имя и вызовет последний конструктор. Таким образом, все выполнение должно быть направлено на один из конструкторов, который на самом деле выполняет всю проверку и т.д. делает проверку.
Однако из-за ошибки компиляции я не могу использовать эту систему в строке Me.New(dt.Rows(0)("FirstName").ToString(),dt.Rows(0)("LastName").ToString())
. Очевидно, эта строка должна быть первой строкой в конструкторе. Но если у меня это первая строка, это нарушит процесс проверки, потому что проверка выдаст ошибку из-за отсутствия имени / фамилии. Мне нужно запросить БД, чтобы получить эту информацию.
Я знаю, что могу назначать здесь значения и вызывать проверку из этого конструктора, но это эффективно изолирует этот конструктор от последнего, таким образом дублируя код и немного добавляя к обслуживанию. К вашему сведению, в приведенном ниже примере у меня есть только 2 конструктора, но на самом деле у меня есть еще несколько. Если каждый будет выполнять свое задание, это просто добавит столько же к обслуживанию.
Итак, есть ли способ выполнить мою задачу, выполнив некоторый код и ЗАТЕМ вызывая перегруженный конструктор?
Спасибо за понимание
ОБНОВЛЕНИЕ 1:
Согласно комментарию the_lotus, я включаю определение dt. Есть обходной путь для этой проблемы. По сути, я бы взял проверку и присвоение из окончательного конструктора и поместил его в функцию. Все конструкторы будут вызывать эту функцию, что устраняет необходимость в цепочке конструкторов. Выглядит неплохо, но я хотел бы понять, почему для объединения конструкторов в цепочку я должен помещать вызовы конструкторов в первую строку.
Вот новый код:
Открытый класс 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
Конец класса
Об одном любопытном не упомянуть: онлайн-конвертеры кода (vb.net в C #) не имеют проблем с преобразованием вызовов связанных конструкторов НЕ в первой строке. Код C # возвращается как this.#ctor(dt.Rows(0)("FirstName").ToString(), dt.Rows(0)("LastName").ToString());
. Однако, если я попытаюсь преобразовать обратно в VB.NET, это не удастся.
'query DB to get firstName and lastName
код ... Я стараюсь, чтобы код был коротким. Предположим, я определяю dt как DataTable и запрашиваю БД, чтобы получить значения. Также предположим, что я получил хотя бы одну строку данных со значениями. Проблема связана с Me.New, который компилятор хочет поместить в первую строку конструктора. Я дополню свой ответ dt Definition - person George   schedule 11.05.2015Door()
может устанавливать_material = wood
,_locks=1
и_hinges=3
(по умолчанию). ЗатемDoor(locks)
вызоветDoor()
и затем установит_locks=locks
, затемDoor(locks, hinges)
вызоветDoor(locks)
и затем установит_hinges=hinges
- person T.S.   schedule 11.05.2015Foo
. Чтобы разрешитьValidate
вызвать исключение, нужно закрыть дверь после того, как собака убежит. Все это можно предотвратить при создании нового Foo после защиты данных, которые ему требуются. - person Ňɏssa Pøngjǣrdenlarp   schedule 12.05.2015