如何将一种类型的通用列表转换为未知类型的通用列表

Bra*_*oss 3 c# generics reflection

我想写一个函数,它接受一个List<Object>并返回一个原始列表,该列表被转换为一个指定对象类型的列表List<ObjectType>,知道原始列表中的对象是类型ObjectType.诀窍是ObjectType可以是任何类型,我发现使用反射.很抱歉没有代码,但我没理由知道我甚至可能会这样做.

p.s*_*w.g 8

如果您知道列表中的每个项目都是类型ObjectType,则可以执行以下操作:

List<object> sourceList = new List<object>() { 1, 2, 3 };
List<int> resultList = sourceList.Cast<int>().ToList();
Run Code Online (Sandbox Code Playgroud)

如果您确实想以通用方式转换列表中的每个项目,最简单的方法是执行以下操作:

public static IEnumerable<T> ConvertTo<T>(this IEnumerable items)
{
    return items.Cast<object>().Select(x => (T)Convert.ChangeType(x, typeof(T)));
}
Run Code Online (Sandbox Code Playgroud)

这将作为扩展方法实现,因此您可以编写:

List<object> sourceList = new List<object>() { 1, 2, 3 };
List<string> resultList = sourceList.ConvertTo<string>().ToList();
Run Code Online (Sandbox Code Playgroud)

如果在编译时不知道目标类型,则确实需要使用反射.像这样的东西会起作用:

class ListUtil
{
    public static List<T> ConvertToList<T>(this IEnumerable items)
    {
        // see method above
        return items.ConvertTo<T>().ToList();
    }

    public static IList ConvertToList(this IEnumerable items, Type targetType)
    {
        var method = typeof(ListUtil).GetMethod(
            "ConvertToList", 
            new[] { typeof(IEnumerable) });
        var generic = method.MakeGenericMethod(targetType);
        return (IList)generic.Invoke(null, new[] { items });
    }
}
Run Code Online (Sandbox Code Playgroud)

现在你可以称之为:

List<object> sourceList = new List<object>() { 1, 2, 3 };
IList resultList = ListUtil.ConvertToList(sourceList, typeof(string));
resultList.GetType(); // List<string>
Run Code Online (Sandbox Code Playgroud)

当然,使用此方法可以避免任何编译时类型的安全性.

  • 如果类型仅在运行时已知,则方法将不起作用 (2认同)