dotnet / roslyn

The Roslyn .NET compiler provides C# and Visual Basic languages with rich code analysis APIs.
https://docs.microsoft.com/dotnet/csharp/roslyn-sdk/
MIT License
18.91k stars 4.01k forks source link

Roslyn compiler emits different code for NewExpression for anonymous type with no members #12297

Open bartdesmet opened 8 years ago

bartdesmet commented 8 years ago

Self-contained repro, comparing against C# 5 native compiler:

C:\Temp>type a.cs
using System;
using System.Linq.Expressions;

class A
{
    static void Main()
    {
        var m = ((NewExpression)((Expression<Func<object>>)(() => new {})).Body).Members;
        Console.WriteLine(m == null ? "null" : m.Count.ToString());
    }
}

C:\Temp>csc a.cs
Microsoft (R) Visual C# Compiler version 1.1.0.51204
Copyright (C) Microsoft Corporation. All rights reserved.

C:\Temp>a
null

C:\Temp>c:\Windows\Microsoft.NET\Framework\v4.0.30319\csc a.cs
Microsoft (R) Visual C# Compiler version 4.6.1038.0
for C# 5
Copyright (C) Microsoft Corporation. All rights reserved.

This compiler is provided as part of the Microsoft (R) .NET Framework, but only supports language versions up to C# 5, which is no longer the latest version. For compilers that support newer versions of the C# programming language, see http://go.microsoft.com/fwlink/?LinkID=533240

C:\Temp>a
0
bartdesmet commented 8 years ago

For context, we use a check against Members being non-null to determine whether a NewExpression node represents the instantiation of an anonymous type (as part of a pretty printer for expression trees as C# strings). For the corner case new { }, it now fails.

VSadov commented 7 years ago

Considering the impact of the scenario and the risk of potential regressions, moved to 2.1.

tuespetre commented 6 years ago

@bartdesmet

For context, we use a check against Members being non-null to determine whether a NewExpression node represents the instantiation of an anonymous type (as part of a pretty printer for expression trees as C# strings). For the corner case new { }, it now fails.

I wanted to chime in here to warn against this; a NewExpression with non-null Members cannot be guaranteed to represent the construction of an anonymous type. It is a shame that there was no AnonymousTypeAttribute or anything specified when anonymous types were introduced, but you can still more-or-less tell whether a given type is anonymous or not by checking certain features of the type itself.