Opinions on 'Object' Usage <vb.net>

NeuralJack

Centurion
Joined
Jul 28, 2005
Messages
138
I use Lists from System.Collections.Generic constantly. Love em, love em, love em.

Here's my question though. I would like to broaden some functions to work on many different lists that I have. I usually avoid using variables defined initally as 'Objects' just because it seems safer to use variables defined as the type of object that you're going to use. But, for this, it looks like defining an object and assigning the proper List to it might be the only way to accomplish what I want.

My guess is that using the Object variable really shouldnt be bad as long as I only use functions that the List object has. I'm trying to cut down on code, but not at the cost of stability. Let me know what you think.

Code:
Dim List1 as New List(of Class1)
Dim List2 as New List(of Class2)
Dim List3 as New List(of Class3)

Dim ListChoice as Integer = 1

Private Sub DeleteLastEntryOfChosenList()
   'Select Proper List
   Dim SelectedList as New Object
   If ListChoice = 1 Then
      SelectedList = List1
   Elseif ListChoice = 2 Then
      SelectedList = List2
   Elseif ListChoice = 3 Then
      SelectedList = List3
   Else
      SelectedList = Nothing
   EndIf

   If SelectedList IsNot Nothing Then
       If SelectedList.Count > 0
           SelectedList.RemoveAt(SelectedList.Count - 1)
       EndIf
   EndIf

End Sub

Of course, my functions are much bigger than DeleteLastEntryOfChosenList and so the code consolidation would be worth it.

Edit: The other thing I'll do is add a verification procedure that will check if the object SelectedList is one of the many valid types of Lists before proceeding. If i do that there really should be no harm in doing it this way, I'm guessing.
 
Last edited:
I would avoid Object as a datatype wherever possible - in this case because the generic list class implements the IList interface anyway you could simply use
Visual Basic:
'Select Proper List
Dim SelectedList As IList
If ListChoice = 1 Then
    SelectedList = List1
ElseIf ListChoice = 2 Then
    SelectedList = List2
ElseIf ListChoice = 3 Then
    SelectedList = List3
Else
    SelectedList = Nothing
End If

If SelectedList IsNot Nothing Then
    If SelectedList.Count > 0 Then
        SelectedList.RemoveAt(SelectedList.Count - 1)
    End If
