主頁 > .NET開發 > C#8.0 新增功能

C#8.0 新增功能

2020-09-24 05:13:19 .NET開發

1、Readonly成員

  可將readonly修飾符應用于結構的任何成員,它指示該成員不會修改狀態,這比將readonly修飾符應用于struct宣告更精細,

public struct Point
{
    public double X { get; set; }

    public double Y { get; set; }

    public double Distance => Math.Sqrt(X * X + Y * Y);

    public override string ToString() => $"({X}, {Y}) is {Distance} from the origin";
}

像大多數結構一樣ToString()方法不會修改狀態,可以通過readonly修飾符添加到ToString()的宣告來對此進行指示:

public readonly override string ToString() => $"({X}, {Y}) is {Distance} from the origin";

上述更改會發生編譯器警告,因為ToString訪問Distance屬性,該屬性未標記為readonly,如下圖所示:

 

 需要創建防御性副本時,編譯器會發出警告,Distance屬性不會更改狀態,因此可以通過將readonly修飾符添加到宣告來修復此警告:

public readonly double Distance => Math.Sqrt(X * X + Y * Y);

請注意,readonly修飾符對于只讀屬性是必須的,編譯器不會假設get訪問器不修改狀態;必須明確宣告readonly,編譯器會強制實施以下規則:

  readonly成員不修改狀態,除非readonly修飾符,否則不會編譯以下方法:

public readonly void Translate(int xOffset,int yOffset)
{
    X += xOffset;
    Y += yOffset;
}

 通過此功能,可以指定設計意圖,使編譯器可以強制執行該意圖,并基于該意圖進行優化,

2、默認介面成員

 現在可以將成員添加到介面,并未這些成員提供實作,借助次語言功能,API坐著可以將方法添加到以后版本的介面中,而不會破壞與該介面當前實作的源或耳機中南海檔案兼容性,現在有的實作繼承默認介面,此功能使C#與面向Android 或Swift的API進行互操作,此類API支持類似功能,默認介面成員還支持類似于“特征”語言功能的方案,

默認介面成員會影響很多方案和語言元素,https://docs.microsoft.com/zh-cn/dotnet/csharp/tutorials/default-interface-methods-versions

3、在更多位置中使用更多模式

模式匹配提供了在相關但不同型別的資料中提供形狀相關功能的工具,C#7.0通過使用is運算式和switch陳述句引入了型別模式和常量模式的語法,這些功能代表了支持資料和功能分離時的編程范例的初步嘗試,隨著行業轉向更多微服務和其他基于云的體系結構,還需要其他語言功能,

C#8.0擴展了此詞匯表,這樣就可以在代碼中的更多位置使用更多模式運算式,當資料和功能分離時,請考慮使用這些功能,當演算法依賴于物件運行時型別以外的事實時,請考慮使用模式匹配,這些技術提供了另一種表達設計的方式,

除了烤魚在新位置使用新模式之外,C#8.0還添加了“遞回模式”,任何模式運算式的結果都是一個運算式,遞回模式只是應用于另外一個模式運算式輸出的模式運算式,

switch運算式

通常情況下,switch陳述句在其每個case塊中生成一個值,借助Switch運算式,可以使用更簡潔的運算式陳述句,只是些許重復的case和break關鍵欄位大括號,以下面列出彩虹顏色的列舉為例:

public enum Rainbow
{
    Red,
    Orange,
    Yellow,
    Green,
    Blue,
    Indigo,
    Violet
}

如果應用定義了通過R、G、B組件構造而成的RGBColor型別,可使用以下包含switch運算式的方法,將Rainbow轉換為RGB值:

public static RGBColor FromRainbow(Rainbow colorBand) =>
colorBand switch
{
    Rainbow.Red => new RGBColor(0xFF, 0x00, 0x00),
    Rainbow.Orange => new RGBColor(0xFF, 0x7F, 0x00),
    Rainbow.Yellow => new RGBColor(0xFF, 0xFF, 0x00),
    Rainbow.Green => new RGBColor(0x00, 0xFF, 0x00),
    Rainbow.Blue => new RGBColor(0x00, 0x00, 0xFF),
    Rainbow.Indigo => new RGBColor(0x4B, 0x00, 0x82),
    Rainbow.Violet => new RGBColor(0x94, 0x00, 0xD3),
    _ => throw new ArgumentException(message: "invalid enum value", paramName: nameof(colorBand)),
};

