Repository: dotnet/runtime
File: src/libraries/Microsoft.Extensions.Logging.Abstractions/gen/LoggerMessageGenerator.Parser.cs (C#)

Code before:
                            foreach (LoggerMethod lm in lc.Methods)
                            {
                                if (methods.TryGetValue(lm.Name, out int currentCount))
                                {
                                    lm.UniqueName = $"{lm.Name}{currentCount}";
                                    methods[lm.Name] = currentCount + 1;
                                }
                                else
                                {
                                    lm.UniqueName = lm.Name;
                                    methods[lm.Name] = 1; //start from 1
                                }
                            }
                            results.Add(lc);
                        }
                    }
                }

                if (results.Count > 0 && _compilation is CSharpCompilation { LanguageVersion : LanguageVersion version and < LanguageVersion.CSharp8 })
                {
                    // we only support C# 8.0 and above
                    Diag(DiagnosticDescriptors.LoggingUnsupportedLanguageVersion, null, version.ToDisplayString(), LanguageVersion.CSharp8.ToDisplayString());
                    return Array.Empty<LoggerClass>();
                }

                return results.OrderBy(x => x.Namespace, StringComparer.Ordinal).ThenBy(x => x.Name, StringComparer.Ordinal).ToList();
            }

            private static string GenerateClassName(TypeDeclarationSyntax typeDeclaration)
            {
                if (typeDeclaration.TypeParameterList != null &&
                    typeDeclaration.TypeParameterList.Parameters.Count != 0)
                {
                    // The source generator produces a partial class that the compiler merges with the original
                    // class definition in the user code. If the user applies attributes to the generic types
                    // of the class, it is necessary to remove these attribute annotations from the generated
                    // code. Failure to do so may result in a compilation error (CS0579: Duplicate attribute).
                    for (int i = 0; i < typeDeclaration.TypeParameterList.Parameters.Count; i++)
                    {
                        TypeParameterSyntax parameter = typeDeclaration.TypeParameterList.Parameters[i];

                        if (parameter.AttributeLists.Count > 0)
                        {
                            typeDeclaration = typeDeclaration.ReplaceNode(parameter, parameter.WithAttributeLists([]));
                        }
                    }
                }

                return typeDeclaration.Identifier.ToString() + typeDeclaration.TypeParameterList;
            }


Review comment (performance):
nit: this is ok, if you want to optimize more to avoid the allocation, may use 

```C#

results.Sort((a, b) =>
{
    int c = StringComparer.Ordinal.Compare(a.Namespace, b.Namespace);
    return c != 0 ? c : StringComparer.Ordinal.Compare(a.Name, b.Name);
});

```

Code after:
                            foreach (LoggerMethod lm in lc.Methods)
                            {
                                if (methods.TryGetValue(lm.Name, out int currentCount))
                                {
                                    lm.UniqueName = $"{lm.Name}{currentCount}";
                                    methods[lm.Name] = currentCount + 1;
                                }
                                else
                                {
                                    lm.UniqueName = lm.Name;
                                    methods[lm.Name] = 1; //start from 1
                                }
                            }
                            results.Add(lc);
                        }
                    }
                }

                if (results.Count > 0 && _compilation is CSharpCompilation { LanguageVersion : LanguageVersion version and < LanguageVersion.CSharp8 })
                {
                    // we only support C# 8.0 and above
                    Diag(DiagnosticDescriptors.LoggingUnsupportedLanguageVersion, null, version.ToDisplayString(), LanguageVersion.CSharp8.ToDisplayString());
                    return Array.Empty<LoggerClass>();
                }

                results.Sort((lhs, rhs) =>
                {
                    int c = StringComparer.Ordinal.Compare(lhs.Namespace, rhs.Namespace);
                    return c != 0 ? c : StringComparer.Ordinal.Compare(lhs.Name, rhs.Name);
                });
                return results;
            }

            private static string GenerateClassName(TypeDeclarationSyntax typeDeclaration)
            {
                if (typeDeclaration.TypeParameterList != null &&
                    typeDeclaration.TypeParameterList.Parameters.Count != 0)
                {
                    // The source generator produces a partial class that the compiler merges with the original
                    // class definition in the user code. If the user applies attributes to the generic types
                    // of the class, it is necessary to remove these attribute annotations from the generated
                    // code. Failure to do so may result in a compilation error (CS0579: Duplicate attribute).
                    for (int i = 0; i < typeDeclaration.TypeParameterList.Parameters.Count; i++)
                    {
                        TypeParameterSyntax parameter = typeDeclaration.TypeParameterList.Parameters[i];

                        if (parameter.AttributeLists.Count > 0)
                        {
                            typeDeclaration = typeDeclaration.ReplaceNode(parameter, parameter.WithAttributeLists([]));
                        }
                    }