0

I can do this in VB.NET

Module ArrayExtension
    <Runtime.CompilerServices.Extension()>
    Public Sub Add(Of T)(ByRef arr As T(), item As T)
        If arr IsNot Nothing Then
            Array.Resize(arr, arr.Length + 1)
            arr(arr.Length - 1) = item
        Else
            ReDim arr(0)
            arr(0) = item
        End If

    End Sub
End Module

And NOT do this in C#

using System;

internal static class ArrayExtension
{
    public static void Add<T>(this ref T[] arr, T item)
    {
        if (arr != null)
        {
            Array.Resize(ref arr, arr.Length + 1);
            arr[arr.Length - 1] = item;
        }
        else
        {
            arr = new T[1];
            arr[0] = item;
        }
    }
}

In VB it works fine, I can use the extension without problems, but in C# "this" doesn't go with "ref". I've read other questions concerning extensions in C#, but my question is, how does it work in VB.NET? Since they belong to the same framework, that should be no problem... Is the "<Runtime.CompilerServices.Extension()>" directive the case? Thank you.

  • Sounds like you are using the wrong version of C#. by-reference `this` for extension methods is supported in C# 7.2 and later. In any case, while the underlying framework is the same, that does not mean that the languages all will have parity. There are significant differences in certain areas between VB.NET, C#, and F#. – Peter Duniho May 09 '21 at 02:55
  • @PeterDuniho Really? I thought C#7.2 only supports `this ref` for structs. – Sweeper May 09 '21 at 03:01
  • 2
    Suggestion: use a `List`, you're creating a new array everytime you need to add something by *resizing* and that's costly. – Trevor May 09 '21 at 03:01
  • @Sweeper: well, that's true AFAIK. It's not clear from the post whether that's material (though maybe it is, since there's no `struct` constraint). Maybe the question should be worded differently, to make clear that the OP is asking about the non-`struct` scenario (if indeed they are). Still, the duplicate provides links to documentation that provides rationale for that restriction, if that's what the OP is asking about. – Peter Duniho May 09 '21 at 03:02
  • "Since they belong to the same framework, that should be no problem..." Well yes, if you manually edit the compiled assembly to include the `ExtensionAttribute` (like your VB code), but your C# source code has to go through the C# compiler _first_, and _it_ can enforce any rule it likes. – Sweeper May 09 '21 at 03:04
  • @Djakson In VB.Net, when calling a method that has a `ByRef` parameter, you don't put `ByRef` in the method call, IE this is wrong in VB: `MyMethod(ByRef MyVariable)`, however, in C#, if a method parameter is `ref`, then in method calls, it has to use `ref`. IE, `MyMethod(ref MyVariable);`. Basically the reason it's possible in VB.Net is because the syntax allows for it, but in C#, where would you put the `ref`? – B.O.B. May 09 '21 at 05:07
  • Btw, all extensions are, syntax sugar. In both VB & C#, it takes your call like `myVar.MyExtension();` and converts it to `ClassName.MyExtension(myVar);`. Also, just an FYI, C# doesn't have 'Modules` like VB. The `static class` is close but not quite the same. However, there's two ways you can get close to VB in C# for modules: In your imports, you can do `using static YourNamespace.ArrayExtension;`, and then do calls like `Add(myArr, item);` versus `ArrayExtension.Add(myArr, item);` .... – B.O.B. May 09 '21 at 05:13
  • .... You can also use aliases in your imports, such as `using Arr = YourNamespace.ArrayExtension;`, and then your calls in that code would be `Arr.Add(myArr, item);`. This can allow your static class to have a meaningful name (such as ArrayHelper or ArrayExtensions), but not have to type out the long class name every single time, and instead use a shorter name in the code. – B.O.B. May 09 '21 at 05:18
  • My actual question was," Why it works with VB.NET and not with C#". In my opinion the closest explanation was from @B.O.B's Thank you all!!! – Djakson May 09 '21 at 11:55

0 Answers0