Nullable(of Guid) with Generic Delegate causes weird (hidden) error?
Scroll to the bottom, EDIT 19 onwards. See @Chris's comments also for good examples
VB:
Public Class Class1
Private Delegate Sub AnEventHandler(Of T)(ByVal newValue As T)
Private Event OnSomething As AnEventHandler(Of Nullable(Of Guid))
End Class
C#:
public class Class1
{
private delegate void AnEventHandler<T>(T newValue);
private event AnEventHandler<Nullable<Guid>> OnSomething;
}
With the above VB code in .Net3.5 and .Net 4, Visual Studio 2008 and 2010, regardless of project type, you get the following error:
Type 'Global.System.Guid' is not defined.
You cannot navigate to the error by double clicking, and no line/coloumn numbers are given.
Do not quote from here that: "T" can only be a Class, an interface or a type parameter.
...because that is wrong, as proven below.
To confirm this statement, a couple of facts
Nullable is a structure. Yet, the following compiles:
Public Class Class1
Private Delegate Sub AnEventHandler(Of T)(ByVal newValue As T)
Private Event OnSomething As AnEventHandler(Of Nullable(Of Integer))
End Class
You can use Nullable Guids as shown here:
Private Sub StackOverflowTest()
Dim s As Nullable(Of Guid)
If s.HasValue Then
'Do something
End If
End Sub
That code compiles and works as you might imagine. Even the following code which uses generics and nullable guids works!!
Private Sub StackOve开发者_如何学JAVArflowTest2(Of T)()
' do stuff
End Sub
Private Sub StackOverflowTest3()
StackOverflowTest2(Of Nullable(Of Guid))()
End Sub
However, my particular example listed at the very top, does not work. Why? Clearly, T does work with structures...
EDIT 19ish! =D
- Create a VB.Net Console Application
Add the following to "Module1.vb"
Module Module1
Sub Main() Dim testCase1 As Nullable(Of Integer) testCase1 = 2190 StackOverflowTest1(Of Nullable(Of Integer))(testCase1) Dim testCase2 As Nullable(Of Guid) testCase2 = Guid.NewGuid StackOverflowTest1(Of Nullable(Of Guid))(testCase2) Dim testCase3 As Nullable(Of Guid) testCase3 = Nothing StackOverflowTest1(Of Nullable(Of Guid))(testCase3) End Sub Private Sub StackOverflowTest1(Of T)(ByVal param As T) Console.WriteLine(param.ToString) End Sub
End Module
Results:
2190
5ef4ed7c-2720-4b37-b8ca-4ac044ec70d0
<<< Nothing here to it just gave carriage return
LAST EDIT (I hope):
It's all gone quiet since Edit 19ish and @Chris reinforcing the issue with a good example (thank you Chris). I'll make the question a little easier (and attempt to tidy up all of the above), can anyone prove this is not an MS bug or similar? It seems to be something under the hood is not correctly wired up for VB.Net with regards to Nullable Structures and Events? However, all other cases using the Nullable Structures does appear to work?
It would appear to be a bug in the code generated behind the scenes by the VB.Net compiler. The following compiles fine, and should be functionally equivalent:
Public Class Class1
Private Delegate Sub AnEventHandler(Of T)(ByVal newValue As T)
Private OnSomethingEvent As AnEventHandler(Of Nullable(Of Guid))
Private Custom Event OnSomething As AnEventHandler(Of Nullable(Of Guid))
AddHandler(value As AnEventHandler(Of Nullable(Of Guid)))
Me.OnSomethingEvent = DirectCast(System.Delegate.Combine(Me.OnSomethingEvent, value), AnEventHandler(Of Nullable(Of Guid)))
End AddHandler
RemoveHandler(value As AnEventHandler(Of Nullable(Of Guid)))
Me.OnSomethingEvent = DirectCast(System.Delegate.Remove(Me.OnSomethingEvent, value), AnEventHandler(Of Nullable(Of Guid)))
End RemoveHandler
RaiseEvent(newValue As System.Guid?)
Dim aeh = OnSomethingEvent
If Not aeh Is Nothing Then
aeh(newValue)
End If
End RaiseEvent
End Event
End Class
(Hence, also, why you don't get line numbers for the errors - the errors are appearing in code that isn't present in any line you've written)
Unfortunately in VB a type parameter can only be a class, not a structure.
A quick and dirty workaround would be to box the Guid? within an Object.
I'm putting this one down to a bug in the Framework. I've posted a bug report on connect.
I'll not mark my own answer as the answer for another day or two, in case someone else can point out something we've overlooked so far.
Thanks everyone so far for your time!
精彩评论