在 C# 中使用重载运算符的方式定义显示/隐式类型转换

momo314相同方式共享非商业用途署名转载

 先看 demo,假设有一个 ItemId 类型,由两个 byte 类型的字段组成。该类型在程序外部存储或显示时,会以4到6位数字形式展示:其中最后三位为第二个 byte 的值,不足3位则以0填充;前1至3位则显示为第一个 byte 的值。

以下代码实现了 ItemId 类型与 int 类型的隐式转换(如果要实现显示类型转换,则将关键字 implicit 替换为 explicit 即可)。


// 隐式转换
ItemId itemId = 1006;
int id = itemId;

// 显式转换
ItemId itemId = (ItemId)101123;
int id = (int)itemId;

个人理解,实现了隐式转换implicit之后就没有必要实现显式转换explicit了,这种情况下即使使用显示转换的语法来写,也能正常转换成功,因为此时的显式转换会被认为时一次非必要的转换


/// <summary>
/// 道具Id
/// </summary>
public readonly struct ItemId
{
    /// <summary>
    /// 道具类型
    /// </summary>
    public byte Type { get; init; }

    /// <summary>
    /// 道具在类型中的唯一Id
    /// </summary>
    public byte TypeId { get; init; }

    public ItemId(byte type, byte typeId)
    {
        Type = type;
        TypeId = typeId;
    }

    public override string ToString()
    {
        return $"{Type}{TypeId.ToString().PadLeft(3, '0')}";
    }

    public static implicit operator ItemId(int itemId)
    {
        _ = TryParse(itemId, out var id);
        return id;
    }

    public static implicit operator int(ItemId itemId)
    {
        return itemId.Type * 1000 + itemId.TypeId;
    }

    public static bool TryParse(int val, out ItemId itemId)
    {
        if (val < 1001)
        {
            itemId = new ItemId(0, 0);
            return false;
        }

        if (val > 255255)
        {
            itemId = new ItemId(0, 0);
            return false;
        }

        var type = val / 1000;
        var typeId = val % 1000;

        if (type > byte.MaxValue || typeId > byte.MaxValue)
        {
            itemId = new ItemId(0, 0);
            return false;
        }

        itemId = new ItemId((byte)type, (byte)typeId);
        return true;
    }
}
✎﹏ 本文来自于 momo314和他们家的猫,文章原创,转载请注明作者并保留原文链接。