Jump to content
Xtreme .Net Talk

Recommended Posts

Posted (edited)

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.

 


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.

Edited by NeuralJack
Currently Using: Visual Basic.Net 2005, .Net Framework 2.0
  • Administrators
Posted

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

'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.

Posting Guidelines FAQ Post Formatting

 

Intellectuals solve problems; geniuses prevent them.

-- Albert Einstein

Posted

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.

Currently Using: Visual Basic.Net 2005, .Net Framework 2.0
Posted

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?

Currently Using: Visual Basic.Net 2005, .Net Framework 2.0
  • Administrators
Posted (edited)

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?

Edited by PlausiblyDamp

Posting Guidelines FAQ Post Formatting

 

Intellectuals solve problems; geniuses prevent them.

-- Albert Einstein

Posted

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.

Currently Using: Visual Basic.Net 2005, .Net Framework 2.0
Posted

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.

Currently Using: Visual Basic.Net 2005, .Net Framework 2.0
Posted

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:

Never trouble another for what you can do for yourself.
Posted

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.


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

Currently Using: Visual Basic.Net 2005, .Net Framework 2.0
Posted

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:

 

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:

 

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:

 

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:

Never trouble another for what you can do for yourself.
Posted

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.

Currently Using: Visual Basic.Net 2005, .Net Framework 2.0

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...