這里有幾個語法改進:

  1、變數位于switch關鍵字之前,不同的順序使得在視覺上可以很輕松的區分switch運算式和switch陳述句,

  2、將case和:元素替換為=>,它更簡潔,更直觀,

  3、將default事例替換為_棄元,

  4、正文是運算式,不是陳述句,

將其與使用經典switch陳述句的等效代碼進行對比:

public static RGBColor FromRainbowClassic(Rainbow colorBand)
{
    switch (colorBand)
    {
        case Rainbow.Red:
            return new RGBColor(0xFF, 0x00, 0x00);
        case Rainbow.Orange:
            return new RGBColor(0xFF, 0x7F, 0x00);
        case Rainbow.Yellow:
            return new RGBColor(0xFF, 0xFF, 0x00);
        case Rainbow.Green:
            return new RGBColor(0x00, 0xFF, 0x00);
        case Rainbow.Blue:
            return new RGBColor(0x00, 0x00, 0xFF);
        case Rainbow.Indigo:
            return new RGBColor(0x4B, 0x00, 0x82);
        case Rainbow.Violet:
            return new RGBColor(0x94, 0x00, 0xD3);
        default:
            throw new ArgumentException(message: "invalid enum value", paramName: nameof(colorBand));
    };
}

屬性模式:

借助屬性模式,可以匹配所有檢查的物件的屬性,請看一個電子商務網站的事例額,該網站必須根據買家地址計算銷售稅,這種計算不時Address類的核心職責,它會隨時間變化,可能比地址格式的更改更頻繁,銷售稅的金額取決于地址的State屬性,下面的方法使用屬性模式從地址和價格計算銷售稅:

public static decimal ComputeSalesTax(Address location, decimal salePrice) =>
    location switch
    {
        { State: "WA" } => salePrice * 0.06M,
        { State: "MN" } => salePrice * 0.75M,
        { State: "MI" } => salePrice * 0.05M,
        // other cases removed for brevity...
        _ => 0M
    };

 模式匹配為表達此演算法創建了簡介的語法

元素模式:

一些演算法依賴于多個輸入,使用元組模式,可以根據表示為元組的多個值進行,以下代碼顯示了游戲“rock,pack,scissors(石頭剪刀布)”的切換運算式

 public static string RockPaperScissors(string first, string second)
    => (first, second) switch
    {
        ("rock", "paper") => "rock is covered by paper. Paper wins.",
        ("rock", "scissors") => "rock breaks scissors. Rock wins.",
        ("paper", "rock") => "paper covers rock. Paper wins.",
        ("paper", "scissors") => "paper is cut by scissors. Scissors wins.",
        ("scissors", "rock") => "scissors is broken by rock. Rock wins.",
        ("scissors", "paper") => "scissors cuts paper. Scissors wins.",
        (_, _) => "tie"
    };

訊息顯示獲勝者,棄元表示平局(石頭剪刀布游戲)的三種組合或其他文本輸入,

位置模式

某些型別包含Deconstruct方法,就可以使用位置模式,該方法將其屬性解構為離散變數,如果可以訪問Deconstruct方法,就可以使用位置模式檢查物件的屬性并將這些屬性用于模式,考慮以下Point類,其中包含用于為X和Y創建離散變數的Deconstruct方法:

public class Point
{
    public int X { get; set; }

    public int Y { get; set; }

    public Point(int x, int y) => (X, Y) = (x, y);

    public void Deconstruct(out int x, out int y) => (x, y) = (X, Y);
}

此外,請考慮以下表示象限的各種位置的列舉:

 public enum Quadrant
 {
     Unknown,
     Origin,
     One,
     Two,
     Three,
     Four,
     OnBorder
 }

下面的方法使用位置模式來提取x和y的值,然后,它使用when自居來確定改點的Quadrant:

static Quadrant GetQuadrant(Point point) => point switch
{
    (0, 0) => Quadrant.Origin,
    var (x, y) when x > 0 && y > 0 => Quadrant.One,
    var (x, y) when x < 0 && y > 0 => Quadrant.Two,
    var (x, y) when x < 0 && y < 0 => Quadrant.Three,
    var (x, y) when x > 0 && y < 0 => Quadrant.Four,
    var (_, _) => Quadrant.OnBorder,
    _ => Quadrant.Unknown
};

