當前位置: 妍妍網 > 碼農

【C#點點滴滴】Deconstruct解構

2024-01-30碼農

建構函式,是在初始化物件時,把數據傳給物件。那Deconstruct正好相反,是從物件中把想要的數據返回。

下面看一個使用場景,下面是定義一個record的Order,我們可以用後設資料的方式,從Order物件中把no,orderTime取出來,這是怎麽做到的呢?

//Order定義成recordrecord Order(string No, DateTime OrderTime, string Address);//使用Ordervar (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#知識又增加了一點。