实现C#泛型四则运算等特化操作

有些情况下我们会对字段做泛型封装,使其支持OnChange、IsDirty等统一的功能扩展,例如:

IObservable<float> hitPoint;

 

而有些字段有挂载修改器的需求,修改器若使用lambda则对序列化不友好,因此考虑自行封装四则运算供修改器

给原始数值进行修改,但C#早期没有四则运算的接口(Interface)。网上的dynamic动态类型做法对多平台也不太好。

(注:使用扩展方法实现的特化,和这类泛型内特化不太一样)

 

不转弱类型的情况下,仍考虑通过接口解决,代码如下:

public interface IArithmeticOperator<T>
{
    public T Add(T x, T y);
    public T Sub(T x, T y);
    public T Mul(T x, T y);
    public T Div(T x, T y);
}

public static class ArithmeticOperator<T>
{
    public static IArithmeticOperator<T> Instance;

    static ArithmeticOperator()
    {
        var type = typeof(T);

        if (type == typeof(int))
            Instance = (IArithmeticOperator<T>)(object)new IntAritOp();
        else if (type == typeof(float))
            Instance = (IArithmeticOperator<T>)(object)new FloatAritOp();
    }
}

public class IntAritOp : IArithmeticOperator<int>
{
    public int Add(int x, int y) => x + y;
    public int Div(int x, int y) => x / y;
    public int Mul(int x, int y) => x * y;
    public int Sub(int x, int y) => x - y;
}

public class FloatAritOp : IArithmeticOperator<float>
{
    public float Add(float x, float y) => x + y;
    public float Div(float x, float y) => x / y;
    public float Mul(float x, float y) => x * y;
    public float Sub(float x, float y) => x - y;
}

public class AttributeModifier<T>
{
    private T _delta;

    public AttributeModifier(T delta) { this._delta = delta; }

    public T Add(T current) => ArithmeticOperator<T>.Instance.Add(current, _delta);
    public T Sub(T current) => ArithmeticOperator<T>.Instance.Sub(current, _delta);
    public T Mul(T current) => ArithmeticOperator<T>.Instance.Mul(current, _delta);
    public T Div(T current) => ArithmeticOperator<T>.Instance.Div(current, _delta);
}

public class Attribute<T>
{
    private T _Value;
    private AttributeModifier<T> _Modifier;


    public Attribute(T value, AttributeModifier<T> modifier)
    {
        _Value = value;
        _Modifier = modifier;
    }

    public T GetValue()
    {
        // 假设都是乘操作,省略逻辑
        return _Modifier.Mul(_Value);
    }
}

public class Test01 : MonoBehaviour
{
    void Start()
    {
        var hp = new Attribute<int>(100, new AttributeModifier<int>(10));
        Debug.Log(hp.GetValue());//1000
        var stamina = new Attribute<float>(25.5f, new AttributeModifier<float>(2f));
        Debug.Log(stamina.GetValue());//51
    }
}

 

 

而如果需要扩展,如属性修改器需要直接在泛型类的基础上支持序列化接口,可以这么写:

#region BinarySerializeOperator
public interface IBinarySerializeOperator<T>
{
    public void Serialize(BinaryWriter writer, T inValue);
    public T Deserialize(BinaryReader reader);
}

public static class BinarySerializeOperator<T>
{
    public static IBinarySerializeOperator<T> Instance;

    static BinarySerializeOperator()
    {
        var type = typeof(T);

        if (type == typeof(int))
            Instance = (IBinarySerializeOperator<T>)(object)new IntBinSeriOp();
        else if (type == typeof(float))
            Instance = (IBinarySerializeOperator<T>)(object)new FloatBinSeriOp();
    }
}

public class IntBinSeriOp : IBinarySerializeOperator<int>
{
    public int Deserialize(BinaryReader reader)
    {
        return reader.ReadInt32();
    }

    public void Serialize(BinaryWriter writer, int inValue)
    {
        writer.Write(inValue);
    }
}

public class FloatBinSeriOp : IBinarySerializeOperator<float>
{
    public float Deserialize(BinaryReader reader)
    {
        return reader.ReadSingle();
    }

    public void Serialize(BinaryWriter writer, float inValue)
    {
        writer.Write(inValue);
    }
}
#endregion


public class AttributeModifier<T>
{
    private T _delta;

    public AttributeModifier(T delta) { this._delta = delta; }

    public T Add(T current) => ArithmeticOperator<T>.Instance.Add(current, _delta);
    public T Sub(T current) => ArithmeticOperator<T>.Instance.Sub(current, _delta);
    public T Mul(T current) => ArithmeticOperator<T>.Instance.Mul(current, _delta);
    public T Div(T current) => ArithmeticOperator<T>.Instance.Div(current, _delta);
    public void Serialize(BinaryWriter writer) => BinarySerializeOperator<T>.Instance.Serialize(writer, _delta);
    public void Deserialize(BinaryReader reader) => _delta = BinarySerializeOperator<T>.Instance.Deserialize(reader);
}

 

posted @ 2025-11-04 00:07  HONT  阅读(13)  评论(0)    收藏  举报