如果我在编译时不知道它的类型,我该如何加入一个集合?

How do I join a collection if I don't know its type at compile-time?

我们有一个字符串的盒装列表:

object myList = new List<string> { "str1", "str2" };

我们要用String.Join得到"str1,str2"。如果我们这样做

String.Join(",",myList)

它 returns System.Collections.Generic.List`1[System.String] 代替。 我们如何在不更改 myList?

声明的情况下处理此问题?

这只是一个具体的例子。类型不必总是 List<string>,我们需要做 myList.GetType() 来获取该信息。

如果您不知道装箱集合的类型,您可以编写一个辅助方法来拆箱并加入它:

public string UnboxAndJoin(string separator, object obj)
{
    if (obj is IEnumerable enumerable)
    {
        return string.Join(separator, enumerable.Cast<object>());
    }
    else
    {
        throw new ArgumentException("Object is not an IEnumerable");
    }
}

用法:

object myList = new List<string> { "str1", "str2" };
Console.WriteLine(UnboxAndJoin(",", myList));       // str1,str2

您将得到 System.Collections.Generic.List`1[System.String],这是您案例中的预期结果。

String.Join 的重载解决方案在您的情况下选择了以下重载:

public static string Join (string? separator, params object?[] values);

如文档所述,对 values 参数的每个对象调用 here the Object.ToString() method。文档中的引述:

The string representation of each object in the array is derived by calling that object's ToString method.

values 参数中的唯一对象是 List<string> class 的实例。此 class 不会覆盖 Object class 中定义的 ToString() 的基本实现,因此 class 的完全限定名称在 ToString() 在 class 本身的任何实例上被调用。

这就是您将字符串 System.Collections.Generic.List`1[System.String] 作为代码输出的原因。

如果您想要的输出是字符串 "str1,str2",那么您真正想要调用的 String.Join 的重载如下:

public static string Join (string? separator, System.Collections.Generic.IEnumerable<string?> values);

为了调用此重载,您需要将 myList 变量向下转换为 List<string> 类型:

String.Join(",", (List<string>) myList)

如果不知道 myList 变量中对象的实际类型,您可以采取防御措施并执行以下操作:

if (myList is IEnumerable<string> values) 
{
  var message = String.Join(",", values);
  Console.WriteLine(message);
}