实现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); }
浙公网安备 33010602011771号