【发布时间】:2011-02-01 13:23:58
【问题描述】:
我有一个包含大量相似字段(比如超过 10 个)的对象,我必须从可变长度的数组中为它们分配值。解决方案可能是基于每次检查数组长度并分配每个字段的大量嵌套 ifs
或
一个 ifs 链检查长度是否超出范围,并在检查后每次分配。
两者似乎都是重复的。有更好的解决方案吗?
【问题讨论】:
标签: refactoring
我有一个包含大量相似字段(比如超过 10 个)的对象,我必须从可变长度的数组中为它们分配值。解决方案可能是基于每次检查数组长度并分配每个字段的大量嵌套 ifs
或
一个 ifs 链检查长度是否超出范围,并在检查后每次分配。
两者似乎都是重复的。有更好的解决方案吗?
【问题讨论】:
标签: refactoring
如果你的语言有 switch/case 和 fallthrough,你可以这样做:
switch(array.length){
case 15: field14 = array[14];
case 14: field13 = array[13];
case 13: field12 = array[12];
// etc.
case 1: field0 = array[0];
case 0: break;
default: throw Exception("array too long!");
}
【讨论】:
for (int i = 0; i < fieldCount; i++)
fields[i].value = array[i];
也就是说,维护一个与你的值数组对应的字段数组。
【讨论】:
value 属性的特殊类型并使它们可索引(并且安全)正是他试图解决的问题,只是重新定义为更复杂的东西。
如果您的语言支持委托、匿名函数等,您可以使用它们来清理它。例如,在 C# 中你可以这样写:
string[] values = GetValues();
SomeObject result = new SomeObject();
Apply(values, 0, v => result.ID = v);
Apply(values, 1, v => result.FirstName = v);
Apply(values, 2, v => result.LastName = v);
// etc.
apply 方法如下所示:
void Apply(string[] values, int index, Action<string> action)
{
if (index < values.Length)
action(values[index]);
}
这显然取决于语言,但无论如何都需要考虑。
另一个我们可能会忽略的非常简单的选项是,如果您实际上尝试从这个值数组中初始化一个对象(而不是更新一个现有对象) , 如果数组不够大,只接受默认值。
C# 示例:
void CreateMyObject(object[] values)
{
MyObject o = new MyObject();
o.ID = GetValueOrDefault<int>(values, 0);
o.FirstName = GetValueOrDefault<string>(values, 0);
o.LastName = GetValueOrDefault<string>(values, 0);
// etc.
}
void GetValueOrDefault<T>(object[] values, int index)
{
if (index < values.Length)
return (T)values[index];
return default(T);
}
有时愚蠢的解决方案是最明智的选择。
【讨论】:
如果您的字段以数组元素的相同顺序声明,您可以使用反射(如果在您的语言中可用)来设置这些值。这是一个如何在 Java 中执行此操作的示例:
// obj is your object, values is the array of values
Field[] fields = obj.getClass().getFields();
for (int i = 0; i < fields.length && i < values.length; ++i) {
fields[i].set(obj, values[i]);
}
【讨论】: