Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Generic method overloading compilation error in VB

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.

  1. 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
        {
        }
    }
    
  2. 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);
        }
    }
    
  3. 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.

like image 958
Mike Thompson Avatar asked Mar 20 '26 02:03

Mike Thompson


2 Answers

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.

like image 65
Konrad Rudolph Avatar answered Mar 21 '26 15:03

Konrad Rudolph


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
like image 27
Mattias S Avatar answered Mar 21 '26 16:03

Mattias S