Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/design-patterns/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
VB.NET-滥用实例变量?_Vb.net_Design Patterns - Fatal编程技术网

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接受基类/接口作为参数,并在内部调用检查方法,则这可能是唯一的解决方案
下面是C#中的示例:

  • 为类提供具体实现。如果您必须在
    中为
    A
    的实例检查一些逻辑,但是对
    B
    的实例进行完全不同的验证,或者在
    C
    中组合现有逻辑和一些新逻辑,那么继承就是您的朋友。尽管如此,如果是这样,我还是希望将
    CheckGender
    CheckAge
    暴露到接口中,并通过接口调用它们。这样,只要满足接口,继承是有效的,但不是强制性的
下面是C#中的一个示例:


关于实例变量与局部变量的使用-在.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