如何在ObservableCollection遍历中用字符串替代属性名
问题
我想用数组中存储的字符串(对应ObservableCollection里对象的属性名),在foreach循环里作为属性使用,请问怎么正确处理这个字符串才能不报错?
报错信息:
System.FormatException: 'Input string was not in a correct format.'
我的代码:
string[] salaryArray = { "Salary1", "Salary2" }; var employees = new ObservableCollection<Employee>(); employees.Add(new Employee() { Name = "Ali", Title = "Developer", Salary1 = 25, Salary2 = 26 }); employees.Add(new Employee() { Name = "Ahmed", Title = "Programmer", Salary1 = 28, Salary2 = 29.5 }); employees.Add(new Employee() { Name = "Amjad", Title = "Desiner", Salary1 = 30, Salary2 = 32.4 }); foreach (Employee emp in employees) { Console.WriteLine(emp.Name + " " + emp.Salary2.ToString()); } foreach (string s in salaryArray) { string tempStr = "emp.s"; foreach (Employee emp in employees) { // 尝试使用数组中的字符串,此行报错 Console.WriteLine(emp.Name + " " + Convert.ToDouble(tempStr)); } }
我的Employee类:
public class Employee { public string Name { get; set; } public string Title { get; set; } public double Salary1 { get; set; } public double Salary2 { get; set; } }
解决方案
你当前的错误是因为把字符串"emp.s"当成数值去转换,这根本不是合法的数字格式。要通过字符串属性名获取对象的属性值,常用两种实用方法:
方法1:使用反射
反射可以通过属性名称动态获取对象的属性值,修改代码如下:
foreach (string s in salaryArray) { foreach (Employee emp in employees) { // 获取Employee类型中名为s的属性 var property = typeof(Employee).GetProperty(s); if (property != null) { // 获取当前emp对象的该属性值 double salaryValue = (double)property.GetValue(emp); Console.WriteLine($"{emp.Name} {salaryValue}"); } } }
注意:如果属性名拼写错误,GetProperty会返回null,建议加非空判断避免空引用异常。
方法2:提前建立属性名称到委托的映射(性能更优)
如果需要频繁调用,反射会有性能损耗,可提前把属性名称和对应的取值委托存入字典,后续直接调用:
// 提前创建映射字典 var salaryPropertyMap = new Dictionary<string, Func<Employee, double>> { { "Salary1", emp => emp.Salary1 }, { "Salary2", emp => emp.Salary2 } }; foreach (string s in salaryArray) { if (salaryPropertyMap.TryGetValue(s, out var getSalary)) { foreach (Employee emp in employees) { double salaryValue = getSalary(emp); Console.WriteLine($"{emp.Name} {salaryValue}"); } } }
这种方法没有反射的性能开销,且类型安全,推荐在需要多次调用的场景下使用。
原代码问题说明
你写的string tempStr = "emp.s"只是普通字符串,程序不会把它当成对象的属性访问代码执行,Convert.ToDouble(tempStr)自然报错——这个字符串根本不是数字格式。
内容的提问来源于stack exchange,提问作者Trey Balut
相关产品推荐
相关产品推荐

