假设我们有一个包含以下值的输入列表(都是字符串(:
var listA = new List<string>();
listA.Add("test");
listA.Add("123");
listA.Add("5.7");
我们还得到了第二个列表:
var listB = new List<object>();
listB.Add(typeof(string));
listB.Add(typeof(int));
listB.Add(typeof(float));
我想通过将 ListA 中的所有值与 ListB 中的类型列表匹配来验证其格式是否正确。两个列表将具有相同的长度。
如果是,我想获取一个 List 作为返回值,其中 ListA 的所有值都以 ListB 中指定的格式存储。如果一个会议失败,我希望能够抛出一个自定义异常。类似的东西
throw new MyException($"Failed to convert value {valueX} to {type}");
我只能想象一个非常丑陋的解决方案,包括 for 循环、大量投射/转换和复制。有没有一个优雅的解决方案?
您可以使用 Zip 执行以下操作。
var result = listA.Zip(listB,(value,type)=>
{
try{return Convert.ChangeType(value,(Type)type);}
catch{throw new Exception($"Cannot cast between value {value} to Type {type}");}
});
通过在 Zip 中进行转换,将确保在列表中较早出现异常时不必转换整个列表。
您可以将列表压缩在一起,然后使用 Convert.ChangeType
方法
返回指定类型的对象,其值等效于指定的对象。
它将引发以下类型的异常
空,转换类型为值类型。 -或 - 值不实现 IConvertible 接口。
FormatException
值不是转换类型识别的格式。OverflowException
值表示超出转换类型的数字。ArgumentNullException
转换类型为空。
InvalidCastException
不支持此转换。 -或 - 值为例
var listA = new List<string> { "test", "123", "5.7" };
var listB = new List<Type> { typeof(string), typeof(int), typeof(int) };
var combined = listA.Zip(listB, (s, type) => (Value :s, Type:type));
foreach (var item in combined)
{
try
{
Convert.ChangeType(item.Value, item.Type);
}
catch (Exception ex)
{
throw new InvalidOperationException($"Failed to cast value {item.Value} to {item.Type}",ex);
}
}
完整演示在这里
旁注:从技术上讲,这不是强制转换本身,而是更改/转换类型
避免forloop
并使用linq来做,仍然是可能的
这是我必须的
var listA = new List<string>();
listA.Add("test");
listA.Add("123");
listA.Add("5.7");
var listB = new List<Type>();
listB.Add(typeof(string));
listB.Add(typeof(int));
listB.Add(typeof(float));
var index =-1;
try{
var newList = listA.Select((x, i)=> Convert.ChangeType(x, listB[(index = i)])).ToList();
}catch(Exception e){
throw new Exception("Failed to cast value "+listA[index]+" to "+listB[index]);
}