Почему не там никакой интерфейс IArray(T) в.NET?

Обновите 2011 06 января:

Хотите верьте, хотите нет, я шел вперед и включил этот интерфейс в библиотеку с открытым исходным кодом, которую я запустил, Tao.NET. Я записал сообщение в блоге, объяснив эту библиотеку IArray интерфейс, который не только решает проблемы я первоначально, повысил в этом вопросе (год назад?!), но также и обеспечивает ковариантный индексируемый интерфейс, что-то, в чем это очень испытывает недостаток (по-моему), в BCL.


Вопрос (короче говоря):

Я спросил, почему.NET имеет IList, который реализует ICollection и поэтому предоставляет методы для изменения списка (Add, Remove, и т.д.), но не предлагает промежуточного интерфейса такой как IArray обеспечить произвольный доступ индексом без любой модификации списка.


РЕДАКТИРОВАНИЕ 2010 21 января 14:22 EST:

В комментарии к исходному ответу Jon Skeet (в котором он подверг сомнению, как часто можно было бы иметь любую потребность в контракте таким как IArray), я упомянул что Keys и Values свойства SortedList класс IList и IList, соответственно, на который ответил Jon:

Но в этом случае это, как объявляют, IList, и Вы знаете, чтобы просто использовать индексаторы.... Это не чрезвычайно изящно, я соглашаюсь - но это на самом деле не причиняет мне боли.

Это разумно, но я ответил бы путем высказывания, что это не причиняет Вам боли, потому что Вы просто знаете, что не можете сделать этого. Но причина, которую Вы знаете, не состоит в том, что это ясно из кода; это - это, у Вас есть опыт с SortedList класс.

Visual Studio не собирается давать мне любые предупреждения, если я делаю это:

SortedList mySortedList = new SortedList();

// ...

IList keys = mySortedList.Keys;
keys.Add("newkey");

Это законно, согласно IList. Но все мы знаем, это собирается вызвать исключение.

Guillaume высказал способное мнение также:

Ну, интерфейсы не прекрасны, но dev может проверить свойство IsReadOnly, прежде чем вызов Добавит/Удалит/Установит...

Снова, это разумно, НО: разве это не кажется тебе немного окольный?

Предположим, что я определил интерфейс следующим образом:

public interface ICanWalkAndRun {
    bool IsCapableOfRunning { get; }

    void Walk();
    void Run();
}

Теперь, предположите также, что я сделал это обычной практикой для реализации этого интерфейса, но только для Walk метод; во многих случаях я решил бы установить IsCapableOfRunning кому: false и бросок a NotSupportedException на Run...

Затем у меня мог бы быть некоторый код, который был похож на это:

var walkerRunners = new Dictionary();

// ...

ICanWalkAndRun walkerRunner = walkerRunners["somekey"];

if (walkerRunner.IsCapableOfRunning) {
    walkerRunner.Run();
} else {
    walkerRunner.Walk();
}

Действительно ли я являюсь сумасшедшим, или действительно ли это - вид нанесения поражения цели названного интерфейса ICanWalkAndRun?


Исходное сообщение

Я нахожу это очень странным, что в.NET, когда я разрабатываю класс со свойством набора, которое обеспечивает произвольный доступ индексом (или метод, который возвращает индексируемый набор, и т.д.), но не должен или не может быть изменен путем добавления/удаления объектов, и если я хочу "сделать правильную вещь", мудрую ООП и обеспечить интерфейс так, чтобы я мог изменить внутреннюю реализацию, не повреждая API, я должен пойти с IList.

Стандартный подход, кажется, должен пойти с некоторой реализацией IList это явно определяет методы Add, Insert, и т.д. - обычно путем выполнения чего-то как:

private List _items;
public IList Items {
    get { return _items.AsReadOnly(); }
}

Но я вид ненависти это. Если другой разработчик использует мой класс, и мой класс имеет свойство типа IList, и вся эта мысль об интерфейсе: "это некоторые доступные свойства и методы", почему я должен бросить a NotSupportedException (или независимо от того, что случай может быть), когда он пытается сделать что-то, что, согласно интерфейсу, должно быть абсолютно законно?

Я испытываю желание реализовывать интерфейс и явно определять некоторых его участников, похож на открытие ресторана и помещение некоторых объектов в меню - возможно, в некоторой неясной, легкой мисс части меню, но в меню, тем не менее - которые никогда не просто доступны.

Кажется, что должно быть что-то как IArray интерфейс, который обеспечивает очень простой произвольный доступ индексом, но никакое добавление/удаление, как следующее:

public interface IArray {
    int Length { get; }
    T this[int index] { get; }
}

И затем IList мог реализовать ICollection и IArray и добавьте IndexOf, Insert и RemoveAt методы.

Конечно, я мог всегда просто писать этот интерфейс и использовать его сам, но это не помогает со всеми существующими ранее классами.NET, которые не реализуют его. (И да, я знаю, что мог записать обертку, которая берет любого IList и выкладывает IArray, но... серьезно?)

Делает у любого есть любое понимание почему интерфейсы в System.Collections.Generic были разработаны этот путь? Я пропускаю что-то? Есть ли убедительный аргумент против того, чего я говорю о своих проблемах с подходом явного определения членов IList?

Я не пытаюсь звучать дерзким, как будто я знаю лучше, чем люди, которые разработали классы.NET и интерфейсы; это просто не имеет смысла мне. Но я готов подтвердить, что существует много, я, вероятно, не учел.

15
задан Dan Tao 6 January 2011 в 21:43
поделиться

3 ответа

живые () вызовы с такими событиями, как изменение, для меня очень важны. Я хотел этого как-то сейчас.

-121--1002646-

Вы можете обойти это, используя Detours , обернув LoadLibrary . Оболочка LoadLibrary сможет распознавать попытки загрузки библиотеки DLL и соответствующим образом переписывать путь.

-121--2270259-

Вопросы дизайна не всегда черно-белые.

Одна сторона - это точные интерфейсы для каждой ситуации, что делает весь процесс фактического внедрения интерфейсов реальной болью.

Другой - это несколько (er) многоцелевых интерфейсов, которые не всегда полностью поддерживаются реализатором, но облегчают многие вещи, такие как передача экземпляров, которые похожи, но не получают те же интерфейсы, назначенные в конструкции «точного интерфейса».

Поэтому BCL дизайнеров выбрал второй путь. Иногда я также желаю, чтобы интерфейсы были немного менее многоцелевыми, особенно для коллекций и с функциями co-/contravariance интерфейса C # 4 (которые не могут быть применены к большинству интерфейсов коллекции escept для IEnumerable < >, потому что они содержат как co-, так и contravariant части).

Также обидно, что базовые классы, такие как последовательности и примитивные типы, не поддерживают некоторые интерфейсы, такие как ICharStream (для последовательностей, которые можно использовать для regex и т.д., чтобы разрешить использование других источников, кроме последовательностей экземпляров для сопоставления образца) или IArithmetic для числовых примитивов, чтобы была возможна общая математика. Но я думаю, что все рамки имеют некоторые слабые точки.

5
ответ дан 1 December 2019 в 05:12
поделиться
-

Самое близкое, которое вы можете получить, это вернуться IENumerable , а затем клиент (A.k.a. Caller) может звонить.

0
ответ дан 1 December 2019 в 05:12
поделиться

Ну, интерфейсы не идеальны, но разработчик может проверить свойство ISREADONLY перед вызовом Add / Remove / Set ...

2
ответ дан 1 December 2019 в 05:12
поделиться
Другие вопросы по тегам:

Похожие вопросы: