0
votes

I have a calls called DtaDate that stores an integer "key", a string name, a string for the date, and a Date object that is created from that string.

I have some code that needs to accept a date-like object. I'd like the user to be able to pass in anything date like - a Date object which I'll extract the information from, another DtaDate, a string with the date in it, or even the key, which I'll use to look up the DtaDate from a collection.

So I have this:

    Friend Sub New(NameIn As String, DateFormulaIn As String, Optional FromDateIn As Object = Nothing)
[stuff that works]
[check that we got a FromDateIn...]
            If TypeOf FromDateIn Is DtaDate Then
                fdk = FromDateIn.Key
                Ans.FromDate = fdk

VB tells me that "Option Strict On disallows late binding". The other cases, where a string or integer is the TypeOf, I use CInt or CStr. But this is the first time I've actually run into a case where the casting is a non-base type. What's the trick?

2
can FromDateIn be anything else other than a DtaDate? it is the As Object which is prompting the warning - Ňɏssa Pøngjǣrdenlarp

2 Answers

1
votes

Your signature defines FromDateIn As Object. Later on, you're trying to treat it as a DtaDate by calling FromDateIn.Key. As far as the compiler knows, FromDateIn is just an Object, and doesn't have a Key property, and option strict prohibits late binding.

It looks like you're checking the type of FromDateIn and then acting based on that, so all you need to do is cast FromDateIn to a DtaDate. There are a few ways to do that.

fdk = CType(FromDateIn, DtaDate).Key
fdk = DirectCast(FromDateIn, DtaDate).Key
fdk = TryCast(FromDateIn, DtaDate).Key

DirectCast will convert the given variable if it is of the given type, or inherits or implements it.

CType does the same, but will also check to see if there is a conversion from its current type to the specified type. Both of these will throw an InvalidCastException on failure.

TryCast only works for reference types, and works like DirectCast, but returns Nothing on failure rather than throwing an exception.

Another alternative would be to provide three separate constructors, each of which takes a strongly typed variable, e.g.

Friend Sub New(NameIn As String, DateFormulaIn As String)
  '...handle case where no date is provided
End Sub

Friend Sub New(NameIn As String, DateFormulaIn As String, FromDateIn As DateTime)
  '...handle case where a DateTime is passed in
End Sub

Friend Sub New(NameIn As String, DateFormulaIn As String, FromDateIn As DtaDate)
  '...handle case where a DtaDate is passed in
End Sub

Friend Sub New(NameIn As String, DateFormulaIn As String, FromDateIn As String)
  '...handle case where a string is passed in
End Sub

This would be more work, but is also safer because the type being passed to the constructor can be checked at compile-time rather than at run-time.

0
votes

I would use the TryCast() method. If it can cast the source object to the specified type then it will, otherwise it sets it to Nothing.

Inside the If block reference the DtaFromDate, which will be the FromDateIn cast to DtaDate.

Friend Sub New(NameIn As String, DateFormulaIn As String, Optional FromDateIn As Object = Nothing)
[stuff that works]
[check that we got a FromDateIn...]

    Dim DtaFromDate As DtaDate
    TryCast(FromDateIn, DtaDate)
    If DtaFromDate IsNot Nothing Then
        fdk = DtaFromDate.Key
        Ans.FromDate = fdk

    End If