Коллекция граблей

Наткнувшись сегодня в статье Александра Галкина «Немного об интерфейсах в .Net (по мотивам одного интервью)» на тот факт, что массив в .NET, оказывается, реализует многие члены интерфейса IList выбрасыванием NotSupportedException, я крайне удивился. Удивился, потому что привык, что .NET страхует программиста, не давая ему наступать на грабли, но в данном случае грабли лежат в основе основ фреймворка, в наисистемнейшем классе System.Array.  В чём же грабли, если эта недореализация недоступна в публичной области видимости? В возможности неявного приведения без каких-нибудь предупреждений.

Объявляет, к примеру, какой-нибудь программист интерфейс:

interface I
{
    void Test(IList collection);
}

Имеет, в общем-то, право.

Далее, какой-нибудь другой программист (ну, или тот же, неважно) реализует этот интерфейс:

class C : I
{
    public void Test(IList collection)
    {
        collection.Clear();
        // разные другие манипуляции
    }
}

И тоже имеет на это полное право.

Но потом приходит третий программист (ну, или тот же самый, но спустя пару месяцев), и пытается использовать этот интерфейс:

    C c = new C();
    c.Test(new[] { 1, 2, 3 });

И… получает NotSupportedException без объявления войны.
Особенно грустно становится, если вспомнить о том, что некоторые разработчики питают нездоровое пристрастие к неявной типизации (впрочем, про неё лучше отдельно как-нибудь), что чревато подобными участками кода:

    var integers = SomeFarObject.GetSomeCollectionOfIntegers(); // int[] GetSomeCollectionOfIntegers()…
    c.Test(integers);

Ой. А стукнет по лбу уже в рантайме — эксепшен вылетит прямо в лицо тестировщику (хорошо, если не клиенту). Неприятно.
Кто-нибудь в курсе, зачем System.Array реализует IList, с какой целью?

2 thoughts on “Коллекция граблей

  1. На мой взгляд, основной фичей массивов является индексация, которая присуща только IList (ICollection и IEnumerable этого не имеют).

    А для твоего случая у IList есть свойство IsFixedSize которое говорит о том, что коллекция неизменяема.

    Поэтому реализацию метода Test нужно исправить с учетом значения IsFixedSize (хотя я не знаю что делать в случае, когда нужно очистить неизменяемую коллекцию — бросать исключение, наверное)

    Нравится

  2. Тогда уж IsReadOnly )
    Но общая мысль понятна, IList ради индексатора. Правда, тогда непонятно, почему в 4.5 ситуация сохранилась несмотря на наличие IReadOnlyList — ради совместимости с 4.0, что ли? Будем надеяться, что в 5.0 это дело исправят, и станет как-то… логичнее?

    Нравится

Добавить комментарий

Заполните поля или щелкните по значку, чтобы оставить свой комментарий:

Логотип WordPress.com

Для комментария используется ваша учётная запись WordPress.com. Выход /  Изменить )

Google photo

Для комментария используется ваша учётная запись Google. Выход /  Изменить )

Фотография Twitter

Для комментария используется ваша учётная запись Twitter. Выход /  Изменить )

Фотография Facebook

Для комментария используется ваша учётная запись Facebook. Выход /  Изменить )

Connecting to %s