views:

22

answers:

1

I have to do an export from DB to CSV. (.NET 2)

field; fileld; field... etc

Have 3 types of fields: Alpha, Numeric and Bool respresented as "alphaValue",intValue and True/False.

I try to encapsulate this in a fields collection, in order to export if alpha then set "", if Bool=>True/False if numeric let as is.

and try to build a CsvField class:

  Public Structure?Class CsvField(Of T As ???)

  End Structure

  Enum FieldType
    Alpha
    Bool
    Numeric
  End Enum

possibile usage:

myCollection.Add(new CsvField(DateTime.Now, FileType.Alpha))
myCollection.Add(new CsvField(myInt, FileType.Numeric))

any suggestions welcomed.

+2  A: 

No generics needed. Simply use inheritance:

' abstract base class; you could possibly declare it as an interface instead: '
MustInherit Class CsvField
    Public MustOverride Function Export() As String
End Class


' specialized class for alpha-numeric fields: '
Class AlphaCsvField : Inherits CsvField
    ...
    Public Overrides Function Export() As String
        Return String.Format("""{0}""", value)
    End Function

    Private value As String
End Class


' specialized class for bool fields '
Class BoolCsvField : Inherits CsvField
    ...
    Public Overrides Function Export() As String
        If value = True Then
            Return "True"
        Else
            Return "False"
        End If
    End Function

    Private value As Boolean
End Class

...

The code example assumes that value stores the actual value of a field. I hope this example is sufficiently clear. Make your fields collection one for type base class type, e.g. List(Of CsvField). It can then contain objects of all derived types, too.


Btw., note how, when using polymorphism, you might be able to get rid of the FieldType enumeration completely and all If / Select Case constructs that decide on what to do depending on the field type. If you still need to do that, you could replace:

If someCsvField.FieldType = Alpha Then ...

with

If TypeOf someCsvField Is AlphaCsvField Then ...

However, you should generally be able to move such logic into the derived classes and get rid of the If statements by overriding methods. This is the whole point of the above example.


P.S.: In case you're wondering how you create your CsvField objects without checking explicitly on the type. One way is to use factory methods and method overloading:

MustInherit Class CsvField

    Public Shared Function Create(value As String) As CsvField
        Return New AlphaCsvField(value)
    End 

    Public Shared Function Create(value As Boolean) As CsvField
        Return New BoolCsvField(value)
    End 

    ...

    ' as in the above code example '
    Public MustOverride Function Export() As String

End Class

For example, CsvField.Create(False) would create a BoolCsvField "disguised" as a CsvField, so that you can put it inside your List(Of CsvField) or whatever collection you have.

stakx
is the polymorphism more resources and time consuming that a simple class with type?
serhio
@serhio no, there's no resource or performance penalty when using inheritance and polymorphism.
Paulo Santos
@serhio: No, or at least the additional *memory* overhead would be so small as to be insignificant in your case (most likely). Runtime *performance* might even improve very slightly. Don't worry about this. Using inheritance will result in better-structured, easier-to-read and thus more maintainable code, which is more important than a few additional used bytes in memory. If you're still interested in the reason for this, I can provide more details on demand.
stakx
why `Create(value As Boolean)` returns a `CsvField` and not a `BoolCsvField`?
serhio
@serhio: Because whoever calls the factory method should not need to be made aware of what exact type of `CsvField` is created. The important thing is that the caller will be able to get to the `Export` method through the returned object. Try to program against the generic "interface" provided by the abstract `CsvField` class as much as possible, because then you won't need to change your program if you'd later decide that you need a new field type. The program logic will only depend on the generic `CsvField` and not on any specific subclasses.
stakx