End If
and avoid the use of Object - will even compile with Option Strict On (you do use Option Strict On I'm assuming) and you still get intellisense for the SelectedList variable.
 
Thanks PD
Dim SelectedList As IList - is what I was looking for.
And you caught me , my option strict is on Custom. It shall be ON from now on.
 
Hey , ya know what's fun is turning on Option Strict after you're far into a project! Actually, it's not a big deal because I was already extensively testing the object Type before I did any implicit conversions.

So it looks like the main thing I need to do for Option Strict is use DirectCast and handle potential errors during the DirectCast.

So there really shouldnt be much of a problem using Option Strict On.

But there are one or two classes that i'm really wanting to use 'Object' variables in because the variable could hold one of many different types. If that class used a Declaration of each of those types the code would get very tedious. Is using an Object variable safe as long as you extensively check it's Type and use DirectCast when using it?
 
If there are several different object types that you need to perform the same operation on then you should really be looking at implementing an interface.

Could you give a bit more detail about the kind of objects you are using where you feel 'Object' is the best way?
 
Last edited:
Sure , here is more detail.

In the project the user can make lists of actions that they want to do. In the code the lists of commands are Generic Lists of a Command Class. In the command class there is a variable called 'action' which is an enumeration variable, because there are only so many actions you can perform. But, each action requires many different types of information to perform work. Those pieces of information are stored in different classes.

So Action1 needs Class1 to store information about how to execute Action1. But Action2 needs Class2 to store information about how to execute Action2. But Some actions are able to use the same information class. Anyway, I ended up using an 'Object' variable called 'ActionObject' to hold that information class (Class1 and Class 2 in the example) in the Command Class. I then test the type of ActionObject before I ever pull information out of it to make sure it's the proper object.

If i didnt use this ActionObject the only way I could see doing things is to declare an instance (or at least a declaration) of each and every information class in each and every Command class. That would take up memory, and it seems nasty, but i could be wrong.
 
Could you not define an interface that all actions implement (IAction or similar)? That way you would never need to know the actual implementation - the majority of your code works with the interface.
 
I have never used or defined interfaces before. So I'll read up on them and see about using them. Each time I post here I learn 100 new things.

I can only guess at all the techniques i'm missing out on by not being a professional programmer and not talking to colleagues daily. I wonder if there is an IRC chat place.
 
Different object model

I interpret your description to mean that you have a class Command which represents a command/action that can be performed. Exactly what action it represents is set by an enumeration, and based on the value of this property the Command class performs the appropriate action by using another object (ActionObject) of arbitrary type which contains specific details of how to perform the action.

If I've misinterpreted the situation then you can probably ignore the rest of this post.

I would suggest that rather than having one Command class which deals with all actions, you have an abstract (MustInherit) generic Command class, or an ICommand interface, which specifies the methods that all commands must have. Then, create subclasses of Command (or implement ICommand) for each of the different actions that might be performed. Since each subclass will be specific to one particular action, it can store and use the relevant ActionObject object. Each subclass could also expose this object independently of the inheritance/interface, so that when correctly cast it can be accessed directly.

Obviously at some point the application will need to know the specific type of Command/ICommand so that it can use the ActionObject correctly. It is unlikely that this can be completely avoided. However, using the above approach should greatly reduce the amount of type checking and casting required, and separating each action into its own Command class will aid maintainability and expandability.

Good luck :cool:
 
Mr. Paul you figured out my description exactly right. And thanks for introducing me to some new concepts, namely Abstract Classes /MustInherit, etc. And it's great that you can define Lists with abstract classes.

So here is the basis of my new model, tell me what you guys think, I'd like to get editing old code asap. I still need to use a Cast when i pull out data.. and i'm not sure If i can avoid it. But at least I am not casting from Objects anymore in this model.

What I needed here was to use a list to hold Command classes (C1, C2,...). Then I wanted to be able to pull out the data in C1, C2 from that list later.
Code:
 Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
        'Make List with the Abstract Class C_Base
        Dim List As New List(Of C_Base)
        'Create New C1 Class and Add to List
        Dim NewC1 As New C1
        NewC1.str_C1_Specific = "From C1"
        List.Add(NewC1)
        'Create New C2 Class and Add to the same List
        Dim NewC2 As New C2
        NewC2.float_C2_Specific = 55.678
        List.Add(NewC2)


        'Get Data From Commands in the List
        For i As Integer = 0 To List.Count - 1
            If List(i).CmdType = CommandType.Command1 Then
                'Retrieve a C1 Specific Variable from list
                Dim GetC1 As C1 = CType(List(0), C1)
                Debug.WriteLine(GetC1.str_C1_Specific)
            ElseIf List(i).CmdType = CommandType.Command2 Then
                'Retrieve a C2 Specific Variable from the same list
                Dim GetC2 As C2 = CType(List(1), C2)
                Debug.WriteLine(GetC2.float_C2_Specific)
            End If
        Next

    End Sub

    Public MustInherit Class C_Base
        Public ACommonVar As String
        Public CmdType As CommandType
    End Class

    Public Class C1 : Inherits C_Base
        Public Sub New()
            CmdType = CommandType.Command1
        End Sub

        Public str_C1_Specific As String
    End Class

    Public Class C2 : Inherits C_Base
        Public Sub New()
            CmdType = CommandType.Command2
        End Sub

        Public float_C2_Specific As Single
    End Class

    Public Enum CommandType
        Command1
        Command2
    End Enum
 
Inheritance continued

That looks a lot better. In this case it is clearly only to demonstrate the concept, but if your loop contained an operation to be performed on every command, then you could define that operation in C_Base and declare it MustOverride, forcing the subclasses to define their own implementation:

Visual Basic:
Public MustInherit Class C_Base
    'etc

    'Method which is command-specific
    Public MustOverride Function GetData() As String
End Class

Public Class C1
    Inherits C_Base
    'etc

    Public Overrides Function GetData() As String
        Return m_str_C1_Specific
    End Sub
End Class

Public Class C2
    Inherits C_Base
    'etc

    Public Overrides Function GetData() As String
        Return m_float_C2_Specific.ToString()
    End Sub
End Class

This means the loop can be greatly simplified:

Visual Basic:
For i As Integer = 0 To List.Count - 1
    Debug.WriteLine(List(i).GetData())
Next

Also note that when you do need to know the type of command, you can just test the type of the class instance, rather than requiring the enumeration:

Visual Basic:
If TypeOf List(i) Is C1 Then
    'Dealing with a C1
ElseIf TypeOf List(i) Is C2 Then
    'Dealing with a C2
End If

Good luck :cool:
 
Re: Inheritance continued

Yep, I plan on using a MustOverride Function 'CopyToMe'. Also, I was planning on using an enumeration variable to see what type of command it is because I actually was not going to make a class for each command type because many commands share the same type of data. For instance, some commands, only need to keep track of one string variable, while others need to keep track of many different variables.

But making each command type have it's own class might be advantageous for other reasons, i'll have to think about it. It'd be best if i could work around having to pull data out as much as possible anyway, to avoid CTyping. There is a chance I could use a MustOverride function that would actually execute the Command instead of the way i'm doing it now which is me pulling out the data in an 'execution' class and then executing the command based on that data. I'll look to see if there is some reason that I cant do that.
Either way, I've got lots of editing to do
Thanks again.
 
Back
Top