I have a namespace with a class inside it with another class inside that, i.e.
namespace MySpace
public class MainClass
public class SubClass
public x as integer
public z as integer
end class
public function Foo ()
dim y as SubClass
y.x = 5
return
end function
end class
end namespace
except the line y.x = 5 gets underlined with the tip "Variable y is used before it has been assigned a value. A null exception could result at runtime"
Basically I want to be able to have the multiple items that Foo assigns then available to whatever other code is using the MainClass class. What is the safest way to do this? If I was doing this in C I would have used a struct but apparently they are less efficient in VB?
You could make x and z shared:
Public Class SubClass
Public Shared x As Integer
Public Shared z As Integer
End Class
Or you can instantiate a class-level variable:
Public Class MainClass
Private m_objSubClass As New SubClass2
and call like so:
Public Function Foo()
'Shared
SubClass.x = 5
'Instantiated Class-Level variable
m_objSubClass.x = 5
End Function
If the Subclass needs to be accessed by other classes then expose the instantiated version through a Property instead of just a private variable (or return the instantiated version in your function).
Return m_objSubClass
Finally, if your values do not need to persist, you could simply instantiate a Subclass2 in the function:
Dim objSubClass2 As New SubClass2
objSubClass2.X = 5
Return objSubClass2
Related
I would like to start that I don't want a to hear about how expensive and terrible reflection is. That won't help—I have a very good reason to use reflection and that's not my question.
Specifically, I have a class within a class that contains several static properties of the same type.
Public Class Foo
Public Class Bar
Public Shared Property prop1 As New CustomClass()
Public Shared Property prop2 As New CustomClass()
Public Shared Property prop3 As New CustomClass()
End Class
End Class
Public Class CustomClass
Public Sub DoStuff()
End Sub
End Class
I'm looking to create a method in Foo that calls DoStuff on each of the properties contained within it. How can I do this? Here's the general idea of what I want to include in Foo, but I obviously can't convert PropertyInfo to CustomClass:
Private Sub Example()
For Each prop As PropertyInfo In GetType(Foo.Bar).GetProperties()
DirectCast(prop, CustomClass).DoStuff()
Next
End Sub
How can I get the static properties and cast them to CustomClass objects?
PropertyInfo represents the type's property get/set method pair. To evaluate the getter you simply call GetValue, like so:
(in C# because I'm a language snob)
foreach( PropertyInfo pi in typeof(Foo.Bar).GetProperties() ) {
// Use null as arguments because it's a static property without an indexer.
Object got = pi.GetValue( null, null );
CustomClass got2 = got as CustomClass;
if( got2 != null ) {
Console.WriteLine( got2.ToString() );
}
}
And to convert Dai's answer to VB because I'm not a language snob:
For Each pi As System.Reflection.PropertyInfo in Foo.Bar.GetType.GetProperties()
' Use nothing as arguments because it's a shared property without an indexer.
Dim got = pi.GetValue(Nothing, Nothing)
Dim got2 as CustomClass = DirectCast(got, CustomClass)
If Not IsNothing(got2) Then Console.WriteLine(got2.toString())
Next
huzzah for less lines and more keystrokes...
Please take a look at the code below:
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 loops through three persons and does two checks: b.CheckGender and c.CheckAge. CheckGender and CheckAge use an instance variable from the superclass A.
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?
Please note that the above code is a hypothetical example. CheckGender and CheckAge are complex functions in the actual application.
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:
Conform to a specific interface or base class, that A, B and C classes have to implement/extend, and that interface or base class provides the CheckGender and CheckAge 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.
Here is example in 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);
Provide specific implementation to the classes. If you have to some logic in CheckAge for instances of A, but either completely different validation for instances of B, or a combination of the existing and some new logic in C, then inheritance is your friend. Still, if that is the case, I'd prefer exposing the CheckGender and CheckAge to interface and call them via the interface. That way, inheritance is valid, but not mandatory, as long the interface is satisfied.
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();
}
}
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.
In case you're interested in "fixing" your code to make Person a Property rather than a field, change the implementation of Class A as follows:
Public Class A
Public Property Person1 As Person
Public Overridable Function ComputeAge() As Integer
Return Person1.Age
End Function
End Class
The benefit here is you have the ability to add additional abstractions over getting and setting this property down the road if you need to. The compiler will generate a hidden private backing field for the auto property. You would still access the Person1 from any implementing classes:
Public Class B
Inherits A
Public Overrides Function ComputeAge() As Integer
Return MyBase.Person1.Age.AddYears(1)
End Function
End Class
Please have a look at the function below:
Public Function Test(ByVal i As Integer) As Animal
If i = 1 Then
Return New Dog
Else
Return New Cat
End If
End Function
A dog or a cat is returned by the function depending on whether the value of the integer is 1 or not. How is this approached if Dog and Cat are Static classes? i.e. you cannot create an instance of a static class. I have read a few webpages on the MSDN website this afternoon talking about static classes, but I have not found an answer to my specific question.
The term "static class" is a C# concept, it doesn't exist in VB.NET. So, no, this isn't possible.
It isn't possible in C# either, a static class can only derive from Object. The closest VB.NET equivalent of a static class is Module. Quite unsuitable.
You can certainly return a static instance of a class. Declare the variable in a Module or use the Shared keyword if you want to declare it inside a class.
Class Example
Private Shared theDog As Dog
Private Shared theCat As Cat
Public Shared Function Test(ByVal i As Integer) As Animal
If i = 1 Then Return theDog Else Return theCat
End Function
End Class
How is this approached if Dog and Cat are Static classes?
This isn't. You can't "return a static class" - you need to always return an object. You could use a static/shared method on a class to generate or operate on the object. For example, if you had a factory creation method on the types, you could do something like:
Public Function Test(ByVal i As Integer) As Animal
If i = 1 Then
Return Dog.Create(i)
Else
Return Cat.Create(i)
End If
End Function
I got an object(myObject) type Object. myObject inherits of another class that contain a fonction (ImyFunction). I want to call the function, but my project need to be in "Option Strict On". So it ask for declaration of the object.
Public MustInherit Class IClass(Of T1)
...
Public Sub IMyFunction()
...
Public Class myClass1 : Inherits IClass(Of Item1)
...
Public Class myClass2 : Inherits IClass(Of Item2)
dim obj as object = new myClass1
...
obj.IMyFunction 'at this moment, I dont know whish class base of IClass I have
(its just a sample)
I cant do obj.IMyFunction because of the strict option.
Maybe there's a cast way?
The MustInherit keyword does not mean that you cannot use it as a variable type, it just means that you cannot instantiate it. For instance:
Dim obj As IClass(Of Item1) = New myClass1() ' This works
Dim obj2 As IClass(Of Item1) = New IClass(Of Item1)() ' This will not compile
However since, it's generic, you have to specify the type of T1, so there's no way to do what I think it is that you really want to do:
Dim obj As IClass = New myClass1() ' Can't do this
obj.iMyFunction()
What I would recommend, in this case, would be to make either a non-generic base class or interface, like this:
Public Interface IInterface
Sub IMyFunction()
End Interface
Public MustInherit Class IClass(Of T1)
Implements IInterface
End Class
Then, you could do something like this:
Dim obj As IInterface = New myClass1()
obj.IMyFunction()
Consider the following case:
Public Interface IHasDateUpdated
Property DateUpdated As DateTime
End Interface
Public Class MyClass
Implements IHasDateUpdated
Public Property MyDateUpdated As DateTime Implements IHasDateUpdated.DateUpdated
End Class
Now, assuming I was referencing an instance of MyClass as an IHasDateUpdated; how would I determine the actual name of the property that implements the interface property via reflection?
For example:
Dim x As IHasDateUpdated = New MyClass()
' How do I derive "MyDateUpdated" from "x" using x.DateUpdated?
Sorry flor the c# answer but you should be able to translate this I'm suer :)
InterfaceMapping im = y.GetInterfaceMap(typeof(IHasDateUpdated ));
foreach (MethodInfo info in im.TargetMethods)
{
if (info.IsPrivate)
MessageBox.Show(info.Name + " is private");
}
MessageBox.Show(y.FullName);