This commit is contained in:
jnm2 2023-05-27 13:17:57 -04:00
Родитель 979330b632
Коммит d16fdec5b4
1 изменённых файлов: 5 добавлений и 5 удалений

Просмотреть файл

@ -16,21 +16,21 @@ People will be able to write better code by hand than the compiler can generate
When an exact count is known for a collection literal but the compiler can't prove that it is not potentially resized later, or when only a minimum count is known for a collection literal, the compiler could for example set the initial capacity to the best-fitting power of two. This would skip some early resizes while also amortizing resizes that could happen if the collection is modified after the collection literal is created.
### Unknown-length construction
### AddRange and boxing
When a struct-typed collection is spread, codegen could call `AddRange(IEnumerable<T>)` on the collection being constructed. This would cause the collection being spread to be boxed. To avoid boxing, codegen could loop over the spread collection and call `Add(T)` repeatedly on the collection being constructed.
This would work fine when the constructed collection has a writeable Capacity property because codegen could set the capacity before calling `Add(T)` in a loop. However, if there's no writeable Capacity property, we're better off calling `AddRange` and boxing, because the `AddRange` implementation is the only way to intelligently avoid intermediate resizes. (In this situation, the thing being spread has a known length but the collection literal as a whole has an unknown length due to an earlier spread.)
#### Conclusion (unknown-length construction)
#### Conclusion (AddRange and boxing)
Stick with building using Add and AddRange. This is good enough for 95% of customers. Allow the compiler to special-case codegen for widely-used collections to improve performance.
The compiler should prefer calling `AddRange(ReadOnlySpan<T>)` if such a method exists and the thing being spread is a span or exposes a span.
### Known-length construction
### Construction API pattern
The ideal API for constructing collections with contiguous backing storage is to pass the capacity and receive a span to the backing storage. To enable creation methods to be in the same class while having the same name, the collection could be passed back using an `out` parameter.
The ideal API for constructing collections with contiguous backing storage is to pass the capacity and receive a span to the backing storage. The collection could be passed back using an `out` parameter to enable overloading on collection type.
The type parameter to use when calling the creation method could be taken from the generic type argument of the collection's `IEnumerable<>` implementation. This strategy would not work for collections which implement `IEnumerable<>` more than once.
@ -70,7 +70,7 @@ public static class MyCollection
}
```
#### Conclusion (known-length construction)
#### Conclusion (construction API pattern)
Use an attribute to point to a creation method similar to the code samples above. If this attribute is present, prefer it over generating Add/AddRange calls.