2013-10-07 32 views
2

扩展转换我有下面的代码,我在VB中工作:允许VB

Public Shared Function LoadFromSession(Of T)(sessionKey As String) As T 
    Try 
     ' Note: SBSSession is simply a reference to HttpContext.Current.Session 
     Dim returnValue As T = DirectCast(SBSSession(sessionKey), T) 
     Return returnValue 
    Catch ex As NullReferenceException 
     ' If this gets thrown, then the object was not found in session. Return default value ("Nothing") instead. 
     Dim returnValue As T = Nothing 
     Return returnValue 
    Catch ex As InvalidCastException 
     ' Instead of throwing this exception, I would like to filter it and only 
     ' throw it if it is a type-narrowing cast 
     Throw 
    End Try 
    End Function 

我想这样做是抛出任何收缩转换异常。例如,如果我将一个十进制数字像5.5保存到会话中,然后尝试将其作为整数检索,那么我想抛出一个InvalidCastException异常。 DirectCast做得很好。

但是,我想允许扩大转换(例如,将一个像5这样的整数保存到会话中,然后将其作为十进制进行检索)。 DirectCast不允许这样做,但CType呢。不幸的是,CType也允许缩小转换次数,这意味着在第一个示例中,它将返回值6.

有没有一种方法可以实现所需的行为?也许通过使用VB的Catch...When来过滤异常?

+1

嗯,不,DirectCast只允许将值拆箱以与盒装值类型完全相同的类型。这样做有太多问题,例如,从Integer到Single的转换无法可靠工作。试试16777217的值。Double to Decimal也无法工作,范围不够。有没有漂亮的解决方案,最好不要这样做。 –

+0

@HansPassant我主要关注Integer到Decimal,但我想我可能会更好,只要抛出InvalidCastException,只要DirectCast想抛出它。 –

+0

您可能可以使用GetType方法查找所涉及的类型并筛选InvalidCastException Catch块中的缩小转换。 – tinstaafl

回答

2

为了解决我在评论中留下的警告,您实际上可以捕捉到CType允许的缩小转换。 Type.GetTypeCode()方法是一种方便的方法,它按大小排序值类型。使这个代码工作:

Public Function LoadFromSession(Of T)(sessionKey As String) As T 
    Dim value As Object = SBSSession(sessionKey) 
    Try 
     If Type.GetTypeCode(value.GetType()) > Type.GetTypeCode(GetType(T)) Then 
      Throw New InvalidCastException() 
     End If 
     Return CType(value, T) 
    Catch ex As NullReferenceException 
     Return Nothing 
    End Try 
End Function 

我看到的唯一古怪的一个是,它将允许从char转换为字节。

+0

我认为这将是我的问题的最佳解决方案。但是,我打算按照您的原始建议去处理,并且只是抛出异常。 –

1

由于狭窄不一般了主意,因为在评论中提到的,它可能是更好地检查类型和转换特定情况下,你所希望的方式:

dim q as object = SBSSession(sessionKey) 
If q.GetType Is GetType(System.Int32) Then ... 

与一般的狭窄的问题,拓宽的是它不是单向关系。有时候,一个对类型可以包含一个值,而另一个不能。