我的程序中有一个情况,我有大约20个字段。所有这些都是字符串。现在我还有一个大小为20的字符串数组。我想从存储在该数组中的字符串中依次初始化这些字段。我不想这样做:
field1 = array [0];
field2 = array [1];
...
field20 = array [19];
所以我写了一个这样的测试程序,但它不能用于字符串。它只适用于引用类型。有没有办法做到这一点?
public class Program
{
private string name;
private string id;
private void Func()
{
var array = new[] {name, id};
for (int i = 0; i < array.Length; i++)
{
array[i] = "some string";
}
}
public static void Main(string[] args)
{
var p = new Program();
p.Func();
Console.WriteLine(p.name); // prints null
}
}
答案 0 :(得分:3)
关于行为的假设是不正确的。
// Create a NEW array with the specified expressions which are evaluated
// immediately (to the current values of the fields)..
var array = new[] {name, id};
// Meaning it is equivalent to this .. note that the field names have
// NOTHING to do with the array object itself.
var array = new[] {(string)null, (string)null};
// Then for each item in the array, assign it a value
// (replacing what was already there anyway)
for (int i = 0; i < array.Length; i++) {
array[i] = "some string";
}
最后我们得到一个看起来像["some string", "some string"]
的数组。同样,字段没有“连接”。这个问题与引用类型无关(而且字符串也是引用类型)。
最好的(通常是正确的)方式是诚实地以不同的方式做到这一点。虽然可以包装字段访问/设置器并且始终存在反射..如果真正需要动态名称,则应该使用字典或类似字典
这是一种使用代理来包装赋值操作的方法。此示例使用操作和"Statement Lambda" syntax。
var setters = new Dictionary<string, Action<Program, string>>() {
{ "name", (p, value) => p.name = value },
{ "id", (p, value) => p.id = value },
};
// For each field setter, assign a value (could use the name as a look-up)
foreach (var setter in setters.Values) {
setter(this, "some string");
}
这是有效的,因为setter(..)
会调用之前定义的实际分配给相应成员的操作。使用这样的查找/代理(使用动作,函数或更复杂的类型)对于某些情况是一种有效的方法,但在不需要时应该避免使用。
此 也可以Reflection完成。
var t = this.GetType();
var fieldNames = new [] { "name", "id" };
var bindingFlags = BindingFlags.NonPublic | BindingFlags.Instance;
foreach (var name in fieldNames) {
var fieldInfo = t.GetField(name, bindingFlags);
fieldInfo.SetValue(this, "some string");
}
反思通常应该是“最后的手段”。它会丢失静态类型信息,将许多错误推迟到运行时,并且会带来性能损失(授予,可能无关紧要)。有一些非常漂亮的东西可以做(特别是当表达和注释也被使用时)..但反射是最好的魔法,直到真正需要它。
答案 1 :(得分:2)
看看这是否是你想要实现的目标:
public class Program
{
private string name;
private string id;
private Dictionary<string, int> mapper = new Dictionary<string, int>();
private String[] array= null;
public Program()
{
mapper.Add("name", 1);
mapper.Add("id", 2);
}
public string Name
{
get { return array[mapper["name"]]; }
}
public string Id
{
get { return array[mapper["id"]]; }
}
private void Func()
{
array = new[] { name, id };
for (int i = 0; i < array.Length; i++)
{
array[i] = "some string";
}
}
public static void Main(string[] args)
{
var p = new Program();
p.Func();
Console.WriteLine(p.name); // prints null
}
}