【问题标题】:Define "custom" integer-based type?定义“自定义”基于整数的类型?
【发布时间】:2011-09-30 19:24:56
【问题描述】:

我有一个与外部库交互的程序,除其他外,该库将一个无符号 12 位值打包在一个更大的结构中。

这曾经是 8 位,所以我们只是将其编组为一个字节。

现在它是 12 位...我可以使用 ushort,但这会引发 (a) 范围检查和 (b) 封送处理的问题。

有没有一种简单的方法来实现像这样的受约束的数字类型,我不必重写每个赋值和比较方法?

【问题讨论】:

  • 你能在编组点检查范围吗?
  • 很遗憾没有;这些的 c# 方面也可能会创建它们,因此代码的其他部分正在为该成员分配值。
  • 为什么这很重要?在分配时提出异常是否至关重要?如果是这样,那么您显然需要编写一个包装类或结构。
  • 嗯,是的。我只是希望有一个简单的包装器可以作为整数类型的数据类型替换而无需覆盖每个运算符等。

标签: c#


【解决方案1】:

试试这个(这个例子展示了一个自定义的 Int64 类型)

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; }
}

在构造函数中实现您喜欢的内容以应用约束。

用法

MyCustomInt64 myInt = 27; //use as like any other value type

这是可重用的基本自定义值类型(如果需要,可以添加更多运算符)

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);
    }
}

【讨论】:

  • 这太棒了!就像找到一个隐藏的宝藏,非常好的东西!
  • 我还没有完整阅读它,但是你处理通用可重用解决方案的方式是黄金 - 只是想到它
  • 既然你已经走到这一步了——你可以用全局静态可分配逻辑(委托)更进一步——我正计划做这样的事情,它会与你的解决方案完美融合
  • 但要让所有这些结构式 - 因为我们想要值类型性质
  • 这太棒了!我还没有测试它。我也在考虑将其转换为结构。为您提供一个互联网 cookie。
【解决方案2】:

您应该创建一个覆盖隐式转换运算符的结构:

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;
    }
}

【讨论】:

  • 谢谢,这两个运算符正是我要找的。​​span>
  • 我认为您的意思是 if (val &gt;= 1 &lt;&lt; 12) ... 2 &lt;&lt; 12 等于 2 * 2 ^ 122 ^ 13
  • 在我的情况下,这就像一个类一样工作。对于结构,我必须为构造函数添加“:this()”。
  • @mikiqex:我删除了自动属性,因为它的支持字段导致了您看到的编译错误,并且没有必要解决问题。
猜你喜欢
  • 2012-03-19
  • 2014-04-12
  • 1970-01-01
  • 1970-01-01
  • 2020-10-22
  • 2021-03-26
  • 1970-01-01
  • 2023-04-03
  • 2021-01-25
相关资源
最近更新 更多