在继承泛型类时,需要T的列表或枚举器的建议

时间:2008-09-10 04:03:08

标签: c# generics

我知道答案并不简单,我已经使用了一些(我觉得很丑陋)的cludges。我只是在寻找一些优雅的答案。

抽象类:

public interface IOtherObjects;

public abstract class MyObjects<T> where T : IOtherObjects
{
   ...

   public List<T> ToList()
   {
       ...
   }
}

儿童:

public class MyObjectsA : MyObjects<OtherObjectA> //(where OtherObjectA implements IOtherObjects)
{


}

public class MyObjectsB : MyObjects<OtherObjectB> //(where OtherObjectB implements IOtherObjects)
{


}

是否可以循环遍历MyObjects(或其他类似的分组,通用或其他)的集合,然后使用 MyObjects 基类的 ToList 方法,如我们此时并不特别知道T的类型。

修改 至于具体的例子,每当这个问题出现时,我已经考虑了一段时间,并做了不同的事情,所以没有当前的要求。但是因为它经常出现,我以为我会漂浮它。

修改 @Sara,它不是我关心的集合的特定类型,它可能是一个List,但是每个实例的ToList方法仍然相对不可用,没有匿名类型)

@aku,true,这个问题可能是相对假设的,但是能够检索并使用T对象列表,只知道它们的基类型将非常有用。让ToList返回List of BaseType是我的解决方法之一

编辑 @ all:到目前为止,这是我希望的那种讨论,尽管它在很大程度上证实了我所怀疑的一切。谢谢所有人,但其他任何人都可以随意输入。

编辑 @Rob,是的,它适用于已定义的类型,但不适用于仅将类型称为IOtherObjects列表的情况。

@Rob 再次谢谢。这通常是我的狡猾的解决方法(没有不尊重:))。或者使用ConvertAll函数通过委托进行Downcast。感谢您花时间了解问题。

合格编辑,以防我有点困惑

更确切地说,(我可能已经让我最近的实现变得太复杂了):

假设我有2个对象类型,B和C继承自对象A.

很多场景都出现在B列表或C列表中,或者在其他情况下列出了一个列表 - 但我不知道如果我在基类,我需要少一些具体的A.清单。

上面的例子是 List Of Less Specific 问题的最新版本的一个淡化例子。

通常它已经出现了,因为我认为可能的场景限制了需要编写的代码量,并且看起来比其他选项更优雅。我真的想要讨论可能性和其他观点,我或多或少都有。我很惊讶到目前为止还没有人提到ConvertAll(),因为这是我使用过的另一种解决方法,但对于手头的场景来说有点过于冗长

@Rob 又一次和Sara

谢谢,但是我确实觉得我理解他们所有静态背景中的泛型,并且确实理解了这里的问题。

我们系统的实际设计和仿制药的使用(我可以说这不仅仅是一点偏见,因为我只是设计中的一员),已经做得很好。就在我使用核心API的时候,我已经找到了一些情况,当我在一个错误的范围内做一些简单的事情,而不是我不得不处理它们而不是我喜欢的那么优雅(试图要聪明或者懒惰 - 我会接受其中任何一个标签。)

我对我称之为“污垢”的厌恶主要是我们需要在记录集中循环,只是将对象转换为可能会影响性能的基值。

我想我想知道是否有其他人在他们的编码之前遇到过这种情况,如果有人在处理它时比我更聪明,或者至少更优雅。

7 个答案:

答案 0 :(得分:2)

在你的情况下,MyObjectsA和MyObjectsB没有共同的前任。泛型类是不同类的模板,而不是公共基类。如果要在不同的类中使用公共属性,请使用接口。您不能在循环中调用 ToList ,因为它在不同的类中具有不同的签名。您可以创建返回对象而不是特定类型的ToList。

答案 1 :(得分:2)

为什么你有一个MyObjects的集合?您是否有特定原因没有列表?

