Общие коллекции C #

Я перехожу к C # из опыта Java и постоянно сталкиваюсь с той же проблемой с дженериками, которую было бы тривиально решить на Java.

Учитывая классы:

interface IUntypedField { }
class Field<TValue> : IUntypedField { }

interface IFieldMap
{
    void Put<TValue>(Field<TValue> field, TValue value);
    TValue Get<TValue>(Field<TValue> field);
}

I ' Я бы хотел написать что-то вроде:

class MapCopier
{
    void Copy(IEnumerable<IUntypedField> fields, IFieldMap from, IFieldMap to)
    {
        foreach (var field in fields)
            Copy(field, from, to); // <-- clearly doesn't compile as field is IUntypedField not Field 
    }

    void Copy<TValue>(Field<TValue> field, IFieldMap from, IFieldMap to)
    {
        to.Put(field, from.Get(field));
    }
}

В Java это было бы просто решить, поскольку коллекция полей была бы Iterable > , и вы могли бы вызвать Copy (Field, IFieldMap, IFieldMap) напрямую.

В C # я обнаружил, что выполняю переключение / приведение для всех возможных значений TValue (что ужасно пахнет, необходимость добавлять регистр для каждого добавляемого вами типа явно является ошибкой ожидает, когда произойдет, и выполнимо только в том случае, если набор типов конечен):

foreach (var field in fields)
{
    switch (field.Type) // added an enum to track the type of Field's parameterised type
    {
    case Type.Int:   Copy((Field<int>)field, from, to); break;
    case Type.Long:  Copy((Field<long>)field, from, to); break; 
    ...
    }
}

Другой вариант, который я иногда делаю, - это переместить функциональность в класс Field, что опять же неприятно. Это не ответственность поля. По крайней мере, это позволяет избежать огромного переключения:

interface IUntypedField { void Copy(IFieldMap from, IFieldMap to); }
class Field<TValue> : IUntypedField 
{ 
    void Copy(IFieldMap from, IFieldMap to)
    {
        to.Put(this, from.Get(this));
    }
}

...

    foreach (var field in fields)
        field.Copy(from, to);

Если бы вы могли написать методы полиморфного расширения (т.е. методы копирования в IUntypedField и Field выше), то вы могли бы, по крайней мере, сохранить код вместе с классом, за который он несет ответственность.

Am Мне не хватает какой-то функции C #, которая сделала бы это возможным. Или есть какой-то функциональный шаблон, который можно было бы использовать? Есть идеи?

(И последнее, я сейчас застрял на .Net 3.5, поэтому не могу использовать какие-либо ковариации / контравариантности, но мне все равно было бы интересно узнать, как они могут здесь помочь, если вообще) .

7
задан SimonC 3 January 2011 в 03:55
поделиться