Define "custom" integer-based type?
I have a program that is interfacing with an external library that, among other thing开发者_如何学Gos, has an unsigned 12-bit value packed in a larger struct.
This used to be 8 bits, so we simply marshaled it as a byte.
Now that it's 12 bits... I can use a ushort, but that opens up issues of (a) range checking and (b) marshaling.
Is there a simple way of implementing a constrained numeric type like this, where I don't have to override every assignment and comparison method?
Try this (this example shows a custom Int64 type)
public class MyCustomInt64 : CustomValueType<MyCustomInt64, Int64>
{
private MyCustomInt64(long value) : base(value) {}
public static implicit operator MyCustomInt64(long value) { return new MyCustomInt64(value); }
public static implicit operator long(MyCustomInt64 custom) { return custom._value; }
}
Implement what you like in the constructor to apply constriants.
Usage
MyCustomInt64 myInt = 27; //use as like any other value type
And here is the reusable base custom value type (add more operators if needed)
public class CustomValueType<TCustom, TValue>
{
protected readonly TValue _value;
public CustomValueType(TValue value)
{
_value = value;
}
public override string ToString()
{
return _value.ToString();
}
public static bool operator <(CustomValueType<TCustom, TValue> a, CustomValueType<TCustom, TValue> b)
{
return Comparer<TValue>.Default.Compare(a._value, b._value) < 0;
}
public static bool operator >(CustomValueType<TCustom, TValue> a, CustomValueType<TCustom, TValue> b)
{
return !(a < b);
}
public static bool operator <=(CustomValueType<TCustom, TValue> a, CustomValueType<TCustom, TValue> b)
{
return (a < b) || (a == b);
}
public static bool operator >=(CustomValueType<TCustom, TValue> a, CustomValueType<TCustom, TValue> b)
{
return (a > b) || (a == b);
}
public static bool operator ==(CustomValueType<TCustom, TValue> a, CustomValueType<TCustom, TValue> b)
{
return a.Equals((object)b);
}
public static bool operator !=(CustomValueType<TCustom, TValue> a, CustomValueType<TCustom, TValue> b)
{
return !(a == b);
}
public static TCustom operator +(CustomValueType<TCustom, TValue> a, CustomValueType<TCustom, TValue> b)
{
return (dynamic) a._value + b._value;
}
public static TCustom operator -(CustomValueType<TCustom, TValue> a, CustomValueType<TCustom, TValue> b)
{
return ((dynamic) a._value - b._value);
}
protected bool Equals(CustomValueType<TCustom, TValue> other)
{
return EqualityComparer<TValue>.Default.Equals(_value, other._value);
}
public override bool Equals(object obj)
{
if (ReferenceEquals(null, obj)) return false;
if (ReferenceEquals(this, obj)) return true;
if (obj.GetType() != this.GetType()) return false;
return Equals((CustomValueType<TCustom, TValue>)obj);
}
public override int GetHashCode()
{
return EqualityComparer<TValue>.Default.GetHashCode(_value);
}
}
You should create a struct that overrides the implicit conversion operator:
struct PackedValue {
private PackedValue(ushort val) {
if(val >= (1<<12)) throw new ArgumentOutOfRangeException("val");
this._value = val;
}
private ushort _value;
public static explicit operator PackedValue(ushort value) {
return new PackedValue(value);
}
public static implicit operator ushort(PackedValue me) {
return me._value;
}
}
精彩评论