将CollectionBase子类强制转换为通用List,而不显式指定类型

时间:2015-09-08 20:17:40

标签: c# generics types casting

我有public abstract class BaseList : CollectionBase { public abstract Type ListType { get; } } public class MyClassList : BaseList { public override Type ListType { get { return typeof(MyClass); } } } 的子类,如下所示:

ToGenericList()

所以我在编译时知道类型。我想添加一个方法BaseList 我的BaseList类会将任何List转换为类型的通用ListType public List<T> ToGeneric<T>() { return List.Cast<T>().ToList(); }

这不起作用:

someList.Cast<MyClass>().ToList();

因为“无法根据用法推断出类型参数。”显然,我可以 这样做:

someList.ToGeneric<MyClass>();

或者这个:

#include <iostream>
#include <type_traits>

template <typename R, typename S>
class ICanDoIt
{
    public:
        virtual void doStuff() = 0;

    protected:
        ICanDoIt<R, S>(R rA, S sA) : r(rA), s(sA) {};
        R r;
        S s;
};

class DoesIt : public ICanDoIt<int, double>
{
        public:
            DoesIt(int iA, double dA) : ICanDoIt(iA, dA) {};

            virtual void doStuff()
                { std::cout << "r * s = " << r * s << " done." << std::endl; }
};

template <typename T>
class NeedsSomeoneWhoCanDoIt
{
    static_assert(std::is_base_of<ICanDoIt<R, S>, T>::value, 
                  "T needs to be able to do it.");

    public:
        NeedsSomeoneWhoCanDoIt(const T& doesItA) : doesIt(doesItA) {};
        void getItDone() { doesIt.doStuff(); };

    private:
        T doesIt;
};


int main()
{
    DoesIt doesIt(5, 2.2);
    NeedsSomeoneWhoCanDoIt<DoesIt> needsIt(doesIt);
    needsIt.getItDone();
}

但是当我使用具有的对象时,这会使非常麻烦 列表列表的列表,我想在它们上面使用一堆LINQ方法,类名称长度超过30个字符。

是否有任何解决方案不涉及调用者指定类型或 一点都没有?

2 个答案:

答案 0 :(得分:2)

没有办法让编译器通过返回类型进行推断。一种选择是为每个集合类型添加一个方法以返回泛型集合:

public class MyClassList : BaseList
{
    public override Type ListType
    {
        get { return typeof(MyClass); }
    }
    public List<MyClass> ToGeneric()
    {
        return this.Cast<MyClass>.ToList();
    }
}

请注意,没有办法将它放在基类上,因为唯一改变的是返回类型(不能通过仅更改返回类型来重载方法)。

如果您不能/不想更改可以使其成为扩展方法的基本类型,但您仍需要为每种类型设置方法。

答案 1 :(得分:1)

如果您的列表具有特定的命名约定,则可以尝试大爆炸方法。

首先,声明第二个基类,引入中间层次结构级别:

public abstract class BaseList<T> : BaseList, IList<T>
{
    public override Type ListType { get { return typeof(T); } }

    // Delegate IList<T> implementation to the base class

    public new IEnumerator<T> GetEnumerator()
    {
        return base.Cast<T>().GetEnumerator();
    }

    public void Add(T item)
    {
        base.Add(item);
    }

    public bool Contains(T item)
    {
        return base.Contains(item);
    }

    public void CopyTo(T[] array, int arrayIndex)
    {
        base.CopyTo(array, arrayIndex);
    }

    public bool Remove(T item)
    {
        return base.Remove(item);
    }

    public int IndexOf(T item)
    {
        return base.IndexOf(item);
    }

    public void Insert(int index, T item)
    {
        base.Insert(index, item);
    }

    public new T this[int index]
    {
        get { return (T)base[index]; }
        set { base[index] = value; }
    }
}

然后,好吧......对代码执行正则表达式替换。您可以使用VS 替换文件工具。

查找

\bclass\s+(\w+)List\s*:\s*BaseList\b

替换为:

class $1List : BaseList<$1>

这是否可行取决于你的代码库,但它可能是一个开始。

完成后,您可以摆脱现在多余的ListType覆盖。