當x或y為0(但不是兩者同時為0)時,前一個開關中的棄元模式匹配,switch運算式必須要么生成值,要么引發例外,如果這些情況都不匹配,則switch運算式將引發例外,如果沒有switch運算式中涵蓋所有可能的情況,編譯器將生成一個警告,

可以在模式匹配高級教程中探索模式匹配方法,https://docs.microsoft.com/zh-cn/dotnet/csharp/tutorials/pattern-matching

4、using宣告

using宣告是前面帶using關鍵字的變數宣告,它指示編譯器宣告的變數應該在封閉范圍的末尾進行處理,以下面撰寫文本檔案的代碼為例:

static void WriteLinesToFile(IEnumerable<string> lines)
{
    using var file = new System.IO.StreamWriter("WriteLines2.txt");
    foreach (var line in lines)
    {
        //如果該行不包含單詞“Second”,則將該行寫入檔案
        if (!line.Contains("Second"))
        {
            file.WriteLine(line);
        }
    }
    //檔案已在此處釋放
}

在前面的示例中,當到達方法的右括號時,將對該檔案進行處理,這是宣告file的范圍的末尾,前面的代碼相當于下面使用經典using 陳述句的代碼:

static void WriteLinesToFile(IEnumerable<string> lines)
{
    using (var file=new System.IO.StreamWriter("WriteLines2.txt"))
    {
        foreach (var line in lines)
        {
            //如果該行不包含單詞“Second”,則將該行寫入檔案
            if (!line.Contains("Second"))
            {
                file.WriteLine(line);
            }
        }
    }//檔案已在此處被釋放
}

在前面的示例中,當到達與using陳述句關聯的右括號時,將對該檔案進行處理,在這兩種情況下,編譯器將生成對Dispose()的呼叫,如果using陳述句中的運算式不可處置,編譯器將生成一個錯誤,

5、靜態本地函式

現在可以向本地函式添加static修飾符,以確保本地函式不會從封閉范圍捕獲(參考)任何變數,這樣做會生成CS8421,“靜態本地函式不能包含對<variable>的參考”,

考慮下列代碼,本地函式LocalFunction訪問在封閉范圍(方法M)中宣告的變數y,因此,不能用static修飾符來宣告LocalFunction:

int M()
{
    int y;
    LocalFunction();
    return y;

    void LocalFunction() => y = 0;
}

如果在LocalFunction方法前面加上static:

 

 

 

下面的代碼包含一個靜態本地函式,它可以是靜態的,因為它不訪問封閉范圍中的熱呢變數:

 int M()
 {
     int y = 5;
     int x = 7;
     return Add(x, y);

     static int Add(int left, int right) => left + right;
 }

6、可處置的ref結構

用ref修飾符宣告的struct可能無法實作任何借口,因此無法實作IDisposable,因此,要能夠處理ref struct,它必須有一個可訪問的void Dispose()方法,這同樣適用于readonly ref struct宣告,

7、可謂空參考型別

在可謂空注釋背景關系中,參考型別的任何變數都被視為不可謂空參考型別,若要指示一個變數可能為null,必須在型別名稱后面附加?,以將該變數宣告為可謂空參考型別,

如果,不用?來宣告,傳統代碼中,這樣寫,會報錯:

static void Main(string[] args)
{
    List<string> list = null;
    var newList = list.Where(s => s.Length > 2) ?? new List<string>();
    foreach (var item in newList)
    {
        Console.WriteLine(item);
    }
    Console.WriteLine("ok");
    Console.ReadLine();
}

 

 

 

改進之后,就沒問題了:

static void Main(string[] args)
{
    List<string> list = null;
    var newList = list?.Where(s => s.Length > 2) ?? new List<string>();
    foreach (var item in newList)
    {
        Console.WriteLine(item);
    }
    Console.WriteLine("ok");
    Console.ReadLine();
}

 

 

 

 對于不可為空參考型別,編譯器使用流分析來確保在宣告時將本地變數初始化為非Null值,欄位必須在構造程序中初始化,如果沒有通過呼叫任何可用的建構式或通過初始化運算式來設定變數,編譯器將生成警告,此外,不能向不可為空參考型別分配一個可以為Null的值,

不對可為空參考型別進行檢查以確保他們沒有被賦予Null值或初始化為Null,不過,編譯器使用流分析來確保可為空參考型別的任何變數在被訪問或分配給不可為空參考型別之前,都會對其Null性進行檢查,

8、異步流

