我有一个类如下:
class Student
{
private string name;
private string family;
private string id;
public string[] fields = {"name", "family", "id"};
public Student(string name,string family,string id)
{
this.name = name;
this.family = family;
this.id = id;
}
}
现在,在另一个类中,我想循环遍历fields
数组中定义的成员。这是我的代码,不工作
class StudentController
{
Student student;
public StudentController(Student st)
{
this.student = st;
}
public void store()
{
foreach(string f in this.student.fields)
Console.WriteLine(this.student.f);
}
}
字段名称不是字段值的替代,因此this.student.f
引用了Student
对象中不存在的名为f
的字段或属性,从而导致错误。
根据你的口味,有多种方法可以解决这个问题。例如,您可以使用反射来获取字段的值(链接中的答案是关于属性的;您可以调整它以使用字段,或者切换到属性,这是一种更像C#的方式(。一个额外的好处是,除非你愿意,否则你不再需要定义所有字段的列表,因为C#可以免费获得所有字段。
或者,您可以定义Func<Student,string>
的集合,其中函数访问特定字段:
public Dictionary<string,Func<Student,string>> fields = {
["name"] = s => s.name
, ["family"] = s => s.family
, ["id"] = s => s.id
};
现在,您可以在fields
上进行迭代,并在进行时打印名称和值:
foreach(string p in student.fields)
Console.WriteLine("{0} = {1}", p.Key, p.Value(student));
通常使用反射来解决这类任务。反射api系统允许您检查Type(在本例中是Student的实例(,并询问其属性和与之相关的方法。其优点是,您不需要字符串的公共字段数组,如果添加新成员,遍历属性的代码也不会更改。缺点是使用反射会对性能产生相对影响(但要真正担心的是,您应该始终在真实环境中进行测试(
但是,您也可以实现一个简单的替代方案,创建自己版本的ToString方法。
例如,将您的学生类扩展为
public class Student
{
private string name;
private string family;
private string id;
public string[] fields = { "name", "family", "id", "all" };
public Student(string name, string family, string id)
{
this.name = name;
this.family = family;
this.id = id;
}
public string ToString(string field)
{
switch (field)
{
case "name":
return this.name;
case "family":
return this.family;
case "id":
return this.id;
case "all":
default:
return $"{name}, {family}, {id}";
}
}
}
现在您可以使用在字段上循环
Student t = new Student("John", "McEnroe", "134");
foreach(string s in t.fields)
Console.WriteLine(t.ToString(s));
或者仅针对具有的单个字段
Console.WriteLine(t.ToString("name"));
如果您试图访问中的值
public string[] fields = {"name", "family", "id"};
然后改一下:
foreach(string f in this.student.fields)
Console.WriteLine(this.student.f);
对此:
foreach(string f in this.student.fields)
Console.WriteLine(f);
您试图访问变量f
,就像它是StudentController
的成员一样。
但是,如果您试图访问传递给Student
构造函数的name
、family
和id
的值,请将这些字段转换为以下属性:
public string Name { get; set; }
public string Family { get; set; }
public string Id { get; set; }
并使用以下代码访问它们:
foreach(var property in typeof(Student).GetProperties()) {
var propValue = property.GetValue(student);
Console.WriteLine(propValue);
}
如果您只从Student
类设置这些属性,那么您可以这样做:
public string Name { get; }
或者这个:
public string Name { get; private set; }