Приведение общей коллекции к конкретной реализации в C # 2.0 - PullRequest
1 голос
/ 10 ноября 2009

Выбранный раствор

Спасибо за помощь всем. Я решил сделать следующее.

public static class PersonCollection
{
    public static List<string> GetNames(RecordCollection<Person> list)
    {
        List<string> nameList = new List<string>(list.Count);

        foreach (Person p in list)
        {
            nameList.Add(p.Name);
        }

        return nameList;
    }
}



Я пытаюсь привести обобщенную коллекцию RecordCollection к производной коллекции PersonCollection, но получаю исключение приведения:

RecordCollection<Person> col = this.GetRecords<Person>(this.cbPeople);
PersonCollection people = (PersonCollection)col;

Причина, по которой я пытаюсь это сделать, двояка:

  1. Производные классы (например, PersonCollection) могут иметь методы экземпляра (например, GetLastNames), которых не должно быть в базовом классе.
  2. Метод GetRecords является общим, поэтому я могу получить коллекцию любых объектов Record.

Как лучше всего решить эту проблему в C # 2.0 ? Какой самый элегантный подход к решению этой проблемы?

Это подпись GetRecords:

public RecordCollection<T> GetRecords<T>(ComboBox cb) where T : Record, new()

Это моя базовая реализация:

public abstract class Record : IComparable
{
    public abstract int CompareTo(object other);
}

public class RecordCollection<T> : ICollection<T> where T : Record, new()
{
    private readonly List<T> list;

    public RecordCollection()
    {
        this.list = new List<T>();
    }

    // Remaining ICollection interface here
}

Я получил производные объекты на основе этой базовой реализации следующим образом:

public class Person : Record
{
    public Person()
    {
        // This is intentionally empty
    }

    public string Name
    {
        get;
        set;
    }

    public override int CompareTo(object other)
    {
        Person real = other as Person;
        return this.Name.CompareTo(real.Name);
    }
}

public class PersonCollection : RecordCollection<Person>
{

}

Ответы [ 3 ]

5 голосов
/ 10 ноября 2009

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

Вы не дали код метода GetRecords <>, но, вероятно, GetRecords возвращает RecordCollection, а не PersonCollection (где-то в коде есть новая RecordCollection, не так ли?)

Вы не можете привести RecordCollection к PersonCollection, если этот конкретный экземпляр на самом деле не является PersonCollection. Presicely, потому что у него нет этих дополнительных методов.

Это похоже на

SomeClass obj=new SomeClass();
DerivedClass o=(DerivedClass)obj; //throws exception
2 голосов
/ 10 ноября 2009

Лучше всего использовать какой-то заводской вызов внутри GetRecords, чтобы при запросе «коллекции» Person он возвращал PersonCollection как RecordCollection<Person>.

Наивная реализация может использовать несколько if, иначе вы можете связать конкретный тип коллекции с типами записей через Dictionary<Type,Type>.

1 голос
/ 10 ноября 2009

Один вариант:

Создание методов для статических методов без расширения для производных типов, которые принимают специализированную коллекцию RecordsCollection, т.е.

public static List<string>GetLastNames( RecordsCollection<Person> people ) 

так что вы можете использовать его в соответствии с

RecordCollection<Person> somePeople = GetRecords<Person>(cbPeople);
List<string> lastNames = PersonCollecion.GetLastNames( somePeople );

Это не так красиво, как методы расширения, но и не так уж плохо.
edit : удалена ошибочная информация, ранее опубликованная и заменена потенциальным решением

...