在 C# 中使用重载运算符的方式定义显示/隐式类型转换
先看 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;
}
}