Collection expressions are suggested for types where it doesn't make sense, and their error messages show inconsistent types
- Dominant language
- C#
- Stars
- 20.7k
- Forks
- 4.3k
- PR merge metrics
- PR metrics pending
Description
**Version Used**:
- First noticed in VS 17.9.6 with SDK 8.0.204
- Last tested in VS 18.6.1 with SDK 10.0.300 (Compiler version: '5.6.0-2.26230.15 (a0ccfc09f8af4a6d4756397fa89c65efd95f70a6)'. Language version: 14.0)
**Steps to Reproduce**:
See comments in the sample:
```cs
using System;
using System.Collections;
using System.Collections.Generic;
namespace ConsoleApp1;
internal class Program
{
private readonly InlineValidator _validator;
public Program()
{
// This shows "IDE0028 Collection initialization can be simplified", but only if the Add method below exists.
// Should it really show this message? I think using a collection expression here is very weird.
_validator = new InlineValidator();
// Applying the code fix results in the following working, but weird, code.
// This still compiles if the Add method below does not exist.
_validator = [];
// This calls the Add method below, but should it?
// The type of the parameter is something completely different than the type of the IEnumerable element.
// If the Add method below does not exist, then this shows error "CS1061 'InlineValidator' does not
// contain a definition for 'Add' and no accessible extension method 'Add' accepting a first argument of type
// 'InlineValidator' could be found".
// This makes even less sense. Why does it try to find an Add method with parameter type
// InlineValidator? Shouldn't it only be parameter type DateTime or IValidationRule (depending on
// whether it should be the generic type of the class itself, or the IEnumerable type)?
_validator = [null!];
// This shows error "CS0029 Cannot implicitly convert type 'int' to 'ConsoleApp1.IValidationRule'.
// This is different from the line above (when the Add method exists). There the compiler passed null as the
// Add method parameter type (Func). But now it tries to convert it to the IEnumerable element type? Why?
//_validator = [1];
}
}
public class InlineValidator : IEnumerable
{
public void Add(Func someFunc)
{
someFunc(1);
}
public IEnumerator GetEnumerator()
{
throw new NotImplementedException();
}
IEnumerator IEnumerable.GetEnumerator()
{
throw new NotImplementedException();
}
}
public interface IValidationRule;
```
[Sample in SharpLab](https://sharplab.io/#v2:D4AQTAjAsAUCAMACEEB0BhA9gG2wUwGMAXAS0wDsBnAblgWQgBZaZZyBDAWz0oAd2CeRFio48AQV68ILWCXJE8AJw7ZkYBgHZYAb1iIDiXkpIA3dosRK87ACYVsAT0QBJctnl4Aauw+2LmEoAPAAiFngAKiTcAHyIAPrmfgFKsjCGyADMWgAUAJT6hnrpGYYA9GWIEQAWJJSIlNWYAO71AEQuIQCi8PBgABzCOPjEZOSI8iSkviQAXhZjiATs4wBGQpTRvB4AZiR4tm0ANIirAK5EiA7OJDuIRNVC4ra2iNwPmK/r2C2IeAAedSIlFQhVKiAqiAAyk0zthXlMrDZcM5Gr8HnU3jxKOwAOZ4AD8rnutXIAGtkEh2EthoRSBQ/v9jNjFo9rBN6qZlM5mngSEpbKCSuDEjN/ERAogALyIch4ZqudyeHzJCXBMKKKKxfJpcEGSGSbaOeS4klCAifIR7f5Iyhw4ETcYPK3DFomxDNQJkk0nc6XXn82wnC22PBCvUQyo1TGUUi4GmcXgkfD1W5mxDPV7vJpfPA/BX2HiyzCXAFA8N60WqyUygDaAF1dXrIdH6stcPVnRmXliPrn876Lg1YfCJkQCWDSi3HvdHLwhJg7l3+EouHhFEoOQ1MNn3RbE/hFE5ELZbjtlHgFCSVumiHOF0uZyhsnm8NwFBXwZCXI+nj3s58px5r8hb1OQJaMkCJzOk6tT1GirR/EoSiSm06BQhA8AAGwQIgADkbgeHKKokOKgShOEWp4DEeEnpgRbgUQk4ZJCFoKOw8iINSoZ7OQUyLDskp4ZmtErK84FcQQgiUJsqz4IyihUIsAGvMJLyiVJeC8KQ5CmtSexKLGXFKLiZzvpci6zvOzHlJUBFKsRYopBRmrRNRtEWnCuaIIJZzkIcn5TlGcFvOwZJFngXLjCm8GXpQYaIAA6tUzigWO9xKM4Eo+fIrw3pmvY5h6UzVEY7Cru8yhWXgNn6pUhHKk5aouZEbkxESMKYF55B4ZciLXEBZUVeuVV3vOiAaq13BXJuLgkeKYwAEpwkIOShvO/nuhQtWRh6jzOpuiJol5g1dvicomAQ1VXL+6hjvF2A7Cckpds+1V5BOwqlFWpEpNKiC1uQcLYAAhI2sA7dOMZNIhygoZuaFQr0YAAJzCCsjETAeJAEFMx5sVySiXGNQh4fIRC0dleEiJQYiGmgc1NUtK14YFLHBZimKnjs57WFeOwoZw6ZEUI7CrJgXKIDkzSPLBf5ZuuRVlrGlB5KgVRskIXb7km+CbvwMkHLKwNcZ2jyQ5UBUqUNa4btdOQgAArGriAAEJDuBCqIkQJhFtlBPKH1xOYOmb2vuZ1VEsljifRGFQ/WRm51hA4NfQAvrAGesHA2TgIqIvzc5ERxAAXAwmRBIzqrM/gMS6JOIC54w3a2A7jtBOTvqYDgcS09wTsFF9xQRn3eBOzkEB5CwGRZw32QuF0QPcKuzVV799LkMtteIAA4uui9mcoKT5JOw96g8KEKnKCoAHIli4B5vpeii2F0/yCNpYw6pOWcZAvS9HzVOXVAe8iAH2XsfQeGQz7ggvr8a+iA75EAftsJ+CgDhvw/hvb+6dM4Qxzo6DcOwBBCDXgtCgW88AsCAA===)
My actual project uses https://github.com/FluentValidation/FluentValidation. The sample contains simplified versions of the FluentValidation classes.
**Diagnostic Id**:
Initially `"IDE0028: Collection initialization can be simplified"`.
But the following error messages are shown if you modify the sample as explained in the comments:
- `"CS1061: 'InlineValidator' does not contain a definition for 'Add' and no accessible extension method 'Add' accepting a first argument of type 'InlineValidator' could be found"`
- `"CS0029: Cannot implicitly convert type 'int' to 'ConsoleApp1.IValidationRule"`
**Expected Behavior**:
I don't expect to see `"IDE0028: Collection initialization can be simplified"` for `new InlineValidator()`. I think this should only be shown if the parameter type of the `Add` method matches the collection type.
I expect consistant parameter/element types shown in the error messages if you modify the sample as explained in the comments.
**Actual Behavior**:
See comments in the sample code.
Contributor guide
Research direction
Start by reproducing the C# sample in the issue, using SharpLab or the reported IDE0028 scenario, and compare the diagnostics for the empty and non-empty collection expressions. Investigate the collection-expression suggestion and the CS1061/CS0029 type reporting; done means the suggestion is suppressed when inappropriate and the resulting diagnostics consistently report the relevant parameter or element type.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- csharp
- Domain
- compilers
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 35/100