答案 2 :(得分:1)

您仍然可以访问ToList()方法,但由于您不确定该类型,这不会起作用吗?

foreach(var myObject in myObjectsList)
    foreach(var obj in myObject.ToList())
        //do something

当然这只适用于C#3.0。

请注意,var的使用仅仅是为了消除知道列表包含什么类型的要求;与弗兰克的评论相反,我认为var会使打字变得动态。

答案 3 :(得分:1)

好的,我很困惑,以下代码对我来说很好(好奇心让我变得更好!):

// Original Code Snipped for Brevity - See Edit History if Req'd

或者我错过了什么?

更新以下来自OP的响应

好的,现在我真的很困惑.. 你要说的是你想从通用/抽象列表中获取 Typed 值列表? (因此,儿童班变得无关紧要)。

如果类型是子/接口实现者,则无法返回类型列表 - 它们不匹配!您当然可以从抽象列表中获取特定类型的项目列表,如下所示:

    public List<OfType> TypedList<OfType>() where OfType : IOtherObjects
    {
        List<OfType> rtn = new List<OfType>();

        foreach (IOtherObjects o in _objects)
        {
            Type objType = o.GetType();
            Type reqType = typeof(OfType);

            if (objType == reqType)
                rtn.Add((OfType)o);
        }

        return rtn;
    }

如果我仍然离开这里,你可以改回你的问题吗?! (似乎我不是唯一一个不确定你驾驶的人)。我试图确定你是否存在对泛型的误解。

另一个更新:D

是的,所以看起来你想要/需要选项来获取类型化列表,或基本列表是吗?

这将使您的抽象类看起来像这样 - 您可以使用ToList来获取具体类型,或者使用ToBaseList()来获取接口类型的List。这应该适用于您拥有的任何场景。这有帮助吗?

public abstract class MyObjects<T> where T : IOtherObjects
{
    List<T> _objects = new List<T>();

    public List<T> ToList()
    {
        return _objects;
    }

    public List<IOtherObjects> ToBaseList()
    {
        List<IOtherObjects> rtn = new List<IOtherObjects>();
        foreach (IOtherObjects o in _objects)
        {
            rtn.Add(o);
        }
        return rtn;
    }
}

更新#3

这不是一个“cludgy”的解决方法(没有不尊重) - 这是唯一的方法。我认为这里更大的问题是设计/问题。你说你遇到了问题,这段代码解决了这个问题。但是,如果你期望做类似的事情:

public abstract class MyObjects<T> where T : IOtherObjects
{
    List<T> _objects = new List<T>();

    public List<IOtherObjects> Objects
    { get { return _objects; } }
}
#warning This won't compile, its for demo's sake.

并且能够挑选出来的类型,可以你怎么做?!我觉得你并不真正理解泛型的含义是什么,而你正试图让他们做一些他们不是为了设计的东西!?

答案 4 :(得分:1)

如果你有

class B : A
class C : A

你有

List<B> listB;
List<C> listC;

您希望将其视为父类型的列表

然后你应该使用

List<A> listA = listB.Cast<A>().Concat(listC.Cast<A>()).ToList()

答案 5 :(得分:0)

我最近找到了

List<A>.Cast<B>().ToList<B>()

图案。

它完全符合我的要求,

答案 6 :(得分:-1)

泛型用于静态时间类型检查运行时调度。使用inheritance / interfaces进行运行时调度,使用泛型进行编译时类型保证。

interface IMyObjects : IEnumerable<IOtherObjects> {}
abstract class MyObjects<T> : IMyObjects where T : IOtherObjects {}

IEnumerable<IMyObjects> objs = ...;
foreach (IMyObjects mo in objs) {
    foreach (IOtherObjects oo in mo) {
        Console.WriteLine(oo);
    }
}

(显然,我更喜欢Enumerables而不是列表。)

OR 只需使用适当的动态语言,如VB。 : - )