【问题标题】:Treat variable as List if template is List<>如果模板是 List<>,则将变量视为 List
【发布时间】:2017-06-26 08:23:02
【问题描述】:

如果模板是列表,我必须创建填充数据的列表。我有一个功能

    static T GenerateRandomFields<T>() where T:new()
    {
        var ret= new T();

        if (typeof(T)==typeof(List<>))
        {
            var leng = rnd.Next(50);
            List<typeof(T).GenericTypeArguments[0]> test;
            for (int i = 0; i < leng; i++)
                ((List<>)ret).Add(...);
            return ret;
        }
        ...
    }

但是不可能将 ret 转换为 List。 ret如何添加数据?

【问题讨论】:

  • 你的方法签名指定返回类型是T,而不是List&lt;T&gt;。你想做什么?如果 T 是 List,是否要返回 List&lt;List&lt;TWhatever&gt;&gt;
  • 您可以使用IList&lt;TItem&gt; 约束创建另一个方法。这将允许您直接使用 IList&lt;T&gt; 方法,例如 ret.Add 并返回该列表
  • 对非集合类型T调用这个方法有意义和正确吗?方法名称听起来很像它只是用于集合。
  • 不要这样做。这是对泛型的滥用。泛型应该是generic;如果您有专门列表的行为,那么它不是通用

标签: c#


【解决方案1】:

据我所知,您必须使用反射。当您在编译时知道类型参数时,您将创建一个简单的泛型方法:

public static IList<T> GenerateRandomList<T>() where T : new() {
    var list = new List<T>();
    var rnd = new Random();
    var leng = rnd.Next(50);

    for (var i = 0; i < Math.Max(leng, 1); i++) {
        var newItem = new T();
        list.Add(newItem);
    }

    return list;
}

现在,您必须将此方法与现有方法联系起来。首先你需要MethodInfo 指向泛型方法(我的类名为Q42117838):

static MethodInfo genericMethod = typeof(Q42117838).GetMethod(nameof(GenerateRandomList));

其次,我们将为使用实际列表类型调用的方法声明一个缓存:

static Dictionary<Type, MethodInfo> methods = new Dictionary<Type, MethodInfo>();

我们可以把它放在一起:

public static T GenerateRandomFields<T>() where T : new() {
    if (typeof(System.Collections.IList).IsAssignableFrom(typeof(T))) {
        var listType = typeof(T).GenericTypeArguments[0];
        MethodInfo method;

        if (!methods.TryGetValue(listType, out method))
            methods.Add(listType, method = genericMethod.MakeGenericMethod(listType));

        return (T)method.Invoke(null, new object[0]);
    }

    return default(T);
}

请注意测试

if (typeof(T)==typeof(List<>))

不起作用,而且似乎没有简单的方法来检查泛型 IList&lt;&gt;(请参阅 this question),所以我使用了可以工作的非泛型变体。

现在您可以选择了,请致电:

  • var x = Q42117838.GenerateRandomList&lt;int&gt;()首选,因为你在编译时就知道类型)
  • var x = Q42117838.GenerateRandomFields&lt;List&lt;int&gt;&gt;()

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-11-27
    • 1970-01-01
    • 1970-01-01
    • 2023-01-19
    • 2018-03-20
    • 1970-01-01
    • 2018-12-11
    相关资源
    最近更新 更多