我在C#中寻找一种紧凑的方式来实现这个结构:
FlurryEventRecordStatus.kFlurryEventFailed
该类几乎是一个固定的字段集合,它们共享相同的类型,具有不同的默认参数,并且必须单独访问(通过public class Test {
public enum Field {
A, B, C, D, E...
}
public int a = 0;
public int b = 0;
public int c = 0;
public int d = 0;
public int e = 0; //....
public int this[Field field] {
set{
switch(field) {
case(Field.A):
a = value;
break;
case(Field.B):
b = value;
break;
...
}
}
get{
switch(field) {
case(Field.A):
return a;
case(Field.B):
return b;
...
}
}
}
}
)AND通过索引器。
这将被称为很多,所以反思可能不是一个选项
在C ++中,我可以为这种事做一个宏,但C#没有。
如何在不写重复文字的情况下实现这一目标?
答案 0 :(得分:4)
你所拥有的CPU使用效率非常高,因此很难被击败。如果您希望在语法方面获得一些效率,可以切换您的设计 - 将数据存储在数组中以方便通过enum
访问,并使用属性为外部用户提供漂亮的名称:
public class Test {
public enum Field {
A, B, C, D, E..., X, Y, Z
}
private readonly int[] data = new int[(int)(Field.Z + 1)];
public int A {
get {
return data[Field.A];
}
set {
data[Field.A] = value;
}
}
//...
public int Z {
get {
return data[Field.Z];
}
set {
data[Field.Z] = value;
}
}
public int this[Field field] {
set{
data[field] = value;
}
get{
return data[field];
}
}
}
这种方法有很多代码重复。您可以完全避免使用以下构建重量级设置代码的代价:
class Program {
public enum Field { A, B, C };
public int a, b, c;
private static readonly Func<Program,int>[] Getter= new Func<Program,int>[3];
private static readonly Action<Program,int>[] Setter= new Action<Program,int>[3];
public int this[Field f] {
get {
return Getter[(int)f](this);
}
set {
Setter[(int) f](this, value);
}
}
static Program() {
var names = Enum.GetNames(typeof(Field));
var pThis = Expression.Parameter(typeof(Program), "pThis");
var pVal = Expression.Parameter(typeof(int), "pVal");
for (var i = 0 ; i != names.Length ; i++) {
var f = Expression.Field(pThis, names[i].ToLower());
Getter[i] = Expression.Lambda<Func<Program, int>>(f, pThis).Compile();
var a = Expression.Assign(f, pVal);
Setter[i] = Expression.Lambda<Action<Program,int>>(a, pThis, pVal).Compile();
}
}
public override string ToString() {
return string.Format("a={0} b={1} c={2}", a, b, c);
}
private static void Main(string[] args) {
var p = new Program();
p.a = 123;
p.b = 456;
p.c = 789;
Console.WriteLine(p);
p[Field.A] = 234;
p[Field.B] = 567;
p[Field.C] = 890;
Console.WriteLine(p);
Console.WriteLine(p[Field.A]);
Console.WriteLine(p[Field.B]);
Console.WriteLine(p[Field.C]);
}
}
此方法在静态构造函数中构建和编译getter和setter,确保反射仅使用一次。请注意,此方法依赖于enum
的小写名称对应于字段名称的约定。如果不是这种情况,请替换此行
Expression.Field(pThis, names[i].ToLower());
使用其他方式从enum
名称中获取字段名称。此代码还假定enum
值是连续的,并从零开始。