Почему C# List<T>.AsReadOnly() выделяет?

Почему C# List<T>.AsReadOnly() выделяет?
Почему C# List<T>.AsReadOnly() выделяет? - jcotten @ Unsplash

Если бы не было выделения, не было бы причин для функции AsReadOnly()

Если все, что вы хотите сделать, это привести его к IReadOnlyList, то сделайте это:
var myList = new List<string>();
var myListReadOnly = (IReadOnlyList<string>) myList;

Приведение вместо того, чтобы полагаться на функцию с потенциальными побочными эффектами (например, создание выделения), более явно показывает, что вы делаете.

Если уж на то пошло, я бы сказал, что название функции AsReadOnly() немного вводит в заблуждение, так как в ней нет явного упоминания об использовании ReadOnlyCollection.

Если говорить о мотивации этого, то я считаю, что вы правы. Преимущества возврата коллекции ReadOnlyCollection включают:

  • Предотвращение того, чтобы получатели коллекции приводили ее к изменяемому списку
  • Методы, полученные через отражение, не будут работать с коллекцией
  • Предотвращает ошибочное сопоставление шаблонов в .GetType()

Концепция ReadOnly заключается в том, чтобы защитить программиста от ошибки при манипулировании данными. В большинстве приложений производительность такого небольшого распределения является тривиальной и стоит того, чтобы не только сообщать, что эти данные доступны для чтения, но и более активно обеспечивать это.

По мере усложнения приложений множество различных путей кода может привести к странным и неожиданным сценариям использования. Возьмем такой пример:

static void GatherAnimals()
{
    var myAnimals = new List<IAnimal> { new Cat(), new Dog() };
    var animalCollector = new MyAnimalCollector();
    animalCollector.Collect(myAnimals);
}

class MyAnimalCollector : BaseAnimalCollector
{
    // Called by the BaseAnimalCollector.Collect() method
    override void AddAnimals(object animals)
    {
        if (animals is IList<IAnimal> list)
        {
            list.Add(new Rabbit());
        }
    }
}

Допустим, вы как разработчик не можете контролировать реализацию BaseAnimalCollector, поэтому вы не можете изменить параметр "животные" на другой тип. Теперь, где-то в другом месте вашего кода, у вас есть немного другой вызов:

static void GatherAllCats()
{
    var myAnimals = new List<IAnimal> { new Cat(), new Tiger() }.AsReadOnly();
    var animalCollector = new MyAnimalCollector();
    animalCollector.Collect(myAnimals);
}

Теперь вызов "is" вернет false, и список не будет отредактирован.

Я бы никогда не рекомендовал кодировать так, как показано в примере выше, но это показывает, как подобные ошибки могут закрасться.

Допустим, критически важно, чтобы кролик не был добавлен в коллекцию Cat: .AsReadOnly(), возвращающая ReadOnlyCollection, защищает от этого. Если бы она просто выполнила приведение, этого бы не произошло.

Рекомендую посмотреть эти видео для лучшего погружения в вопрос:

Прикрепленное видео 1 - Основы C -, Девятый урок. Коллекции: Список (List)

Прикрепленное видео 2 - Fix Not available in this source, NuGet Visual Studio Error Guide


LetsCodeIt, 1 марта 2023 г., 02:34