C#中能否编写可操作指定类型属性getter/setter的扩展方法
解决方案
C#原生没有直接提供IProperty<T>这类属性抽象的语法,但可以通过以下两种常见方案实现你想要的简化调用效果,避免重复赋值引发的笔误:
方案1:无侵入式封装(不修改原有API)
如果原有Vector、Line的定义无法调整,可以通过委托/表达式树封装属性的读写逻辑,完全通过扩展方法实现需求:
// 通用属性更新扩展 public static void UpdateProp<TObj, TProp>(this TObj obj, Func<TObj, TProp> getter, Action<TObj, TProp> setter, Action<TProp> update) { var val = getter(obj); update(val); setter(obj, val); } // Vector专属操作扩展 public static void IncrX(this Vector v, float delta) => v.x += delta; public static void IncrY(this Vector v, float delta) => v.y += delta;
调用方式如下,不用重复写属性路径:
void MoveStuffAround() { obj.left.top.UpdateProp(o => o.scale, (o,v) => o.scale = v, v => v.IncrX(-1f)); obj.left.bottom.UpdateProp(o => o.pos, (o,v) => o.pos = v, v => v.IncrY(-0.5f)); obj.right.top.UpdateProp(o => o.invScale, (o,v) => o.invScale = v, v => v.IncrX(1f)); obj.right.bottom.UpdateProp(o => o.pos, (o,v) => o.pos = v, v => v.IncrY(0.5f)); }
如果觉得lambda参数冗余,还可以通过表达式树进一步封装,简化为如下调用形式:
obj.left.UpdateProp(o => o.top.scale, v => v.IncrX(-1f));
方案2:ref属性优化(可修改原有API时优先选择)
C# 7.0+支持ref返回属性,C# 7.2+支持ref扩展方法,调整原有API定义后可以完全实现你预期的写法,无额外性能损耗:
class Line { private Vector _start; private Vector _end; // 改为ref返回属性,直接返回字段的引用 public ref Vector start => ref _start; public ref Vector end => ref _end; } // 编写ref扩展方法 public static void MoveX(this ref Vector v, float val) { v.x += val; } public static void MoveY(this ref Vector v, float val) { v.y += val; }
调用效果和你预期的完全一致:
void MoveStuffAround() { obj.left.top.scale.IncrX(-1f); obj.left.bottom.pos.IncrY(-0.5f); obj.right.top.invScale.IncrX(1f); obj.right.bottom.pos.IncrY(0.5f); }
内容的提问来源于stack exchange,提问作者tylerl
相关产品推荐
相关产品推荐

