6

First up, I am currently working with VB.NET and therefore not really knowledgeable in C#.

I wanted to create a custom generic Vector class with the constrain, that the type parameter must implement the interface INumber(Of T). However, when I tried to declare a +-operator in said class (using an element-wise addition of values given by two vectors), my VB.NET project produced following error:

Error BC30452 Operator '+' is not defined for types 'T' and 'T'

Since I pretty much only tested the example given on this page and didn't really believe, that Microsoft would publish something that wouldn't work, I decided to also test my problem in C# (also using .NET 7).

For that I build following two MWEs in VB.NET

Vector.vb:

Imports System.Numerics


Public Class Vector(Of T As INumber(Of T))

    Private _items() As T

    Public Sub New(n As Integer)
        ReDim _items(n - 1)
    End Sub

    Public ReadOnly Property Size As Integer
        Get
            Return _items.Length
        End Get
    End Property

    Public Function GetValue(i As Integer) As T
        Return _items(i)
    End Function

    Public Sub SetValue(i As Integer, val As T)
        _items(i) = val
    End Sub

    Public Sub SetAll(val As T)
        For i As Integer = 0 To _items.Length - 1
            _items(i) = val
        Next
    End Sub

    Public Sub Print()
        For i As Integer = 0 To _items.Length - 1
            Console.WriteLine(_items(i))
        Next
    End Sub

    Public Shared Operator +(a As Vector(Of T), b As Vector(Of T)) As Vector(Of T)
        Dim retVal As New Vector(Of T)(a.Size)
        For i As Integer = 0 To retVal.Size - 1
            retVal.SetValue(i, a.GetValue(i) + b.GetValue(i))
        Next
        Return retVal
    End Operator

End Class

Program.vb:

Module Program
    Sub Main(args As String())
        Dim x As New Vector(Of Double)(3)
        x.SetAll(3)
        Dim y As New Vector(Of Double)(3)
        y.SetAll(2)
        Dim z = x + y
        z.Print()
    End Sub
End Module


and in C#

Vector.cs:

using System.Numerics;


namespace Test
{
    public class Vector<T> where T : INumber<T>
    {
        private T[] _items;

        public Vector(int n) {
            Array.Resize<T>(ref _items, n);
        }
        public int Size {
            get { return _items.Length; }
        }
        public T GetValue(int i) {
            return _items[i];
        }
        public void SetValue(int i, T val){
            _items[i] = val;
        }
        public void SetAll(T val) {
            for (var i = 0; i < _items.Length; i++) {
                _items[i] = val;
            }
        }
        public void Print() {
            for (var i = 0; i < _items.Length; i++) {
                Console.WriteLine(_items[i]);
            }
        }
        public static Vector<T> operator +(Vector<T> a, Vector<T> b)
        {
            var retVal = new Vector<T>(a.Size);
            for (var i = 0; i < retVal.Size; i++) {
                retVal.SetValue(i, a.GetValue(i) + b.GetValue(i));
            }
            return retVal;
        }
    }
}

Program.cs:

using Test;


var x = new Vector<Double>(3);
x.SetAll(3);
var y = new Vector<Double>(3);
y.SetAll(2);
var z = x + y;
z.Print();

In each mwe two vectors (of Double) x,y with a length of 3 are created, so that all entries of x are 3 and all entries of y are 2. These vectors are then added together and saved in the vector z.

The C# project compiles without an error and produces follwing output

5
5
5

while the VB.NET project won't compile and throws above mentioned error.

I don't even really understand why the error is thrown in the first place. The type parameter was given the constrain, that it has to implement the interface INumber(Of T), which in return implements the IAdditionOperators(Of T,T,T) interface, which in return exposes the +-operator. I therefore thought, that T should be able to rely on said operator, like it does in C#, but not in VB.NET.

Is that an error on my site or is VB.NET not working correctly in that regard?

  • that one of the many many bugs – nbk Aug 08 '23 at 21:35
  • The use of static abstract members requires language support. You'd have similar response with C# 10 (IIRC) -- VB.NET is a semi-dead language – Jimi Aug 08 '23 at 21:41
  • 3
    @nbk Explicitly not a bug. It works as documented for VB, and the documentation has been consistent since the beginning. – Joel Coehoorn Aug 08 '23 at 21:44
  • this ids for me still a bug, like many other that i reported and that M$ will not fix – nbk Aug 08 '23 at 21:57
  • @nbk, you are not the arbiter of what is and isn't a bug. You may not like it that they won't add a feature to the language but it's not a bug unless they tried to add it and failed in the implementation. – jmcilhinney Aug 09 '23 at 01:54

1 Answers1

8

Generic math was introduced in C# 11, which was released in November 2022.

Visual Basic hasn't had a new version since 2019. Currently, Microsoft's stated strategy for Visual Basic is to not adopt features that would require changes to the language:

We will ensure Visual Basic remains a straightforward and approachable language with a stable design. The core libraries of .NET (such as the BCL) will support VB and many of the improvements to the .NET Runtime and libraries will automatically benefit VB. When C# or the .NET Runtime introduce new features that would require language support, VB will generally adopt a consumption-only approach and avoid new syntax. We do not plan to extend Visual Basic to new workloads.

So this is just a case of a feature that C# got that Visual Basic didn't. Over time, there will be more such features, as C# continues to evolve and Visual Basic stays "stable."

StriplingWarrior
  • 151,543
  • 27
  • 246
  • 315
  • Yep. An interface is just an interface, until you add specific compiler support for it to do extra things. IDisposable+using is another example of this, though at least VB.Net also support that enhancement. – Joel Coehoorn Aug 08 '23 at 21:42
  • 3
    @JoelCoehoorn: I think VB supported `using` way back at the dawn of time (2002-2003), didn't it? At various times, VB has supported things that C# didn't. Some of them C# picked up up (`when` on the catch of an exception) and others that C# didn't (like XML literals). – Flydog57 Aug 08 '23 at 22:45
  • @Flydog57 INumber didn't exist until last year. – Joel Coehoorn Aug 09 '23 at 14:04