如何在C#中动态转换泛型列表?

9

我正在尝试动态地将List<object>转换为List<string>。我尝试了几种方法,但是无法找到解决方案。以下是一个小示例,展示了这个问题:

List<object> listObject = new List<object>();
listObject.Add("ITEM 1");
listObject.Add("ITEM 2");
listObject.Add("ITEM 3");

List<string> listString = ¿¿listObject??;

提前感谢!


8
在第四版中也不可能实现这一点,因为将 List<T> 进行"向上转型"或"向下转型"都不是类型安全的-它是不变的,既不是协变的也不是逆变的。顺便说一句,我对每个关于集合协变性/逆变性的问题都发布错误信息感到厌烦。 - Pavel Minaev
6个回答

18

如果您可以使用LINQ,那么Cast方法将实现您的需求:

List<string> listString = listObject.Cast<string>().ToList();

正如Stan在他的回答中所指出的那样,您也可以使用ConvertAll方法:

List<string> listString = listObject.ConvertAll(x => (string)x);

如果您没有使用C#3,则需要使用“旧”的委托语法而不是Lambda表达式:

List<string> listString =
    listObject.ConvertAll(delegate(object x) { return (string)x; });

1
@nader:我总是试着记住,当LINQ不可用时,lambda语法也不可用。 - LukeH
而且为了预防任何挑剔的人......我知道VS2008可以针对较早版本的.NET Framework,这将允许使用Lambda语法但不是LINQ。但是,一般来说,没有LINQ通常意味着也没有Lambda。 - LukeH

4
如果您使用的是.NET 3.5,您可以使用此方法,这样您就不必执行额外的ToList()操作。如果需要转换高级对象,您还可以提供自己的转换器。
 List<string> listString = listObject.ConvertAll(x=> x as String);

如果您无法使用LINQ,可以这样做。
foreach(object item in listObject)
{
  string convertedItem = item as String;
  if(convertedItem != null)
       listString.Add(convertedItem);
}

1
这也在.NET 2.0中得到支持(尽管没有LINQ,但委托语法不是很好)。但需要注意的是,我不认为.Cast<string>.ToList()会创建像你暗示的“额外”列表。它将为结果创建一个新列表,就像您的方法一样。 - Nader Shirazie
我想你指的是C# 3.0和.Net 3.5。 - user7116
@nader:我的意思是ToList()会进行额外的枚举。 - Stan R.
1
@Stan:你确定吗?ToList()会导致枚举,但仅此而已。Cast<string>()不会实际枚举集合。 - Nader Shirazie
@Nader:我非常确定 Cast 枚举一次以对每个对象执行转换,然后我认为 ToList 进行另一个枚举(它调用 CopyTo)。 - Stan R.
显示剩余2条评论

1
这样怎么样:
public static List<T> ConvertToGenericList<T>(IList listOfObjects)
{
    List<T> items = new List<T>();

    for (int i = 0; i < listOfObjects.Count; i++)
    {
        items.Add((T)listOfObjects[i]);
    }
     return items;
}

使用方法:

List<object> listObject = new List<object>();
listObject.Add("ITEM 1");
listObject.Add("ITEM 2");
listObject.Add("ITEM 3");
List<string> listString = Converter.ConvertToGenericList<string>(listObject);

0

我认为你不能一步完成它。相反,尝试像这样:

        List<object> listObject = new List<object>();
        listObject.Add( "ITEM 1" );
        listObject.Add( "ITEM 2" );
        listObject.Add( "ITEM 3" );

        List<string> lstStr = new List<string>( listObject.Count );

        foreach ( object obj in listObject )
        {
            lstStr.Add( obj.ToString() );
        }

这是错误的,他不想在该对象上调用ToString()方法,他想将其转换为字符串对象。从技术上讲,你的示例这次可以工作,但只适用于字符串。但如果他碰巧遇到更高级的对象,他将无法使用这种方法。 - Stan R.

0
List<string> listString = (from o in listObject select (string)o).ToList();

-2

我的第一篇帖子... 希望有用,看起来能在我的项目中工作...

        public  dynamic ConvertList(Type CallingType)
    {

        dynamic DynamicList;

        if (CallingType == TypeOfValue)
        {
            Type d1 = typeof(List<>);

            Type[] typeArgs = { TypeOfValue };

            Type DynamicListType = d1.MakeGenericType(typeArgs);


            object DynamicListObj = Activator.CreateInstance(DynamicListType);


            DynamicList = Convert.ChangeType(DynamicListObj, DynamicListType);


            foreach (object ValueElement in ValueRange)
            {
                    dynamic el = Convert.ChangeType(ValueElement, TypeOfValue);
                    DynamicList.Add(el);
            }

        }
        else //retrun empty List but with right type
        {
            Type d1 = typeof(List<>);

            Type[] typeArgs = { CallingType };

            Type DynamicListType = d1.MakeGenericType(typeArgs);

            object DynamicListObj = Activator.CreateInstance(DynamicListType);

            DynamicList = Convert.ChangeType(DynamicListObj, DynamicListType);
        }

        return DynamicList;
    }

我想我会在某个地方添加一个 try catch。

如何进行测试

                if (PropertyType == typeof(UInt32))
                {
                    List<UInt32> UInt32_test = NewProperty.ConvertList(PropertyType);
                }
                if (PropertyType == typeof(string))
                {

                    List<string> string_test = NewProperty.ConvertList(PropertyType);
                }

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接