建構函式,是在初始化物件時,把數據傳給物件。那Deconstruct正好相反,是從物件中把想要的數據返回。
下面看一個使用場景,下面是定義一個record的Order,我們可以用後設資料的方式,從Order物件中把no,orderTime取出來,這是怎麽做到的呢?
//Order定義成record
record Order(string No, DateTime OrderTime, string Address);
//使用Order
var (no, orderTime, _) = new Order("T000001", DateTime.Now, "北京市海澱區");
Console.WriteLine(no);
Console.WriteLine(orderTime);
其實實作很簡單,只要在類內部定義一個Deconstruct的方法就可以了,下面是另一個Order為 class的例項。除了基本的內容,還實作了一個Deconstruct,參數是兩個out的參數,這個方法只返回No和經過簡化的Goods的ID集合。這裏只是給出一個例子,對於想把什麽數據解構出來,以什麽形式解構出來,可以根據自己的需要。同時Deconstruct可以有多載,但是,參數一樣時,函式就有二義性了。【其確我覺得可以透過(string no,List<int> goodsIds)來解決二義性,但現在不好用】
classOrder
{
publicOrder(string no, DateTime orderTime, string address)
{
No = no;
OrderTime = orderTime;
Address = address;
}
publicstring No { get; set; }
public DateTime OrderTime { get; set; }
publicstring Address { get; set; }
public List<Goods> Goodses { get; set; } = new List<Goods>();
publicvoidDeconstruct(outstring no, out List<int> goodsIds)
{
no = No;
goodsIds = Goodses.Select(a => a.ID).ToList();
}
publicvoidDeconstruct(outstring no, out DateTime orderTime)
{
no = No;
orderTime = OrderTime;
}
}
var (no, goodsIds) = new Order("T000001", DateTime.Now, "北京市海澱區")
{
Goodses = new List<Goods>
{
new Goods { ID = 1, Name = "商品A", Price = 10m },
new Goods { ID = 2, Name = "商品B", Price = 15m },
}
};
Console.WriteLine($"OrderNo:{no}");
foreach (var goodsId in goodsIds)
{
Console.WriteLine($" GoodsId:{goodsId}");
}
另外,Deconstruct可以透過擴充套件的方式,給一些型別增加解構功能,下面是對Exception的解構,取出Message和InnerException,當然這只是一個Demo,只提供了一條路子,具體套用可以靈活定義。
static classExceptionExtensions
{
publicstatic void Deconstruct(this Exception? exception, out string? message, out Exception? innerException)
{
message = exception?.Message;
innerException = exception?.InnerException;
}
publicstatic void Deconstruct(this Exception? exception, out string? message, out string? innerMessage, out Exception? innerInnerException)
{
message = exception?.Message;
innerMessage = exception?.InnerException?.Message;
innerInnerException = exception?.InnerException?.InnerException;
}
}
try
{
thrownewException("1級錯誤", newException("2級錯誤"));
}
catch (Exception exc)
{
var (msg, (innerMsg, _)) = exc;
Console.WriteLine(msg);
Console.WriteLine(innerMsg);
}
奇奇怪怪的C#知識又增加了一點。