Description
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
Document Version Independent Id
49349466-94fd-00b5-93da-e4200d9f9ec8
Article author
Metadata
- ID: 63733f9f-0896-c948-1a7e-58fb428c11c0
- Service: dotnet-csharp
- Sub-service: lang-reference