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

Problem with the Collection builder example #41756

Open
RexJaeschke opened this issue Jul 14, 2024 · 0 comments
Open

Problem with the Collection builder example #41756

RexJaeschke opened this issue Jul 14, 2024 · 0 comments
Labels
doc-enhancement Improve the current content [org][type][category] dotnet-csharp/svc lang-reference/subsvc Pri1 High priority, do before Pri2 and Pri3

Comments

@RexJaeschke
Copy link

Type of issue

Code doesn't work

Description

I'm writing the spec for the "collections expressions" feature for the Ecma C# standard, and used your tutorial to get up to speed on this topic. While playing with your Collection builder example I found a shortcoming. Regardless of how many elements are in the collection expression, the result returned is a collection of 80, based on the fixed size of the char array allocated. Specifically, for a collection expression with 3 elements, one would expect the type's Count or Length property to be 3, but on enumeration, one gets 80 elements. As such, the type is not well-behaved, so is not the best example in that regard. You write

Collection expressions work with any collection type that's well-behaved. A well-behaved collection has the following characteristics:

  • The value of Count or Length on a countable collection produces the same value as the number of elements when enumerated.
  • ...

Here is my test; it fixes this problem; it adds a Count property and an indexer, and it's generic.

using System;
using System.Collections;
using System.Collections.Generic;
using System.Runtime.CompilerServices;
using System.Xml.Linq;

MyCollection<char> coll1 = ['t', 'e', 'x', 't'];
DisplayCollection("coll1", coll1);
Console.WriteLine($"coll1[1] = >{coll1[1]}<");
coll1[2] = '?';
DisplayCollection("coll1", coll1);

MyCollection<ValueType> coll2 = [7, 6.5, 'x', 123L];
DisplayCollection("coll2", coll2);

MyCollection<object> coll3 = ["abc", 100, 10.5];
DisplayCollection("coll3", coll3);

MyCollection<object> coll4 = [];
DisplayCollection("coll4", coll4);

MyCollection<object> coll5 = [10, "xyz", ..coll2];
DisplayCollection("coll5", coll5);

static void DisplayCollection<T>(string collName, MyCollection<T> coll)
{
    Console.Write($"{collName}'s Count = {coll.Count}: ");
    foreach (var element in coll)
    {
        Console.Write($" {element}");
    }
    Console.WriteLine();
}

[CollectionBuilder(typeof(MyCollectionBuilder), "Create")]
public class MyCollection<T> : IEnumerable<T>
{
    private readonly T[] _storage;
    public int Count { get; }
    public T this[int index]
    {
        get
        {
            return _storage[index];
        }

        set
        {
            _storage[index] = value;
        }
    }
    public MyCollection(ReadOnlySpan<T> elements)
    {
        Count = elements.Length;
        _storage = new T[Count];
        for (int i = 0; i < Count; i++)
        {
            _storage[i] = elements[i];
        }
    }
    public IEnumerator<T> GetEnumerator() => _storage.AsEnumerable<T>().GetEnumerator();
    IEnumerator IEnumerable.GetEnumerator() => _storage.GetEnumerator();
}
internal static class MyCollectionBuilder
{
    internal static MyCollection<T> Create<T>(ReadOnlySpan<T> values) => new MyCollection<T>(values);
}

Page URL

https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/operators/collection-expressions

Content source URL

https://github.com/dotnet/docs/blob/main/docs/csharp/language-reference/operators/collection-expressions.md

Document Version Independent Id

49349466-94fd-00b5-93da-e4200d9f9ec8

Article author

@BillWagner

Metadata

  • ID: 63733f9f-0896-c948-1a7e-58fb428c11c0
  • Service: dotnet-csharp
  • Sub-service: lang-reference
@dotnet-bot dotnet-bot added the ⌚ Not Triaged Not triaged label Jul 14, 2024
@issues-automation issues-automation bot added dotnet-csharp/svc lang-reference/subsvc Pri1 High priority, do before Pri2 and Pri3 labels Jul 14, 2024
@BillWagner BillWagner added the doc-enhancement Improve the current content [org][type][category] label Jul 15, 2024
@dotnet-bot dotnet-bot removed the ⌚ Not Triaged Not triaged label Jul 15, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
doc-enhancement Improve the current content [org][type][category] dotnet-csharp/svc lang-reference/subsvc Pri1 High priority, do before Pri2 and Pri3
Projects
None yet
Development

No branches or pull requests

3 participants