开发者

Casting generic collection to concrete implementation in C# 2.0

开发者 https://www.devze.com 2022-12-10 21:06 出处:网络
Chosen Solution Thanks for the help everyone.I\'ve decided to do the following. public static class PersonCollection

Chosen Solution

Thanks for the help everyone. I've decided to do the following.

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;
    }
}


I'm trying to cast a generic collection RecordCollection to a derived collection PersonCollection, but I get a cast exception:

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

The reason I'm trying to do this is two-fold:

  1. The derived classes (eg, PersonCollection) can have insta开发者_JAVA技巧nce methods (eg, GetLastNames) which shouldn't be in the base class.
  2. The method GetRecords is generic so I can get a collection of any Record objects.

What is the best approach to solve this in C# 2.0? What is the most elegant approach to solving this?

This is signature of GetRecords:

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

This is my base implementation:

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
}

I have derived objects based on that base implementation as follows:

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>
{

}


Your approach does not work because cast does not convert instances of one class to instances of another class.

You did not give the code of GetRecords<> method, but presumably GetRecords returns RecordCollection, and not PersonCollection (it has new RecordCollection somewhere in the code, doesn't it?).

You cannot cast RecordCollection to PersonCollection unless this particular instance actually is PersonCollection. Presicely because it does not have these additional methods.

This is like

SomeClass obj=new SomeClass();
DerivedClass o=(DerivedClass)obj; //throws exception


Your best bet is to use some sort of factory call inside GetRecords, so that when you request a 'collection' of Person it will return PersonCollection as RecordCollection<Person>.

A naive implementation can use a few if's, else you can associate concrete collection type to record types via a Dictionary<Type,Type>.


One option:

Make the methods on the derived types non-extension static methods that take in a specialized RecordsCollection ie

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

so you can have usage along the lines of

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

It's not as pretty as the extension methods, but not too bad either.
edit: Removed erroneous info previously posted and replaced with potential solution

0

精彩评论

暂无评论...
验证码 换一张
取 消