假设我有一组对象,其中一些是数组。
我想将所有值连接起来打印它们,但我不知道数组中元素的类型。
foreach(var item in myList)
{
var val = item.Property;
if (val.GetType().IsArray)
{
var array = val as IEnumerable<object>;
val = string.Join(",", array);
}
DoSomething(val);
}
如果val包含string[]
,则此代码段也适用于myClass[]
。
但如果它包含int[]
或double[]
,则数组将为null,表示动态转换失败。
如果从继承自object的System.TypeValue继承int或double,为什么不对此代码段起作用?
我怎么能实现呢?
编辑:将代码段更改为更明确,并避免错误的变量用法,因为我错误地简化了我的代码。
答案 0 :(得分:2)
在C#中不允许这样做,更多细节here。
但是您可以转换为非泛型 IEnumerable
,然后在推送到string.Join()
之前将所有内容转换为对象:
foreach(var val in myList)
{
if (val.GetType().IsArray)
{
var array = (IEnumerable)val;
// It's not allowed to set val variable, but I assume it's just an example
val = string.Join(",", array.Cast<object>());
}
}
答案 1 :(得分:0)
首先,尝试在val
循环内分配foreach
将无法正常工作。您无法更改正在迭代的集合。
所以你需要建立一个新的集合。这样的工作,看看迭代器中的yield return
语句如何构建一个新的IEnumerable
叶子对象,并适用于任何级别的对象和值类型。
class Program
{
static void Main(string[] args)
{
var myWackyList = new object[] {
new[]{1d, 2d},
3d,
new[]{4d, 5d},
new []
{
new[]
{
6d
}
},
"7",
new[]{ "8", "9"}
};
Console.WriteLine( string.Join(", ", Flatten( myWackyList )));
}
static IEnumerable<object> Flatten(IEnumerable enumerable)
{
foreach (var val in enumerable)
{
if ( val.GetType().IsArray )
foreach ( var flattenedVal in Flatten( val as IEnumerable ) )
yield return flattenedVal;
else
yield return val;
}
}
}
答案 2 :(得分:0)
如果你只是担心一般的阵列,或者更好的是IEnumerable
(根据你的演员阵容)那么我建议将支票的反射部分留下来,只是试图转换为{{1} }。
IEnumerable
老实说,我不知道你打算如何处理数组,因为你将它作为一个对象添加到一个字符串中,它只是foreach (var val in myList)
{
if (val is IEnumerable enumeration)
{
string.Join(",", array); //You can't use val (as per your example because it's the element of the loop)
}
}
等等。我会发布一个更好的解决方案但是我不确定它是否是你想要的,因为你上面做的事情并没有多大意义。
array, array, array...
现在,至少我觉得你更倾向于你想要的方向,但是我不能很好地和我坐在一起,因为我不知道你是怎么回事。重新获得它。
我将发布另一个示例,一个将迭代并为您构建字符串内部枚举的示例。我不知道或假设你想要什么,但在我提供的3个例子之间,我希望你可以带走并重新设计它以获得你需要的东西,并从中学到它。 / p>
var notSureWhyStringBuilder = new StringBuilder();
foreach (var val in myList)
{
if (val is IEnumerable enumeration)
{
notSureWhyStringBuilder.Append($",{enumeration.ToString()}");
}
}
Console.WriteLine(notSureWhyStringBuilder.ToString());
这是一个小型的控制台应用程序,我把它放在一起让你捣乱。按原样复制并粘贴它,它应该可以工作。
控制台应用
var notSureWhyStringBuilder = new StringBuilder();
foreach (var val in myList)
{
if (val is IEnumerable enumeration)
{
foreach (var innerEnumeration in enumeration)
{
notSureWhyStringBuilder.Append($",{innerEnumeration.ToString()}");
}
}
}
Console.WriteLine(notSureWhyStringBuilder.ToString());
<强>输出强>
using System;
using System.Collections;
using System.Collections.Generic;
using System.Text;
namespace Question_Answer_Console_App
{
class Program
{
private const string ShortTab = " ";
private static readonly List<object> ListOfObjects = new List<object>()
{
4,
"Michael",
new object(),
new Program(),
69.4,
new List<string>() {"Mathew", "Mark", "Luke", "John" },
new int[] { 1, 3, 5, 7, 9 }
};
static void Main(string[] args)
{
var itemsText = new StringBuilder();
var arrayCounter = 0;
foreach (var item in ListOfObjects)
{
if (item is IEnumerable enumeration)
{
itemsText.AppendLine($"Array: {++arrayCounter}");
if (item is string text)
{
itemsText.AppendLine($"{ShortTab}{text}");
}
else
{
foreach (var innerItem in enumeration) itemsText.AppendLine($"{ShortTab}{innerItem.ToString()}");
}
}
}
Console.WriteLine(itemsText.ToString());
Console.Read();
}
}
}
答案 3 :(得分:0)
您无法将值类型数组强制转换为IEnumerable,因为只有在不需要代表性转换的情况下,方差才适用。因此,它不适用于价值类型。在这种特殊情况下,这种转换意味着拳击。
我会这样做以防止不必要的装箱,例如Cast中的情况。
public static string Stringify(this object o, string delimiter)
{
if (!(o is IEnumerable enumerable))
return o.ToString();
var sb = new StringBuilder();
foreach (var i in enumerable)
{
if (sb.Length > 0)
sb.Append(delimiter);
sb.Append(i.ToString());
}
return sb.ToString();
}