I have a problem with the VB.NET compiler failing to compile a class (in a separate C# assembly) which contains two overloads of a method with generic arguments. The equivalent code in C# compiles against the same assembly with no errors.
Here are the two method signatures:
protected void SetValue<T>(T newValue, ref T oldValue)
protected void SetValue<T>(T? newValue, ref T? oldValue) where T : struct
Here is the code to three assemblies that demonstrate the problem. The first is the C# assembly with a Base class that implements the generic methods. The second is a C# class derived from Base and calls both overloads of SetValue correctly. The third is a VB class also derived from Base, but fails to compile with the following error message:
Error 1 Overload resolution failed because no accessible 'SetValue' is most specific for these arguments: 'Protected Sub SetValue(Of T As Structure)(newValue As System.Nullable(Of Integer), ByRef oldValue As System.Nullable(Of Integer))': Not most specific. 'Protected Sub SetValue(Of T)(newValue As System.Nullable(Of Integer), ByRef oldValue As System.Nullable(Of Integer))': Not most specific.
Base Class assembly
example:
public class Base
{
protected void SetValue<T>(T newValue, ref T oldValue)
{
}
protected void SetValue<T>(T? newValue, ref T? oldValue) where T : struct
{
}
}
C# Derived Class
example:
public class DerivedCSharp : Base
{
private int _intValue;
private int? _intNullableValue;
public void Test1(int value)
{
SetValue(value, ref _intValue);
}
public void Test2(int? value)
{
SetValue(value, ref _intNullableValue);
}
}
VB Derived Class
example:
Public Class DerivedVB
Inherits Base
Private _intValue As Integer
Private _intNullableValue As Nullable(Of Integer)
Public Sub Test1(ByVal value As Integer)
SetValue(value, _intValue)
End Sub
Public Sub Test2(ByVal value As Nullable(Of Integer))
SetValue(value, _intNullableValue)
End Sub
End Class
Am I doing something wrong in the VB code, or are C# & VB different when it comes to generic overload resolution? If I make the method arguments in Base non-generic then everything compiles correctly, but then I have to implement SetValue for every type that I wish to support.
I stand by my comment that this is most likely a bug. However, I can reproduce it using the Mono VB compiler vbnc. The (somewhat mangled) error message here is “No non-narrowing (except object)” – which I presume refers to missing implicit conversions and hence to the same overload resolution problem.
The problem seems to be that the overload resolution of the compiler fails because of the ByRef arguments, since that requires some special management which is made explicit in the C# call but not in the VB call.
It seems like you have to help the VB compiler a little to pick the right overload to call. The following compiles for me
Public Sub Test1(ByVal value As Integer)
SetValue(Of Integer)(value, _intValue)
End Sub
Public Sub Test2(ByVal value As Nullable(Of Integer))
SetValue(Of Integer)(value, _intNullableValue)
End Sub
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With