Что большая часть inuitive пути состоит в том, чтобы попросить объектов в парах?

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

Мой вопрос - то, что лучший способ состоит в том, чтобы позволить пользователю моего класса давать мне ту информацию?

Это должно попросить набор пар как это?

MyClass(IEnumerable<KeyValuePair<Object, Object>> objects)

Или отдельные наборы как это?

MyClass(IEnumberable<Object> x, IEnumerable<Object> y)

Или есть ли другая опция?

Мне нравится первое, потому что отношения являются явными, мне не нравятся они из-за дополнительной работы, они ставят клиент.

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

Мнения?

6
задан Neil Anderson 12 July 2010 в 19:27
поделиться

12 ответов

В .NET 4 вы должны быть используя Tuple . Дополнительная информация о классе Tuple в MSDN.

10
ответ дан 8 December 2019 в 05:19
поделиться

Если у вас есть доступ к нему, используйте Tuple. Если нет, просто напишите собственный класс Tuple или Pair. Я бы избегал использовать KeyValuePair, просто потому что он многословен и имеет ассоциацию с Dictionary.

5
ответ дан 8 December 2019 в 05:19
поделиться

Я предпочитаю первый метод, так как со вторым одна последовательность может быть длиннее другой - он не поддерживает требуемое отображение 1: 1.

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

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

Одно: если вы используете .NET 4.0, я бы рекомендовал использовать Tuple вместо KeyValuePair.

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

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

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

Я думаю, вы должны выбрать вариант 1. Должны быть явные взаимосвязи, иначе вы просто напрашиваетесь на проблемы.

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

Я обычно предоставляю и то, и другое, с конструктором KeyValuePair, делегирующим конструктор с двумя аргументами. Лучшее из обоих миров.

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

Мне нравится первый метод по двум причинам.

  1. Если они уже хранят свои отношения в объекте Dictionary <>, они могут просто передать словарь как есть - дополнительный код не требуется.

  2. Если они используют свое собственное хранилище, то предоставить вам KeyValuePairs в IEnumerable очень просто с помощью оператора yield

Примерно так:

IEnumerable<KeyValuePair<Object,Object>> GetMappedPairs()
{
    foreach( var pair in _myCustomData )
    {
        yield return new KeyValuePair{Key = pair.ID, Value = pair.Data};
    }
}

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

Кстати, вам, вероятно, лучше всего будет объявить ваш метод универсальным вместо жесткого кодирования KeyValuePair

MyClass<TKey,TValue>( IEnumerable<KeyValuePair<TKey,TValue>> pairs );
0
ответ дан 8 December 2019 в 05:19
поделиться

Возможно, стоит подумать, зачем вы вообще раскрываете перечислимое. Вы можете использовать метод Add(Object a, Object b), который полностью скрывает ваш внутренний способ работы с парами. Затем клиент мог бы установить свои собственные средства добавления к нему отношений в виде множеств или по отдельности.

Конечно, если вам все еще нужен метод, принимающий перечислимое, то первый вариант, вероятно, лучше: явное отношение. Но вы можете использовать или создать тип Tuple или Pair для использования вместо KeyValuePair, предполагая, что отношения между ними не являются отношениями типа "ключ-значение".

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

А что если сделать что-то вроде этого?

// The client can choose to put together an IEnumerable<...> by hand...    
public MyClass(IEnumerable<KeyValuePair<object, object>> pairs)
{
    // actual code that does something with the data pairs
}

// OR the client can pass whatever the heck he/she wants, as long as
// some method for selecting the Xs and Ys from the enumerable data is provided.
// (Sorry about the code mangling, by the way -- just avoiding overflow.)
public static MyClass Create<T>
(IEnumerable<T> source, Func<T, object> xSelector, Func<T, object> ySelector)
{
    var pairs = source
        .Select(
            val => new KeyValuePair<object, object>(
                xSelector(val),
                ySelector(val)
            )
        );

    return new MyClass(pairs);
}

Это позволит клиентам писать код вроде этого:

// totally hypothetical example
var stockReturns = StockReturns.Create(prices, p => p.Close, p => p.PrevClose);
0
ответ дан 8 December 2019 в 05:19
поделиться

Я бы предпочел KeyValuePair из двух, которые вы упомянули, поскольку он более выразителен и сохраняет взаимосвязь между объектами.

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

(Псевдокод)

class MyPair
{
    public TypeA One;
    public TypeB Two;
}

MyClass(IEnumerable<MyPair> objects)

В некоторых ответах упоминается Tuple <,> , который читается так же, как KeyValuePair, но более гибкий, поскольку может содержать более двух параметров.

[Edit - дополнительная информация о кортежах / классах после хорошего ночного сна]

В кортеж или не в кортеж

5
ответ дан 8 December 2019 в 05:19
поделиться

Я бы использовал вторую версию (потому что она проще) + комментарии + статические / динамические проверки. Если вы можете использовать контракты кода, постарайтесь убедиться, что коллекции имеют одинаковую длину, а не null. Если нет, то сделайте то же самое с Debug.Assert , а также с if ... throw ArgumentException . В качестве альтернативы вы можете создать свой собственный объект, содержащий пару, но тогда становится сложнее использовать универсальные шаблоны для членов пары. Кроме того, когда вы создаете объект, предназначенный для хранения в контейнере, вы должны правильно реализовать GetHashCode , Equals и т. Д. В первой книге «Эффективный C #» есть элемент на этом.

Как правило, я предпочитаю не перерабатывать сигнатуры методов.

0
ответ дан 8 December 2019 в 05:19
поделиться
Другие вопросы по тегам:

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