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

Collection Initializer cannot handle Extensions akin to IEnumerable<T>.Add(IEnumerable<T>) ( IDE0028 vs CS0029) #72460

Open
LukasGelke opened this issue Mar 8, 2024 · 1 comment
Labels
Area-Language Design untriaged Issues and PRs which have not yet been triaged by a lead

Comments

@LukasGelke
Copy link

Version Used:
Visual Studio: Version 17.9.2
dotnet: 6.0.419

Steps to Reproduce:

  1. have legacy Extension-Code like this
public class Class1
{
  public void Issue()
  {
    int[] numbers = [1, 2,3];
    Dictionary<string, int> dict = new() { numbers.Select(i => new KeyValuePair<string, int>(i.ToString(), i)) };
  }

  public void Issue2()
  {
    Dictionary<string, int> dict = new() { GetPairs() };
  }

  private static ICollection<KeyValuePair<string, int>> GetPairs() => throw new NotImplementedException();
}


public static class MyExtensions2
{
  public static void Add<T, TEnumElement>(this ICollection<T> collection,
    IEnumerable<TEnumElement>? elements)
    where TEnumElement : T
  {
    if (elements is null)
      return;
    ArgumentNullException.ThrowIfNull(collection);
    if (collection is List<T> list)
      list.AddRange((IEnumerable<T>)elements);
    else
      foreach (T element in elements)
        collection.Add(element);
  }
}
  1. invoke CodeFix
    image

  2. get compiler error
    image

A minimal repro, with source-code provided, is ideal. Using sharplab is preferred for compiler/language issues whenever possible.

Diagnostic Id:

  • IDE0028 Collection initialization can be simplified
  • CS0029 Cannot implicitly convert type 'System.Collections.Generic.ICollection<System.Collections.Generic.KeyValuePair<string, int>>' to 'System.Collections.Generic.KeyValuePair<string, int>' ClassLibrary2 D:\repos\WinFormsApp1\ClassLibrary2\Class1.cs

Expected Behavior:
something like

Dictionary<string, int> dict = [.. GetPairs()];

image

Actual Behavior:

  • IDE0028 is very eager to find "...Add(...)" Methods, however does not care if it produces valid code.
  • Collection Initalizer cannot handle Dictionaries/KeyValuePairs very well (see just above)

Notes:

we've experienced the same Problem with Lists/Collections (ie Generics with Arity=1), however I'm unable to get a working minimal example:
(in this case ExecuteSync() returns an ICollection<string?>, but we know it's exactly one element so capacity=2)
image

image

image

corrected (and working):
image

@dotnet-issue-labeler dotnet-issue-labeler bot added Area-Language Design untriaged Issues and PRs which have not yet been triaged by a lead labels Mar 8, 2024
@sharwell sharwell changed the title Collection Initializer cannot handle Extensions akin to IEnumarable<T>.Add(IEnumerable<T>) ( IDE0028 vs CS0029) Collection Initializer cannot handle Extensions akin to IEnumerable<T>.Add(IEnumerable<T>) ( IDE0028 vs CS0029) Mar 8, 2024
@sharwell
Copy link
Member

sharwell commented Mar 8, 2024

This is also covered in #71240. Collection expressions do not behave the same way as collection initializers (they are significantly restricted relative to them).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Area-Language Design untriaged Issues and PRs which have not yet been triaged by a lead
Projects
None yet
Development

No branches or pull requests

2 participants