为什么 C# 允许在具有约束 INumber 的泛型类中使用 + 运算符,而 VB.NET 不允许?

Had*_*fel 6 c# vb.net .net-7.0

首先,我目前正在使用 VB.NET,因此对 C# 并不了解。

我想创建一个带有约束的自定义泛型 Vector 类,即类型参数必须实现接口INumber(Of T)。但是,当我尝试在所述类中声明+ 运算符(使用两个向量给定值的元素级加法)时,我的 VB.NET 项目产生了以下错误:

错误 BC30452 未为类型“T”和“T”定义运算符“+”

由于我几乎只测试了本页给出的示例,并且并不真正相信 Microsoft 会发布一些不起作用的东西,因此我决定也在 C# 中测试我的问题(也使用 .NET 7)。

为此,我在VB.NET中构建了以下两个 MWE

矢量.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
Run Code Online (Sandbox Code Playgroud)

程序.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
Run Code Online (Sandbox Code Playgroud)

在C#

矢量.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;
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

程序.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();
Run Code Online (Sandbox Code Playgroud)

在每个 mwe 中,创建两个长度为 3 的(双精度)向量 x,y,因此 x 的所有条目均为 3,y 的所有条目均为 2。然后将这些向量相加并保存在向量 z 中。

C# 项目编译时没有错误并产生以下输出

5
5
5

而 VB.NET 项目将无法编译并抛出上述错误。

我什至不太明白为什么会首先抛出该错误。类型参数受到约束,即它必须实现接口 INumber(Of T),该接口反过来实现 IAdditionOperators(Of T,T,T) 接口,该接口又公开 + 运算符。因此我认为,T 应该能够依赖所述运算符,就像在 C# 中那样,但在 VB.NET 中不行。

这是我的网站上的错误还是 VB.NET 在这方面无法正常工作?

Str*_*ior 8

通用数学是在 2022 年 11 月发布的C# 11 中引入的。

自 2019 年以来, Visual Basic就没有新版本。目前,Microsoft 针对 Visual Basic 的既定策略是不采用需要更改语言的功能:

我们将确保 Visual Basic 仍然是一种简单易懂的语言,具有稳定的设计。.NET 的核心库(例如 BCL)将支持 VB,并且 .NET 运行时和库的许多改进将自动使 VB 受益。当 C# 或 .NET 运行时引入需要语言支持的新功能时,VB 通常会采用仅使用方法并避免新语法。我们不打算将 Visual Basic 扩展到新的工作负载。

因此,这只是 C# 拥有而 Visual Basic 没有的功能的一个例子。随着时间的推移,随着 C# 的不断发展和 Visual Basic 的保持“稳定”,将会出现更多这样的功能。

  • @JoelCoehoorn:我认为 VB 在早期(2002-2003 年)就支持“使用”,不是吗?在不同时期,VB 支持 C# 不支持的功能。其中一些是 C# 拾取的(捕获异常时的“when”),而其他 C# 没有拾取的(例如 XML 文字)。 (3认同)