You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.26 16:15:07