從C#8.0開始,可以創建并以異步方式使用流,回傳異步流的方法有三個屬性:

  1、它是用async修飾符宣告的

  2、它將回傳IAsyncEnumerable<T>

  3、該方法包含用于在異步流中回傳連續元素的yield return 陳述句

使用異步流需要在列舉流元素時在foreach關鍵字前面添加await關鍵字,談價await關鍵字需要列舉異步流的方法,以使用async修飾符進行宣告并回傳async方法允許的型別,通常在意味著回傳Task或Task<TResult>,也可以為ValueTask或ValueTask<TResult>,方法既可以使用異步流,也可以生成異步流,這意味著它將回傳IAsyncEnumerable<T>,下面的代碼生成一個從0到10的序列,在生成沒個數字之間等待100毫秒:

public static async System.Collections.Generic.IAsyncEnumerable<int> GenerateSequence()
{
    for (int i = 0; i < 20; i++)
    {
        await Task.Delay(100);
        yield return i;
    }
}

可以使用await foreach陳述句來列舉序列:

 public static async void TestGenerateSequence()
 {
     await foreach (var item in GenerateSequence())
     {
         Console.WriteLine(item);
     }
 }

9、索引和范圍

 范圍和索引為在陣列中指定資范圍(Span<T>或ReadOnlySpan<T>)提供了簡潔語法,

此語言支持依賴于兩個新型別和兩個新運算子,

  1、System.Index表示一個序列索引

  2、^運算子,指定一個索引與序列末尾相關,

  3、System.Range表示序列的子范圍

  4、范圍運算子(..),用于指定范圍的開始和末尾,就像運算元一樣,

讓我們從索引規則開始,請考慮陣列sequence,0索引與sequence[0]相同,^0索引與sequence[sequence.Length]相同,請注意,sequence[^0]不會引發例外,就像是sequence[sequence.Length]一樣,對于任何數字n,索引^n與sequence.Length-n相同,

范圍指定范圍的開始和末尾,包括此范圍的開始,但是不包括此范圍的末尾,這表示此范圍包含開始但不包含末尾,范圍[0..^0]表示整個范圍,就像[0..sequence.Length]表示整個范圍,

請看以下一個示例,請考慮以下陣列,用其順數索引和倒數索引進行注釋:

 var words = new string[]
 {
                 // index from start    index from end
     "The",      // 0                   ^9
     "quick",    // 1                   ^8
     "brown",    // 2                   ^7
     "fox",      // 3                   ^6
     "jumped",   // 4                   ^5
     "over",     // 5                   ^4
     "the",      // 6                   ^3
     "lazy",     // 7                   ^2
     "dog"       // 8                   ^1
 };              // 9 (or words.Length) ^0

可以使用^1索引檢索最后一個詞:

 Console.WriteLine($"The last word is {words[^1]}");

 

 以下代碼創建了一個包含單詞"quick"、"brown"和"fox"的子范圍,它包括words[1]到words[3],元素words[4]不在此范圍內,

var quickBrownFox = words[1..4];
foreach (var item in quickBrownFox)
{
    Console.WriteLine(item);
}

 

 以下代碼使用"lazy"和"dog"創建一個子范圍,它包括words[^2]和words[^1],不包括結束索引words[^0]:

var lazyDog = words[^2..^0];

下面的示例為開始和/或結束創建了開放范圍:

var allWords = words[..];      // contains "The" through "dog".
var firstPhrase = words[..4];  // contains "The" through "fox"
var lastPhrase = words[6..];   // contains "the", "lazy" and "dog"

此外可以將范圍宣告為變數:

Range phrase = 1..4;

然后可以在[和]字符中使用該范圍:

var text = words[phrase];

 

轉載請註明出處,本文鏈接:https://www.uj5u.com/net/116644.html

標籤:C#

上一篇:為什么要實作 IDisposable 介面?

下一篇:C# 添加、讀取、洗掉Excel檔案屬性

