Executando verificação de segurança...
4

Quando vi no começo você dizendo que o segundo exemplo era o bom, já me doeou, mas eu fui lendo a explicação, e te perdoei 😀.

Esse sim é um conteúdo... parabéns!

O pessoal não ta preocupado com isso, porque o essencial hoje é programar com strategy(acho importante), mas as vezes custa. E no fim o problema nunca é custo, e sim saber porque custa e saber se vale a pena.

Em "Aprendendo a substituir heap alloc..." no número 5, foi dito "capacity no construtor que vai reduzir a quantidade de alocações internamente".
Ai se você me permitir contribuir...

Pra quem não sabe (certeza que não é o teu caso), por debaixo dos panos a ICollection vai usar array comum, e toda vez que precisamo aumentar uma array não tem segredo, temos que criar uma nova com mais espaço e a antiga liberar da memória.

Nesse sentido se você tive 500 itens pra colocar na sua collection, e sua collection tiver um capacity de 50 itens, então quando chegar a 50 o .NET (ou qualquer outra), vai precisa alocar e liberar, fazendo isso pelo menos umas 10x (não sei a heurística para isso, só ex) até chegar em 500, agora se você já sabe que são 500 itens já inicializa alocando 500 "itens".

Normalmente utilizamos coisas dinâmicas então não temos como saber exatamente a quantidade de itens, então eu coloco algo próximo (tiro do 👌🏻 essa ideia)...
var capacity_qtde_kids = familys.Lenght * 2

óbvio que as vezes pode passar, como pode ser pouco também, mas é melhor do que não ter número nenhum.

Se tiverem afim de ver uma coisa muito é massa...

🐓 Rinha de compiladores (Vlang) - Me acompanha

Carregando publicação patrocinada...
2

Posso acrescentar um pouco mais à tua resposta! Mas minha contribuição vai ser exclusivamente acerca do C#.NET

Primeiro, nem toda classe que implementa a ICollection<T> utilizará um array. Mas o List<T>, que com certeza é a mais utilizada, usa um array em sua implementação.

Segundo, a eurística implementada em duas partes do código da List<T>. Os códigos que mostrarei aqui estão no repositório do .NET no GitHub, aqui o link pro arquivo de implementação da List<T> https://github.com/dotnet/runtime/blob/main/src/libraries/System.Private.CoreLib/src/System/Collections/Generic/List.cs.

A primeira parte está no método List<T>.Grow(), que é chamado sempre que a lista excede a capacidade anterior. É possível ver que a eurística é dobrar a capacidade até alcançar o patamar máximo que é Array.MaxLength.

/// <summary>
/// Increase the capacity of this list to at least the specified <paramref name="capacity"/>.
/// </summary>
/// <param name="capacity">The minimum capacity to ensure.</param>
internal void Grow(int capacity)
{
    Debug.Assert(_items.Length < capacity);

    int newCapacity = _items.Length == 0 ? DefaultCapacity : 2 * _items.Length;

    // Allow the list to grow to maximum possible capacity (~2G elements) before encountering overflow.
    // Note that this check works even when _items.Length overflowed thanks to the (uint) cast
    if ((uint)newCapacity > Array.MaxLength) newCapacity = Array.MaxLength;

    // If the computed capacity is still less than specified, set to the original argument.
    // Capacities exceeding Array.MaxLength will be surfaced as OutOfMemoryException by Array.Resize.
    if (newCapacity < capacity) newCapacity = capacity;

    Capacity = newCapacity;
}

A segunda parte está implementada na propriedade List<T>.Capacity que é modificada no método List<T>.Grow(), onde é implementada toda a lógica de criação do novo array e cópia dos elementos do antigo pro novo. Não é feita a liberação do antigo array porque isso é feito pelo GC.

// Gets and sets the capacity of this list.  The capacity is the size of
// the internal array used to hold items.  When set, the internal
// array of the list is reallocated to the given capacity.
//
public int Capacity
{
    get => _items.Length;
    set
    {
        if (value < _size)
        {
            ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.value, ExceptionResource.ArgumentOutOfRange_SmallCapacity);
        }

        if (value != _items.Length)
        {
            if (value > 0)
            {
                T[] newItems = new T[value];
                if (_size > 0)
                {
                    Array.Copy(_items, newItems, _size);
                }
                _items = newItems;
            }
            else
            {
                _items = s_emptyArray;
            }
        }
    }
}
1

Opa, iae comentário valioso!

Sim você está certo! Falha minha esquecendo que nem todos conhecem C#, Java, Js e etc...

Toda liberação é feita pelo GC, mas existem caso que é possível forçar prioridade de liberação para o GC.

Mas não é o caso do List, pois ele não implementa IDisposable.
Ai nesse caso, a nossa lista fica ao Deus dará... 😆