Giter Site home page Giter Site logo

Comments (6)

CyrusNajmabadi avatar CyrusNajmabadi commented on June 19, 2024 1
  • Yup. This is just not a case we want to with currently. Will look into ways to make this work in the future. for now, stick with collection initializers here.

Sorry about the hassle!

from roslyn.

cston avatar cston commented on June 19, 2024

This looks to be a regression from 17.9.

In 17.9, for collection types implementing IEnumerable but not IEnumerable<T>, the compiler assumed the elements were convertible to the iteration type object when determining convertibility. In 17.10, the compiler checks that each element is implicitly convertible to object. For this example, that conversion fails because the type of the delegate cannot be inferred.

cc @jaredpar, @CyrusNajmabadi

from roslyn.

CyrusNajmabadi avatar CyrusNajmabadi commented on June 19, 2024

What rule changed that caused this? I thought we were effectively rolling back to the 17.9 rules (just looking for the presence of an Add method now).

from roslyn.

cston avatar cston commented on June 19, 2024

The Add requirement was relaxed in 17.10p4 but the check that each element is implicitly convertible to the iteration type was retained. In 17.9, that check was skipped if the target type implemented IEnumerable but not IEnumerable<T>.

That additional check in 17.10 that the element is implicitly convertible to object (for the IEnumerable case) can fail when the element is target typed, and relies on a strongly-typed Add method parameter type.

from roslyn.

cston avatar cston commented on June 19, 2024

@ufcpp, thanks for reporting this issue.

The break was the result of an intentional design change for collection expressions targeting types that implement IEnumerable (and that do not have a strongly-typed enumerator) to require that all elements are implicitly convertible to the iteration type object (see LDM-2024-01-08). That change provided consistency with other target types where we already required collection expression elements to be implicitly convertible to the iteration type of the target.

We had not recognized your breaking change case previously. I’ve added an item based on your example to the breaking change documentation for 17.10 (see #73278).

Did you hit this issue with an existing collection type? We're curious how common this case might be. Thanks.

from roslyn.

ufcpp avatar ufcpp commented on June 19, 2024

Yes, this change broke my team's code.

Extracting the main points, we had the following classes. It used collection initialisers for event handler registration.

using System.Collections;

Reciever reciever = new()
{
    (sender, args) =>
    {

    },
    (sender, args, args2) =>
    {

    }
};

class Reciever : IEnumerable
{
    public void Recieve()
    {
        RecievedEventArgs args = new();
        _onRecieved1?.Invoke(this, args);

        if (_onRecieved2 is { } r)
        {
            RecievedEventArgs2 args2 = new(); // high computational cost
            _onRecieved2?.Invoke(this, args, args2);
        }
    }

    private Action<Reciever, RecievedEventArgs>? _onRecieved1;
    private Action<Reciever, RecievedEventArgs, RecievedEventArgs2>? _onRecieved2;

    public void Add(Action<Reciever, RecievedEventArgs> onRecieved) => _onRecieved1 += onRecieved;

    public void Add(Action<Reciever, RecievedEventArgs, RecievedEventArgs2> onRecieved) => _onRecieved2 += onRecieved;

    IEnumerator IEnumerable.GetEnumerator() => throw new NotImplementedException("dummy for collection initializers");
}

// normal args
struct RecievedEventArgs;

// args with high computational cost
struct RecievedEventArgs2;

VS 17.9 suggested IDE0028 (and 17.10 still makes this suggestion). With this applied, we had the code like the following.

Reciever reciever =
[
    (sender, args) =>
    {

    },
    (sender, args, args2) =>
    {

    }
];

Since there are two overloads of Add, Implementing IEnumerable<T> does not solve the problem. The collection builder is also helpless.

from roslyn.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.