標籤雲
其他(157675) Python(38076) JavaScript(25376) Java(17977) C(15215) 區塊鏈(8255) C#(7972) AI(7469) 爪哇(7425) MySQL(7132) html(6777) 基礎類(6313) sql(6102) 熊猫(6058) PHP(5869) 数组(5741) R(5409) Linux(5327) 反应(5209) 腳本語言(PerlPython)(5129) 非技術區(4971) Android(4554) 数据框(4311) css(4259) 节点.js(4032) C語言(3288) json(3245) 列表(3129) 扑(3119) C++語言(3117) 安卓(2998) 打字稿(2995) VBA(2789) Java相關(2746) 疑難問題(2699) 细绳(2522) 單片機工控(2479) iOS(2429) ASP.NET(2402) MongoDB(2323) 麻木的(2285) 正则表达式(2254) 字典(2211) 循环(2198) 迅速(2185) 擅长(2169) 镖(2155) 功能(1967) .NET技术(1958) Web開發(1951) python-3.x(1918) HtmlCss(1915) 弹簧靴(1913) C++(1909) xml(1889) PostgreSQL(1872) .NETCore(1853) 谷歌表格(1846) Unity3D(1843) for循环(1842)

熱門瀏覽
  • WebAPI簡介

    Web體系結構: 有三個核心:資源(resource),URL(統一資源識別符號)和表示 他們的關系是這樣的:一個資源由一個URL進行標識,HTTP客戶端使用URL定位資源,表示是從資源回傳資料,媒體型別是資源回傳的資料格式。 接下來我們說下HTTP. HTTP協議的系統是一種無狀態的方式,使用請求/ ......

    uj5u.com 2020-09-09 22:07:47 more
  • asp.net core 3.1 入口:Program.cs中的Main函式

    本文分析Program.cs 中Main()函式中代碼的運行順序分析asp.net core程式的啟動,重點不是剖析原始碼,而是理清程式開始時執行的順序。到呼叫了哪些實體,哪些法方。asp.net core 3.1 的程式入口在專案Program.cs檔案里,如下。ususing System; us ......

    uj5u.com 2020-09-09 22:07:49 more
  • asp.net網站作為websocket服務端的應用該如何寫

    最近被websocket的一個問題困擾了很久,有一個需求是在web網站中搭建websocket服務。客戶端通過網頁與服務器建立連接,然后服務器根據ip給客戶端網頁發送資訊。 其實,這個需求并不難,只是剛開始對websocket的內容不太了解。上網搜索了一下,有通過asp.net core 實作的、有 ......

    uj5u.com 2020-09-09 22:08:02 more
  • ASP.NET 開源匯入匯出庫Magicodes.IE Docker中使用

    Magicodes.IE在Docker中使用 更新歷史 2019.02.13 【Nuget】版本更新到2.0.2 【匯入】修復單列匯入的Bug,單元測驗“OneColumnImporter_Test”。問題見(https://github.com/dotnetcore/Magicodes.IE/is ......

    uj5u.com 2020-09-09 22:08:05 more
  • 在webform中使用ajax

    如果你用過Asp.net webform, 說明你也算是.NET 開發的老兵了。WEBform應該是2011 2013左右,當時還用visual studio 2005、 visual studio 2008。后來基本都用的是MVC。 如果是新開發的專案,估計沒人會用webform技術。但是有些舊版 ......

    uj5u.com 2020-09-09 22:08:50 more
  • iis添加asp.net網站,訪問提示:由于擴展配置問題而無法提供您請求的

    今天在iis服務器配置asp.net網站,遇到一個問題,記錄一下: 問題:由于擴展配置問題而無法提供您請求的頁面。如果該頁面是腳本,請添加處理程式。如果應下載檔案,請添加 MIME 映射。 WindowServer2012服務器,添加角色安裝完.netframework和iis之后,運行aspx頁面 ......

    uj5u.com 2020-09-09 22:10:00 more
  • WebAPI-處理架構

    帶著問題去思考,大家好! 問題1:HTTP請求和回傳相應的HTTP回應資訊之間發生了什么? 1:首先是最底層,托管層,位于WebAPI和底層HTTP堆疊之間 2:其次是 訊息處理程式管道層,這里比如日志和快取。OWIN的參考是將訊息處理程式管道的一些功能下移到堆疊下端的OWIN中間件了。 3:控制器處理 ......

    uj5u.com 2020-09-09 22:11:13 more
  • 微信門戶開發框架-使用指導說明書

    微信門戶應用管理系統,采用基于 MVC + Bootstrap + Ajax + Enterprise Library的技術路線,界面層采用Boostrap + Metronic組合的前端框架,資料訪問層支持Oracle、SQLServer、MySQL、PostgreSQL等資料庫。框架以MVC5,... ......

    uj5u.com 2020-09-09 22:15:18 more
  • WebAPI-HTTP編程模型

    帶著問題去思考,大家好!它是什么?它包含什么?它能干什么? 訊息 HTTP編程模型的核心就是訊息抽象,表示為:HttPRequestMessage,HttpResponseMessage.用于客戶端和服務端之間交換請求和回應訊息。 HttpMethod類包含了一組靜態屬性: private stat ......

    uj5u.com 2020-09-09 22:15:23 more
  • 部署WebApi隨筆

    一、跨域 NuGet參考Microsoft.AspNet.WebApi.Cors WebApiConfig.cs中配置: // Web API 配置和服務 config.EnableCors(new EnableCorsAttribute("*", "*", "*")); 二、清除默認回傳XML格式 ......

    uj5u.com 2020-09-09 22:15:48 more
最新发布
  • C#多執行緒學習(二) 如何操縱一個執行緒

    <a href="https://www.cnblogs.com/x-zhi/" target="_blank"><img width="48" height="48" class="pfs" src="https://pic.cnblogs.com/face/2943582/20220801082530.png" alt="" /></...

    uj5u.com 2023-04-19 09:17:20 more
  • C#多執行緒學習(二) 如何操縱一個執行緒

    C#多執行緒學習(二) 如何操縱一個執行緒 執行緒學習第一篇:C#多執行緒學習(一) 多執行緒的相關概念 下面我們就動手來創建一個執行緒,使用Thread類創建執行緒時,只需提供執行緒入口即可。(執行緒入口使程式知道該讓這個執行緒干什么事) 在C#中,執行緒入口是通過ThreadStart代理(delegate)來提供的 ......

    uj5u.com 2023-04-19 09:16:49 more
  • 記一次 .NET某醫療器械清洗系統 卡死分析

    <a href="https://www.cnblogs.com/huangxincheng/" target="_blank"><img width="48" height="48" class="pfs" src="https://pic.cnblogs.com/face/214741/20200614104537.png" alt="" /&g...

    uj5u.com 2023-04-18 08:39:04 more
  • 記一次 .NET某醫療器械清洗系統 卡死分析

    一:背景 1. 講故事 前段時間協助訓練營里的一位朋友分析了一個程式卡死的問題,回過頭來看這個案例比較經典,這篇稍微整理一下供后來者少踩坑吧。 二:WinDbg 分析 1. 為什么會卡死 因為是表單程式,理所當然就是看主執行緒此時正在做什么? 可以用 ~0s ; k 看一下便知。 0:000> k # ......

    uj5u.com 2023-04-18 08:33:10 more
  • SignalR, No Connection with that ID,IIS

    <a href="https://www.cnblogs.com/smartstar/" target="_blank"><img width="48" height="48" class="pfs" src="https://pic.cnblogs.com/face/u36196.jpg" alt="" /></a>...

    uj5u.com 2023-03-30 17:21:52 more
  • 一次對pool的誤用導致的.net頻繁gc的診斷分析

    <a href="https://www.cnblogs.com/dotnet-diagnostic/" target="_blank"><img width="48" height="48" class="pfs" src="https://pic.cnblogs.com/face/3115652/20230225090434.png" alt=""...

    uj5u.com 2023-03-28 10:15:33 more
  • 一次對pool的誤用導致的.net頻繁gc的診斷分析

    <a href="https://www.cnblogs.com/dotnet-diagnostic/" target="_blank"><img width="48" height="48" class="pfs" src="https://pic.cnblogs.com/face/3115652/20230225090434.png" alt=""...

    uj5u.com 2023-03-28 10:13:31 more
  • C#遍歷指定檔案夾中所有檔案的3種方法

    <a href="https://www.cnblogs.com/xbhp/" target="_blank"><img width="48" height="48" class="pfs" src="https://pic.cnblogs.com/face/957602/20230310105611.png" alt="" /></a&...

    uj5u.com 2023-03-27 14:46:55 more
  • C#/VB.NET:如何將PDF轉為PDF/A

    <a href="https://www.cnblogs.com/Carina-baby/" target="_blank"><img width="48" height="48" class="pfs" src="https://pic.cnblogs.com/face/2859233/20220427162558.png" alt="" />...

    uj5u.com 2023-03-27 14:46:35 more
  • 武裝你的WEBAPI-OData聚合查詢

    <a href="https://www.cnblogs.com/podolski/" target="_blank"><img width="48" height="48" class="pfs" src="https://pic.cnblogs.com/face/616093/20140323000327.png" alt="" /><...

    uj5u.com 2023-03-27 14:46:16 more