VB.NET - 滥用实例变量? [英] VB.NET - Misusing instance variables?
问题描述
请看下面的代码:
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
中的实例变量。
c.SomeMethod
loops through three persons and does two checks: b.CheckGender
and c.CheckAge
. CheckGender
and CheckAge
use an instance variable from the superclass A
.
现场环境中的代码每天在数据库中循环100,000条记录,并删除那些 CheckGender
和 CheckAge
都是真的。 在这种情况下使用实例变量是不是很糟糕的设计选择?我一直被教导使用局部变量。我希望将 Person
对象传递给 CheckGender
和 CheckAge
每个循环。还是真的没关系?
The code in the live environment loops through 100,000 records daily in a database and deletes those where CheckGender
and CheckAge
are both true. Is it a bad design choice to use instance variables in this scenario? I was always taught to use local variables. I would expect the Person
object to be passed to CheckGender
and CheckAge
on each loop. Or does it really not matter?
请注意,上面的代码是一个假设的例子。 CheckGender
和 CheckAge
是实际应用中的复杂功能。
Please note that the above code is a hypothetical example. CheckGender
and CheckAge
are complex functions in the actual application.
推荐答案
只要 CheckGender
和 CheckAge
不访问层次结构中的任何私有,受保护或内部成员,并且是公共函数,并且对于任何实例,它们的逻辑是相同的, A
, B
或 C
,在另一个类中使用这些方法是一个更好的设计。如果可能,使它们静止。您可以让他们接受最常见的课程实施(例如, A
),允许检查年龄或性别。从您的代码中,您甚至可以通过 Person
属性,而不是使用任何 A
, B
和 C
类。
As long as CheckGender
and CheckAge
are not accessing any private, protected or internal member of the classes in hierarchy, and are public functions, and their logic is the same for any instance, being A
, B
, or C
, it is a better design to have these methods in another class. Make them static if possible. You can have them accept the most general implementation of your classes (A
for instance) that allows checking either the age or gender. Taken from your code, you can even pass the Person
property instead of using any of the A
, B
and C
classes.
在上述情况下使用继承只要您需要执行以下任何或全部操作即可使用此类逻辑:
Use of inheritance in the above case and such logic is permitted though, as long as you need to do any or all of the following:
- 符合特定界面或基础类,
A
,B
和C
类必须实现/扩展,该接口或基类提供了CheckGender
和CheckAge
方法。如果您将对象传递到第三方API,则可以是唯一的解决方案,该API接受基类/接口作为参数,并在内部调用检查方法。
- Conform to a specific interface or base class, that
A
,B
andC
classes have to implement/extend, and that interface or base class provides theCheckGender
andCheckAge
methods. This can be the only solution if you pass your objects to 3rd party API, that accepts the base class/interface as an argument and internally calls the check methods.
这里是C#中的示例:
public static class CheckUtil
{
public static bool CheckAgeOfPerson(Person p)
{
return p.Age > 30;
}
public static bool CheckAgeOfObject(A obj)
{
// NOTE: obj.person1 must be accessible - by being either public or internal.
// If this class is in another assembly, internal is not useful
return CheckAgeOfPerson(obj.person1);
}
}
A objA = ...;
B objB = ...;
C objC = ...;
CheckUtil.CheckAgeOfObject(objA);
CheckUtil.CheckAgeOfObject(objB);
CheckUtil.CheckAgeOfObject(objC);
CheckUtil.CheckAgeOfPerson(objA.person1);
CheckUtil.CheckAgeOfPerson(objB.person1);
CheckUtil.CheckAgeOfPerson(objC.person1);
- 为类提供具体的实现如果在
CheckAge
中为A
的实例提供了一些逻辑,但对<$ c的实例完全不同的验证$ c> B ,或C
中现有和一些新逻辑的组合,则继承是您的朋友。但是,如果是这样,我更愿意将CheckGender
和CheckAge
接口并通过接口。这样,继承是有效的,但不是强制的,只要界面满意。 - Provide specific implementation to the classes. If you have to some logic in
CheckAge
for instances ofA
, but either completely different validation for instances ofB
, or a combination of the existing and some new logic inC
, then inheritance is your friend. Still, if that is the case, I'd prefer exposing theCheckGender
andCheckAge
to interface and call them via the interface. That way, inheritance is valid, but not mandatory, as long the interface is satisfied.
这里是C#中的一个例子: p>
here is an example in C#:
public interface IGenderCheckable
{
bool CheckGender();
}
public interface IAgeCheckable
{
bool CheckAge();
}
public class A : IAgeCheckable, IGenderCheckable
{
public virtual bool CheckGender()
{
return this.person1.Gender.Equals("M");
}
public virtual bool CheckAge()
{
return this.person1.Age > 30;
}
}
public class B : A
{
public override bool CheckAge()
{
// combine custom logic with new logic
return this.person1.Age < 0 || base.CheckAge();
}
}
对于复杂场景,两者的组合方法也可能被使用(当然比年龄和性别检查要复杂得多):
For complex scenarios, a combination of both approaches might be also used (of course for far more complex cases than age and gender checks):
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();
}
}
关于实例变量与局部变量的使用 - 在.NET中使用实例变量的性能有一个缺点,特别是当它们是值类型时。例如,使用 int _someIntMember
的本地成员转换为 this._someIntMember
- 这又将堆调用获取此
对象,然后访问其 _someIntMember
成员。将成员作为局部变量,将其值放在堆栈中,并从其中读取,而不需要通过堆的不必要的往返。此外,堆栈比堆快。
About usage of instance variables vs local variables - there is a drawback in performance of using instance variables in .NET especially when they are value types. Use of local member that is int _someIntMember
for example gets translated to this._someIntMember
- which in turn calls the heap to get the this
object, and then accesses its _someIntMember
member. Having the member as a local variable, puts its value in the stack, and reads it from there without the unnecessary roundtrip trough the heap. Moreover, the stack is faster than the heap.
但是,我不能说太多的堆使用是滥用它,也不是在使用太多时滥用局部变量。这取决于所需的性能和代码的复杂性。有时局部变量使代码更易于阅读,但是如果太多,你可以很容易地忘记每一个是什么(这可能比疏忽的性能增益更严重)。所以这是一个风格和必要性的问题。
However, I cannot say whether too much heap usage is an abuse of it, neither a misuse of local variables when they are used too much. This depends on the performance needed, and the complexity of code. Sometimes local variables make the code more-readable, but if too many, you could easily forget what each one was (and that can be more serious issue than the negligent performance gain). So it is a matter of style and necessity.
这篇关于VB.NET - 滥用实例变量?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!