2

我知道答案不会很简单,而且我已经使用了几个(我认为丑陋的)结块。我只是在寻找一些优雅的答案。

抽象类:

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,是的,这个问题可能是相对假设的,但是能够检索并使用 T 对象列表,只知道它们的基本类型将非常有用。让 ToList 返回 BaseType 列表是我的解决方法之一

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

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

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

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

更准确地说,(我可能让我最新的实现变得太复杂了):

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

许多场景已经出现在哪里,从 B 列表或 C 列表,或者在其他情况下是其中之一的列表 - 但我不知道如果我在基类中,我需要一个不太具体的列表一种。

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

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

@Rob Yet Again和 Sara

谢谢,但是我确实觉得我理解泛型的所有静态上下文荣耀,并且确实理解了这里的问题。

我们系统的实际设计和泛型的使用(我可以这样说没有一点偏见,因为我只是设计中的参与者之一),已经做得很好。当我一直在使用核心 API 时,我发现我在错误的范围内简单地做某事,相反我不得不以比我喜欢的更不优雅的方式处理它们(尝试要么聪明或者可能是懒惰的——我会接受这些标签中的任何一个)。

我对我所说的 cludge 的厌恶主要是因为我们需要对记录集进行循环,只是为了将对象转换为它们的基本值,这可能会影响性能。

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

4

7 回答 7

2

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

于 2008-09-10T04:10:58.407 回答
2

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

于 2008-09-10T04:12:21.573 回答
1

您可能仍然可以访问 ToList() 方法,但由于您不确定类型,这不可行吗?

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

当然,这只适用于 C# 3.0。

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

于 2008-09-10T04:17:53.867 回答
1

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

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

还是我错过了什么?

更新以下来自 OP 的响应

好的,现在我真的很困惑..您的意思是您想从通用/抽象列表中获取类型值列表?(因此子类变得无关紧要)。

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

    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

这不是一个真正的“笨拙”的解决方法(没有不尊重) - 这是唯一的方法。我认为这里更大的问题是设计/grok问题。你说你有问题,这段代码解决了它。但是,如果您希望执行以下操作:

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.

并且能够挑选出来的类型,你还能怎么做?!我觉得您并不真正了解泛型的意义,并且您正试图让他们做一些他们不是为之设计的事情!?

于 2008-09-10T05:02:47.473 回答
1

如果你有

class B : A
class C : A

你有

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

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

那么你应该使用

List<A> listA = listB.Cast<A>().Concat(listC.Cast<A>()).ToList()
于 2008-09-17T15:27:57.177 回答
0

我最近发现

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

图案。

它完全符合我的要求,

于 2008-09-18T23:31:05.323 回答
-1

泛型用于静态时间类型检查而不是运行时调度。使用继承/接口进行运行时调度,使用泛型进行编译时类型保证。

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

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

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

于 2008-09-10T04:39:02.367 回答