【发布时间】:2015-05-11 15:24:11
【问题描述】:
我正在尝试创建一个代码重复最少的高效类。
我已经定义了:
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 作为参数的构造函数将查询 DB 以获取名称并调用最终构造函数。这样,所有执行都应该针对实际执行所有验证等的构造函数之一。其背后的想法是,如果我添加新的构造函数,我只需要提取必要的数据(名字/姓氏)并调用最终的构造函数进行验证。
但是,有一个编译错误阻止我在Me.New(dt.Rows(0)("FirstName").ToString(),dt.Rows(0)("LastName").ToString()) 线上使用这个系统。显然,这一行必须是构造函数中的第一行。但是如果我将其作为第一行,它将破坏验证过程,因为验证会由于没有名字/姓氏而引发错误。我必须查询数据库才能提取该信息。
我知道我可以在这里分配值并从这个构造函数调用验证,但这会有效地将这个构造函数与最后一个构造函数隔离,从而复制代码并增加一些维护。仅供参考,在下面的示例中,我只有 2 个构造函数,但实际上我还有更多。如果每个人都做自己的任务,那只会增加维护费用。
那么,有没有办法通过执行一些代码然后调用重载的构造函数来完成我的任务?
感谢您的任何见解
更新 1:
根据 the_lotus 评论,我包括 dt 定义。这个问题有一个解决方法。基本上我会从最终的构造函数中取出验证和赋值,并将其放入一个函数中。所有的构造函数都会调用这个函数,从而消除了链接构造函数的需要。它看起来不错,但我想了解为什么为了链接构造函数,我必须将构造函数调用放在第一行。
这是新代码:
公开课 Foo 私有 _firstName 作为字符串 = "" 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,它会失败。
【问题讨论】:
-
您没有显示 dt 的来源。您可以拥有私有 Initialize 方法或共享工厂方法。
-
dt 在这里不是问题。这就是为什么我包含
'query DB to get firstName and lastName代码...我试图保持代码简短。假设我将 dt 定义为 DataTable 并查询数据库以获取值。还假设我得到至少一行带有值的数据。问题在于 Me.New,编译器希望将它放在构造函数的第一行。我将用 dt 定义更新我的答案 -
是的,你需要在你的构造函数声明之后有构造函数重载调用——这是规则。然后,从那里设计您的对象,而不是其他方式。
-
这会破坏我的验证,因为在验证例程中我不能有一个空/未填充的值。我刚刚用一种解决方法更新了我的答案,基本上在没有构造函数链接的情况下实现了我想要的。我仍然不明白'链式构造函数调用必须在第一行'规则的目的是什么。
-
为什么要使用构造函数链接?因为您的对象可以在许多属性中具有默认值,并且您可能有许多构造函数,每个构造函数都添加一个属性。在内部,一个构造函数可以设置 5 个属性,而其他 4 个构造函数只能设置 1 个属性。例如
Door()可以设置_material = wood、_locks=1和_hinges=3(默认)。然后Door(locks)会调用Door()然后设置_locks=locks,然后Door(locks, hinges)会调用Door(locks)然后设置_hinges=hinges
标签: vb.net constructor-overloading constructor-chaining