传递给方法时,根据元素类型填充列表

时间:2014-03-17 19:48:37

标签: c#

不确定是否可行,但我希望能够根据List<T>填充T。目前,我有这样的事情(请原谅通用名称 - 它是出于测试目的):

public static class CollectionsClass
{

    List<Object1> list1 = new List<Object1>();
    List<Object2> list2 = new List<Object2>();
    List<Object3> list3 = new List<Object3>();
}

public static class ActionClass
{
    public static void PopulateCollections()
    {
        Populate(CollectionsClass.list1, 0, 10);
        Populate(CollectionsClass.list2, 20, 50);
        Populate(CollectionsClass.list3, 30, 100);
    }

    private static void Populate(dynamic list, int minLimit, int maxLimit)
    {
        var rnd = new Random();
        int rndNum = rnd.Next(minLimit, maxLimit);
        for (int i = 0; i < rndNum; i++)
        {
            if (list.GetType() == typeof(List<Object1>))
            {
                list.Add(new Object1());
            }
            else if (list.GetType() == typeof(List<Object2>))
            {
                list.Add(new Object2());
            }
            else if (list.GetType() == typeof(List<Object3>))
            {
                list.Add(new Object3());
            }
            else
            {
                // put out an error
            }
        }
    }
}

虽然该代码有效,但我想通过执行以下操作来缩小它:

list.Add(new list.ObjectType());

我整天都在思考反思和获取类型,但我似乎无法想象这一点。

6 个答案:

答案 0 :(得分:4)

不要使用动态,使用泛型:

static void Populate<T>(List<T> list, ...) where T: new()
{
    ... 
    for (int i=0; i<rndNum; i++)
        list.Add(new T());
}

答案 1 :(得分:3)

由于您已经在使用dynamic,因此您应该可以添加方法来处理此问题:

private static void AddToList<T>(List<T> list) where T : new()
{
    list.Add(new T());
}

鉴于此,你可以写:

private static void Populate(dynamic list, int minLimit, int maxLimit)
{
    var rnd = new Random();
    int rndNum = rnd.Next(minLimit, maxLimit);
    for (int i = 0; i < rndNum; i++)
    {
         AddToList(list);
    }
}

答案 2 :(得分:2)

尝试使用通用方法:

public static class CollectionsClass
{
    public static List<Object1> list1 = new List<Object1>();
    public static List<Object2> list2 = new List<Object2>();
    public static List<Object3> list3 = new List<Object3>();
}

public static class ActionClass
{
    public static void PopulateCollections()
    {
        Populate(CollectionsClass.list1, 0, 10);
        Populate(CollectionsClass.list2, 20, 50);
        Populate(CollectionsClass.list3, 30, 100);
    }

    private static void Populate<T>(List<T> list, int minLimit, int maxLimit)
        where T : new()
    {
        var rnd = new Random();
        int rndNum = rnd.Next(minLimit, maxLimit);
        for (int i = 0; i < rndNum; i++)
        {
            list.Add(new T());
        }
    }
}

答案 3 :(得分:1)

听起来你想要一系列泛型和反思。

首先make it generic

void Populate<T>(List<T> mylist)

现在您知道列表的类型:它是T

剩下的就是循环并创建特定类型T的实例。为此,您可以使用Activator.CreateInstance

for(int i = 0; i < 5; i++){
    mylist.Add((T) Activator.CreateInstance(typeof(T)));
}

使用此示例代码:

void Main()
{
    Populate<Type1>(new List<Type1>());
    Populate<Type2>(new List<Type2>());
}


void Populate<T>(List<T> mylist){
    for(int i = 0; i < 5; i++){
        mylist.Add((T) Activator.CreateInstance(typeof(T)));
    }

    foreach(var item in mylist){
        Console.WriteLine (item);
    }
}



class Type1 { }
class Type2 { }
class Type3 { }

你得到这个输出:

enter image description here

这将依赖于反射来创建对象的实例,假设有一个公共非参数构造函数可用(否则将从Activator抛出异常)。

这不是一个非常理想的行为,只要我看到在其泛型函数中使用where T : new()约束的其他答案,我就会意识到这一点:使用此方法超过我的。

我仍然会把它留在这里以保持完整性(至少它表明了一个可能的陷阱)。

答案 4 :(得分:1)

您可以使用通用new约束来实现此目的:

private static void PopulateList<T>(List<T> list, int minLimit, int maxLimit) 
    where T : new()
{
    var rnd = new Random();
    int rndNum = rnd.Next(minLimit, maxLimit);
    for (int i = 0; i < rndNum; i++)
    {
         list.Add(new T());
    }
}

约束是类型T必须提供默认构造函数。如果要将项添加到List,则不需要dynamic关键字,因为您可以直接将List<T>指定为参数类型。

如果您无法添加默认构造函数,还可以提供创建者函数

private static void PopulateList<T>(List<T> list, Func<int, T> creatorFunc, 
                                    int minLimit, int maxLimit) 
{
    var rnd = new Random();
    int rndNum = rnd.Next(minLimit, maxLimit);
    for (int i = 0; i < rndNum; i++)
    {
         list.Add(creatorFunc(i));
    }
}

你可以这样调用这个方法:

var lst = new List<MyObjectType>();
PopulateList<MyObjectType>(lst, x => new MyObjectType(x), 1, 7);

在此示例中,i的值提供给creatorFunc,后者返回类型为MyObjectType的新对象。

答案 5 :(得分:1)

使用factory来提取创建逻辑,使用反射来获取正确的类型,使用Activator来获取实例。

public static class TFactory 
{ 
    public static T Getmplementation<T>()
    {            
        var typeName = typeof(T).Name;
        var type = Type.GetType(typeName);
        if (type != null)
            return Activator.CreateInstance(type) as T;
        else
            throw new NotImplementedException(typeName);
    }
}

然后,

List.Add(TFactory.GetImplmentation&LT;&#39; T&GT;());