【问题标题】:Casting generic collection to concrete implementation in C# 2.0将泛型集合转换为 C# 2.0 中的具体实现
【发布时间】:2010-12-15 03:46:26
【问题描述】:

选择的解决方案

感谢大家的帮助。我决定做以下事情。

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

}

【问题讨论】:

  • 你说你想强制转换是因为派生类可能有扩展方法。您实际上是指实例方法吗?如果您真的是指扩展方法,那么像这样声明它们并没有错:method(this RecordCollection records,...)

标签: c# c#-2.0 collections generics casting


【解决方案1】:

一个选项:

使派生类型上的方法成为非扩展静态方法,这些方法采用专门的 RecordsCollection 即

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

所以你可以按照以下方式使用

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

它不如扩展方法漂亮,但也不算太差。
编辑:删除之前发布的错误信息并替换为潜在的解决方案

【讨论】:

  • -1:这个问题与泛型变量无关,在 C# 4.0 中仍然无法工作。这是因为你不能将一个对象转换为更派生的类型,因为它不是一个类型,而且这永远不会改变。
  • 糟糕,我读得太快了,误解了他的问题。谢谢指正。
【解决方案2】:

您的方法不起作用,因为强制转换不会将一个类的实例转换为另一个类的实例。

你没有给出 GetRecords 方法的代码,但大概是 GetRecords 返回 RecordCollection,而不是 PersonCollection(它在代码的某处有新的 RecordCollection,不是吗?)。

除非此特定实例实际上是 PersonCollection,否则您不能将 RecordCollection 转换为 PersonCollection。正是因为它没有这些额外的方法。

这就像

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

【讨论】:

  • 我为 GetRecords 添加了签名
【解决方案3】:

最好的办法是在GetRecords 中使用某种工厂调用,这样当您请求“收集”Person 时,它会将PersonCollection 作为RecordCollection&lt;Person&gt; 返回。

简单的实现可以使用一些 if,否则您可以通过 Dictionary&lt;Type,Type&gt; 将具体集合类型与记录类型相关联。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-06-24
    • 2019-04-05
    • 2010-10-07
    • 2023-04-04
    相关资源
    最近更新 更多