VB.NET-滥用实例变量?
请看下面的代码:VB.NET-滥用实例变量?,vb.net,design-patterns,Vb.net,Design Patterns,请看下面的代码: Public Class A Public person1 As Person End Class Public Class B Inherits A Public Function CheckGender() As Boolean If person1._Gender = "M" Then CheckGender = True End If End Function End
Public Class A
Public person1 As Person
End Class
Public Class B
Inherits A
Public Function CheckGender() As Boolean
If person1._Gender = "M" Then
CheckGender = True
End If
End Function
End Class
Public Class C
Inherits B
Public Function CheckAge() As Boolean
If person1._Age > 30 Then
CheckAge = True
End If
End Function
End Class
Public Class D
Inherits C
Public Sub SomeMethod()
Dim list As List(Of Person) = New List(Of Person)
Dim p1 As New Person("Ian", "M", 31)
Dim p2 As New Person("Susan", "F", 20)
Dim p3 As New Person("Mark", "M", 22)
list.Add(p1)
list.Add(p2)
list.Add(p3)
For Each Person As Person In list
person1 = Person
If CheckAge() And CheckGender() Then
'Do something
End If
Next
End Sub
Public Shared Sub Main()
Dim d As New D
d.SomeMethod()
End Sub
End Class
Public Class Person
Public _Name As String
Public _Gender As String
Public _Age As String
Public Sub New(ByVal Name As String, ByVal Gender As String, ByVal Age As Integer)
_Name = Name
_Gender = Gender
_Age = Age
End Sub
End Class
c.SomeMethod
通过三个人循环并执行两项检查:b.CheckGender
和c.CheckAge
CheckGender
和CheckAge
使用超类A
中的实例变量
实时环境中的代码每天循环遍历数据库中的100000条记录,并删除CheckGender
和CheckAge
均为真的记录在这个场景中使用实例变量是一个糟糕的设计选择吗?我一直被教导使用局部变量。我希望Person
对象在每个循环上被传递到CheckGender
和CheckAge
。还是真的没关系
请注意,上面的代码是一个假设的示例
CheckGender
和CheckAge
在实际应用中是复杂的函数 只要CheckGender
和CheckAge
不访问层次结构中类的任何私有、受保护或内部成员,并且是公共函数,并且它们的逻辑在任何情况下都是相同的,A
、B
或C
,在另一个类中使用这些方法是更好的设计。如果可能的话,让它们保持静止。您可以让他们接受类的最通用实现(例如,A
),允许检查年龄或性别。从代码中提取,您甚至可以传递Person
属性,而不必使用A
、B
和C
类
但是,只要您需要执行以下任何或所有操作,就允许在上述情况下使用继承和此类逻辑:
- 符合特定的接口或基类,
、a
和B
类必须实现/扩展,并且该接口或基类提供了C
和检查性别
方法。如果将对象传递给第三方API,该API接受基类/接口作为参数,并在内部调用检查方法,则这可能是唯一的解决方案检查年龄
- 为类提供具体实现。如果您必须在
中为
的实例检查一些逻辑,但是对A
的实例进行完全不同的验证,或者在B
中组合现有逻辑和一些新逻辑,那么继承就是您的朋友。尽管如此,如果是这样,我还是希望将C
和CheckGender
暴露到接口中,并通过接口调用它们。这样,只要满足接口,继承是有效的,但不是强制性的CheckAge
关于实例变量与局部变量的使用-在.NET中使用实例变量的性能有一个缺点,尤其是当它们是值类型时。例如,使用名为
int\u someIntMember
的本地成员将被转换为this.\u someIntMember
-这反过来调用堆以获取this
对象,然后访问其\u someIntMember
成员。将成员作为局部变量,将其值放入堆栈中,并从堆栈中读取,而无需通过堆进行不必要的往返。此外,堆栈比堆快
然而,我不能说过多的堆使用是否是滥用,也不能说当局部变量使用过多时是滥用。这取决于所需的性能和代码的复杂性。有时局部变量会使代码更具可读性,但如果太多,则很容易忘记每个变量是什么(这可能比疏忽的性能增益更严重)。因此,这是一个风格和必要性的问题。如果您有兴趣“修复”代码以使Person成为属性而不是字段,请按如下方式更改Class a的实现:
Public Class A
Public Property Person1 As Person
Public Overridable Function ComputeAge() As Integer
Return Person1.Age
End Function
End Class
这里的好处是,如果需要的话,您可以在获取和设置此属性的过程中添加额外的抽象。编译器将为auto属性生成一个隐藏的私有备份字段。您仍然可以从任何实现类访问Person1:
Public Class B
Inherits A
Public Overrides Function ComputeAge() As Integer
Return MyBase.Person1.Age.AddYears(1)
End Function
End Class
谢谢+1.我会考虑一下的。你能回答原来的问题吗。在循环中使用实例变量是一种糟糕的做法,还是这并不重要?请不要认为我是在暗示你没有回答我的问题(保留你的原始答案),你是这个问题的唯一答案。我不明白你最后的评论。对不起,我想的是那个:。我想我今天太累了……对不起,我不知道你的意思。你认为这是不好的做法吗?再次感谢。这与性能有关,但肯定不差。太多局部变量的缺点是可能会对较小的性能改进产生混淆-我的意思是,性能的改进可能不如具有可读性和可维护性的代码好。不过,房产有好也有坏。好的方面是,作为优化的一部分,它们通常由编译器内联,这会自动创建局部变量。坏的是,如果属性不是您的代码,并且您不确定它实际上做了什么。即使是属性的getter也可能在其实现中执行意外的逻辑,这会让您想知道瓶颈在哪里(比如lazy属性的NHibernate实体代理)。只要这不是一个问题,也没有风险,这是一个好的做法。@Jim Wooley,谢谢。您认为person应该是的实例变量,还是应该作为参数传递给CheckAge和CheckGender。或者这并不重要+1.
public class A : IAgeCheckable, IGenderCheckable
{
...
}
public static class CheckUtil
{
public static bool CheckAge(IAgeCheckable obj)
{
return obj.CheckAge();
}
public static bool CheckGender(IGenderCheckable)
{
return obj.CheckGender();
}
}
Public Class A
Public Property Person1 As Person
Public Overridable Function ComputeAge() As Integer
Return Person1.Age
End Function
End Class
Public Class B
Inherits A
Public Overrides Function ComputeAge() As Integer
Return MyBase.Person1.Age.AddYears(1)
End Function
End Class