假设我们有一个包含以下值(都是字符串)的输入列表:
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中的类型列表进行匹配来验证ListA中的所有值是否都正确。两个列表的长度相同。
如果是,我想获取一个List作为返回值,其中ListA的所有值都以ListB中指定的格式存储。 如果一次转换失败,我希望能够引发一个自定义异常。
throw new MyException($"Failed to convert value {valueX} to {type}");
我只能想象一个非常丑陋的解决方案,其中包含for循环,大量强制转换/转换和复制。有解决方案吗?
答案 0 :(得分:1)
您可以将Zip列表放在一起,然后使用Convert.ChangeType
方法
返回指定类型的对象,该对象的值等于a 指定的对象。
它将引发以下类型的异常
InvalidCastException
不支持此转换。 -或-value为null,conversionType为值类型。 -或-值不
实现IConvertible接口。
FormatException
的值不是由conversionType识别的格式。
OverflowException
值表示一个超出conversionType范围的数字。
ArgumentNullException
conversionType为空。
示例
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);
}
}
小注释 :从技术上讲,这并不是强制转换本身,而是更改/转换类型
答案 1 :(得分:1)
您可以对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中进行转换,可以确保如果列表中较早的地方没有异常,则不必转换整个列表。
答案 2 :(得分:0)
好吧,如果您想避免使用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]);
}