Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

VB -> C#: IEnumerable linq extension methods are replaced with static Enumerable methods #1149

Open
gaschd opened this issue Nov 4, 2024 · 2 comments
Labels
VB -> C# Specific to VB -> C# conversion

Comments

@gaschd
Copy link
Contributor

gaschd commented Nov 4, 2024

IEnumerable.Select is replaced with Enumerable.Select if predicate is empty. Same happens to .Zip() and .OrderBy() but not to .Where().

It seems to be depended on the extension method used afterwards, while .Sum() and .Max() cause this bug, .Count() does not.

Tested with different numeric types, resulting in the same issue.

Also one generic type parameter is missing from the methods so it does not compile, e.g. .Select needs two but only has one or .Zip needs three but only has two.

VB.Net input code

    Public Class TestClass
        Public Shared Sub Test()
            Dim intCol = New Integer() {1, 2, 3}
            Dim intCol2 = New Integer() {1, 2, 3}

            Dim intColQuery = intCol.Select(Function(x) x)
            Dim intColCopy = intCol.Select(Function(x) x).ToArray()
            Dim intSum = intCol.Select(Function(x) x).Sum(Function(x) x)
            Dim intMax = intCol.Select(Function(x) x).Max(Function(x) x)
            Dim intCnt = intCol.Select(Function(x) x).Count(Function(x) x > 1)

            Dim intSum2 = intCol.Select(Function(x) x).Sum()
            Dim intMax2 = intCol.OrderBy(Function(x) x).Max()
            Dim intCnt2 = intCol.Select(Function(x) x).Count()
            Dim intSum3 = intCol.Zip(intCol2, Function(x, y) x + y).Sum()
        End Sub
    End Class

Erroneous output

public class TestClass
{
    public static void Test()
    {
        int[] intCol = new int[] { 1, 2, 3 };
        int[] intCol2 = new int[] { 1, 2, 3 };

        var intColQuery = intCol.Select(x => x);
        int[] intColCopy = intCol.Select(x => x).ToArray();
        int intSum = intCol.Select(x => x).Sum(x => x);
        int intMax = intCol.Select(x => x).Max(x => x);
        int intCnt = intCol.Select(x => x).Count(x => x > 1);

        var intSum2 = Enumerable.Select<int>((IEnumerable<int>)intCol, x => x).Sum();
        var intMax2 = Enumerable.OrderBy<int>((IEnumerable<int>)intCol, x => x).Max();
        int intCnt2 = intCol.Select(x => x).Count();
        var intSum3 = Enumerable.Zip<int, int>((IEnumerable<int>)intCol, (IEnumerable<int>)intCol2, (x, y) => x + y).Sum();
    }
}

Expected output

    public class TestClass
    {
        public static void Test()
        {
            int[] intCol = new int[] { 1, 2, 3 };
            int[] intCol2 = new int[] { 1, 2, 3 };

            var intColQuery = intCol.Select(x => x);
            int[] intColCopy = intCol.Select(x => x).ToArray();
            int intSum = intCol.Select(x => x).Sum(x => x);
            int intMax = intCol.Select(x => x).Max(x => x);
            int intCnt = intCol.Select(x => x).Count(x => x > 1);

            int intSum2 = intCol.Select(x => x).Sum();
            int intMax2 = intCol.OrderBy(x => x).Max();
            int intCnt2 = intCol.Select(x => x).Count();
            int intSum3 = intCol.Zip(intCol2, (x, y) => x + y).Sum();
        }
    }

Details

  • Product in use: VS extension
  • Version in use: 9.2.6.0
@gaschd gaschd added the VB -> C# Specific to VB -> C# conversion label Nov 4, 2024
@gaschd
Copy link
Contributor Author

gaschd commented Nov 5, 2024

The IsOriginalSymbolGenericMethod func in VbNameExpander returns true for the correct case (IsReducedTypeParameterMethod returns true), but is false for the wrongly converted case. Overwriting it with true yields the expected output for the input code.

The intSum assignment
Method Function System.Collections.Generic.IEnumerable(Of System.Int32).Sum(selector As System.Func(Of System.Int32, System.Int32)) As System.Int32
is reduced to the generic form:

Method Function System.Linq.Enumerable.Sum(Of TSource)(source As System.Collections.Generic.IEnumerable(Of TSource), selector As System.Func(Of TSource, System.Int32)) As System.Int32

while the intSum2 assignment
Method Function System.Collections.Generic.IEnumerable(Of System.Int32).Sum() As System.Int32
is reduced to a non generic form:
Method Function System.Linq.Enumerable.Sum(source As System.Collections.Generic.IEnumerable(Of System.Int32)) As System.Int32

@GrahamTheCoder
Copy link
Member

Thanks for the report. Sounds like you're close to a fix, feel free to PR ☺️

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
VB -> C# Specific to VB -> C# conversion
Projects
None yet
Development

No branches or pull requests

2 participants