Unity進階--C#補充知識點--【C#各版本的新功能新語法】C#1~4與C#5

·來源于唐老獅的視頻教學,僅作記錄和感悟記錄,方便日后復習或者查找


一.C#版本與Unity的關系

1.各Unity版本支持的C#版本

更多信息可以在Untiy官網說明查看
https://docs.unity3d.com/2020.3/Documentation/Manual/CSharpCompiler.html(這個好像要科學上網)

2.為什么不同版本Unity支持的C#版本不同

是因為不同版本的Unity使用的 C#編譯器 腳本運行時版本不同

3.不同版本C#的意義

主要就是可以使用新功能,來節約代碼量,讓代碼更簡單直觀簡潔

4.Unity中調整.Net API 兼容級別

可以去工程中選擇對應的兼容級別

目前新版本(這里是2022.3.62f1c1)分為了.Net Standard 2.1 和 .Net Framework

.Net Framework(特殊需求時):

  • 具備較為完整的.Net API,甚至包含了一些無法跨平臺的API
  • 如果你的應用主要針對Windows平臺,并且會使用到.Net Standard 2.0中沒有的功能時會選擇使用它
  • 包體更大

.Net Standard 2.1(常規情況下):

  • ?是一個.Net標準API集合,相對.Net Framework包含更少的內容,可以減小最終可執行文件大小
  • ?它具有更好的跨平臺支持
  • .Net Standard 2.1?配置文件大小是.Net Framework配置文件的一半

通常情況下,為了跨平臺和更小的包體,我們都選擇使用默認的.Net Standard 2.1


二.C#1~4

1.Unity最低支持的C#版本

2.C#1~4的功能和語法

這里只要提及一些Unity開發中常用的功能與特性

3.補充內容--命名與可選參數

可以讓我們在調用函數的時候,指定傳入的數據是傳入到哪一個參數上的。例如如下:

public void Test(int i, float f, bool b)
{}public void Test2(int i , bool b = true, string s = "123")
{}//有了命名參數,我們將不用匹配參數在所調用方法中的順序
//每個參數可以按照參數名字進行指定
Test(1, 1.2f, true);
Test(f: 3.3f, i: 5, b: false);
Test(b: false, f: 3.4f, i: 3);//命名參數可以配合可選參數使用,讓我們做到跳過其中的默認參數直接賦值后面的默認參數
Test2(1, true, "234");
Test2(1, s: "234");

這樣的好處是:

①可以跳過一些默認參數去賦值后面的參數

②通過好處一可以讓我們少寫一些代碼與重載函數

4.補充內容--動態類型

關鍵詞:dynamic

作用:能夠接收任意類型的不為NULL的變量,類似于Object,但是不是把他裝箱為Object,而是直接動態地解析成該變量的類型,我們可以在代碼后面直接使用該變量去賦值或者調用里面的成員變量與方法(不過不會有提示,需要我們自己保證拼寫沒有出錯)。更詳細的解釋如下:

注意事項:

  • 使用dynamic功能 需要將Unity的.Net API兼容級別切換為.Net Framework
  • IL2CPP 不支持 C# dynamic 關鍵字。它需要 JIT 編譯,而 IL2CPP 無法實現
  • 動態類型是無法自動補全方法的,我們在書寫時一定要保證方法的拼寫正確性
  • 該功能我們只做了解,不建議大家使用

使用例子:

using UnityEngine;public class TestClass
{public string name = "Test Me";public void PrintName(){Debug.Log(name);}
}public class Lesson3 : MonoBehaviour
{// Start is called before the first frame updatevoid Start(){//不確定要賦值的類型的時候使用dynamic i = 1;print(i);//可以接受一個類類型dynamic t = new TestClass();//去調用其中的方法t.PrintName(); print(t.GetType());    }
}

好處:

  • 可以讓我不用自己去關心和處理類型轉化相關的事項,節約代碼。
  • 不確定對象類型,但是確定對象成員時,可以使用動態類型通過反射處理某些功能時,也可以考慮使用動態類型來替換它

三.C#5

1.C#5的新功能和新語法

①調用方信息特性(C#進階套課——特性)

using System.Runtime.CompilerServices;public static void Log(string message,[CallerMemberName] string caller = null,[CallerFilePath] string file = null,[CallerLineNumber] int line = 0)
{Console.WriteLine($"【{message}】| 調用者:{caller} | 文件:{file} | 行號:{line}");
}// 調用示例
public class Demo
{public void Test(){Log("發生錯誤"); // 編譯器自動注入調用信息}
}

②異步方法async和await

2.回顧內容--線程

Unity中線程使用的注意事項:

  • Unity支持多線程
  • Unity中開啟的多線程不能使用主線程中的對象(不能使用Unity的API)
  • Unity中開啟多線程后一定記住關閉(一般在一個對象中創建線程后,在OnDestory中關閉線程)

線程的使用例子:

//創建一個新線程對象
t = new Thread(()=> {//線程中進行一個死循環while (true){print("123");//每次運行到這里的時候讓線程休眠1秒Thread.Sleep(1000);}
});
//啟用線程
t.Start();//下面是主線程的代碼
print("主線程執行");

3.補充內容--線程池

3.1.原理與特性

命名空間:System.Threading

類名:ThreadPool(線程池)

目的:

  • 在多線程的應用程序開發中,頻繁的創建刪除線程會帶來性能消耗,產生內存垃圾
  • 為了避免這種開銷C#推出了 線程池ThreadPool類

大致原理:

  • ThreadPool中有若干數量的線程,如果有任務需要處理時,會從線程池中獲取一個空閑的線程來執行任務
  • 任務執行完畢后線程不會銷毀,而是被線程池回收以供后續任務使用
  • 當線程池中所有的線程都在忙碌時,又有新任務要處理時,線程池才會新建一個線程來處理該任務,
  • 如果線程數量達到設置的最大值任務會排隊,等待其他任務釋放線程后再執行

優點:

  • 線程池能減少線程的創建,節省開銷,可以減少GC垃圾回收的觸發

缺點:

  • 不能控制線程池中線程的執行順序,也不能獲取線程池內線程取消/異常/完成的通知

3.2.內部的方法使用

//1.獲取可用的工作線程數和I/O線程數
int num1;
int num2;
ThreadPool.GetAvailableThreads(out num1, out num2);
print(num1);
print(num2);//2.獲取線程池中工作線程的最大數目和I/O線程的最大數目ThreadPool.GetMaxThreads(out num1, out num2);print(num1);print(num2);

//3.設置線程池中可以同時處于活動狀態的 工作線程的最大數目和I/O線程的最大數目
//  大于次數的請求將保持排隊狀態,知直到線程池線程變為可用
//  更改成功返回true,失敗返回false
if(ThreadPool.SetMaxThreads(20, 20))
{print("更改成功");
}

//5.設置 工作線程的最小數目和I/O線程的最小數目
if(ThreadPool.SetMinThreads(5, 5))
{print("設置成功");
}//4.獲取線程池中工作線程的最小數目和I/O線程的最小數目
ThreadPool.GetMinThreads(out num1, out num2);
print(num1);
print(num2);

最小線程數是:在初始的時候一直保持至少有這么多個線程是在運行的(即使它沒有執行什么任務,但是一旦有任務可以馬上用它來執行)

最大線程數是:如果當前線程數已經達到了最大線程數,當有新任務的時候,就會先排隊等待線程資源被釋放出來

//6.將方法排入隊列以便執行,當線程池中線程變得可用時執行//ThreadPool.QueueUserWorkItem((obj) =>
//{
//    print(obj);
//    print("開啟了一個線程");
//}, "123452435345");for (int i = 0; i < 10; i++)
{//第一個參數傳入一個回調函數,第二個參數傳入一個要在回調中使用的參數值(傳給obj了)ThreadPool.QueueUserWorkItem((obj) =>{print("第" + obj + "個任務");}, i);
}print("主線程執行");

4.補充內容----Task任務類

4.1.認識Task

命名空間:System.Threading.Tasks
類名:Task

說明:Task就是任務的意思,它繼承了線程池的優點的同時改進了線程池的缺點,即創建的任務能夠被精確地控制。它是基于線程池的優點的一個封裝類,可以幫助我們更加高效地完成多線程相關的開發。

4.2.創建Task的方式

4.2.1.創建無返回值的Task的三種方式
        //1.通過new一個Task對象傳入委托函數并啟動Task t1 = new Task(() => {int i = 0;while (isRuning) {print("方式一:" + i);++i;Thread.Sleep(1000);}});t1.Start();//2.通過Task中的Run靜態方法傳入委托函數Task t2 = Task.Run(() => {int i = 0;while (isRuning) {print("方式二:" + i);++i;Thread.Sleep(1000);}});//3.通過Task.Factory中的StartNew靜態方法傳入委托函數Task t3 = Task.Factory.StartNew(() => {int i = 0;while (isRuning) {print("方式三:" + i);++i;Thread.Sleep(1000);}});

①new一個Task對象,傳入委托函數

②使用Task.Run靜態方法傳入委托函數

③使用Task.Factory.StartNew()傳入委托函數

4.2.2.創建有返回值的Task的三種方式
        //1.通過new一個Task對象闖入委托函數并啟動t1 = new Task<int>(() => {int i = 0;while (isRuning) {print("方式一:" + i);++i;Thread.Sleep(1000);}return 1;});t1.Start();//2.通過Task中的Run靜態方法傳入委托函數t2 = Task.Run<string>(() => {int i = 0;while (isRuning) {print("方式二:" + i);++i;Thread.Sleep(1000);}return "1231";});//3.通過Task.Factory中的StartNew靜態方法傳入委托函數t3 = Task.Factory.StartNew<float>(() => {int i = 0;while (isRuning) {print("方式三:" + i);++i;Thread.Sleep(1000);}return 4.5f;});

①方式和無返回值的基本方法差不多:new,Task.Run(),Task.Factory.RunNew()

②不同的在于這些方法后面要多加一個用于告訴返回值是多少的泛型,并且傳入的委托函數中要有相對應的返回值

//獲取返回值
//注意:
//Resut獲取結果時會阻塞線程
//即如果task沒有執行完成
//會等待task執行完成獲取到Result
//然后再執行后邊的代碼,也就是說 執行到這句代碼時 由于我們的Task中是死循環 
//所以主線程就會被卡死
print(t1.Result);
print(t2.Result);
print(t3.Result);print("主線程執行");

①通過task變量的值.Result獲取里面返回的值

②要注意一旦使用這個方法的時候,如果該線程中還沒有計算完成返回值的話就會一直阻塞主線程的執行

4.3.同步執行Task

默認情況下各個線程和主線程之間肯定是異步執行的

同步執行Task的意思大概可以粗暴地理解成把Task中的任務再放回主線程中執行。

//如果你希望Task能夠同步執行
//只需要調用Task對象中的RunSynchronously方法
//注意:需要使用 new Task對象的方式,因為Run和StartNew在創建時就會啟動Task t = new Task(() => {Thread.Sleep(1000);print("哈哈哈");
});
//t.Start();
t.RunSynchronously();
print("主線程執行");
//不Start 而是 RunSynchronously

①在開始線程的時候用的不是Start()而是RunSynchronously()

②注意這個只能用在用new一個Task的時候使用,因為另外兩種方法會直接默認Start()線程

4.4.Task中線程阻塞的方式(任務阻塞)

即讓一個線程執行完了之后才能夠繼續執行后面的內容

當我們需要在某幾個任務完成之后再去執行其他任務的時候可以使用這個方法

//1.Wait方法:等待任務執行完畢,再執行后面的內容
Task t1 = Task.Run(() =>
{for (int i = 0; i < 5; i++){print("t1:" + i);}
});Task t2 = Task.Run(() =>
{for (int i = 0; i < 20; i++){print("t2:" + i);}
});
t2.Wait();//2.WaitAny靜態方法:傳入任務中任意一個任務結束就繼續執行
//Task.WaitAny(t1, t2);//3.WaitAll靜態方法:任務列表中所有任務執行結束就繼續執行
//Task.WaitAll(t1, t2);//print("主線程執行");

①可以直接讓t1.wait()

②可以用Task中的靜態方法.WaitAny(),傳入可變參數個任務,等待其中任意一個任務完成之后就繼續執行

③可以用Task中的靜態方法.WaitAll(),傳入可變參數個任務,等待所有這些任務完成之后就繼續執行

4.5.Task中完成后續其他Task(任務延續)

即讓Task按一定順序接續執行

當我們需要讓某幾個任務之間按一定順序完成的時候就要使用這個方法

//1.WhenAll靜態方法 + ContinueWith方法:傳入任務完畢后再執行某任務
Task.WhenAll(t1, t2).ContinueWith((t) => {print("一個新的任務開始了");int i = 0;while (isRuning) {print(i);++i;Thread.Sleep(1000);}
});Task.Factory.ContinueWhenAll(new Task[] { t1, t2 }, (t) => {print("一個新的任務開始了");int i = 0;while (isRuning) {print(i);++i;Thread.Sleep(1000);}
});//2.WhenAny靜態方法 + ContinueWith方法:傳入任務只要有一個執行完畢后再執行某任務
Task.WhenAny(t1, t2).ContinueWith((t) => {print("一個新的任務開始了");int i = 0;while (isRuning) {print(i);++i;Thread.Sleep(1000);}
});Task.Factory.ContinueWhenAny(new Task[] { t1, t2 }, (t) => {print("一個新的任務開始了");int i = 0;while (isRuning) {print(i);++i;Thread.Sleep(1000);}
});

①可以通過Task的靜態類.WhenAll和.WhenAny中的.ContinueWith方法,或者Task.Factory中的靜態方法.ContinueWhenAll()和.ContinueWhenAny()來指定所有任務完成后或者其中任意一個任務完成之后再去執行的任務

②委托函數中傳入的參數t是一個Task類型的,它是里面包含了前置的那些任務的執行狀態之類的變量。比如可以按如下方式使用:

.ContinueWith(t => {if (t.IsFaulted) {Debug.LogError($"任務失敗: {t.Exception}");return;}// 安全執行后續邏輯...
});

4.6.取消Task執行

方法一:通過加入bool標識 控制線程內死循環的結束

方法二:通過CancellationTokenSource取消標識源類 來控制
CancellationTokenSource對象可以達到延遲取消、取消回調等功能

 //聲明一個取消標識源類c = new CancellationTokenSource();//延遲取消c.CancelAfter(5000);//取消回調c.Token.Register(() =>{print("任務取消了");});Task.Run(() =>{int i = 0;//用里面的是否被撤銷的屬性來控制循環while (!c.IsCancellationRequested){print("計時:" + i);++i;Thread.Sleep(1000);}});//延遲取消// Update is called once per frame
void Update()
{if(Input.GetKeyDown(KeyCode.Space)){//調用取消標識源中的取消方法來取消任務c.Cancel();}
}

①可以在一開始的時候設定一個控制取消的延遲時間

②可以在取消的時候觸發一個取消回調事件

③可以用是否撤銷的屬性來控制線程是否被撤銷

5.異步方法

5.1.什么是同步和異步

同步和異步主要用于修飾方法
同步方法:
當一個方法被調用時,調用者需要等待該方法執行完畢后返回才能繼續執行
異步方法:
當一個方法被調用時立即返回,并獲取一個線程執行該方法內部的邏輯,調用者不用等待該方法執行完畢

5.2.什么時候需要異步編程

當我們調用的方法計算量比較大且耗時的時候,我們不希望花太多時間在這上面阻塞主線程。這個時候據需要使用異步方法了。

比如:

  • 1.復雜邏輯計算時
  • 2.網絡下載、網絡通訊
  • 3.資源加載時

等等

5.3.異步方法async和await

async和await一般需要配合Task進行使用

async:負責修飾方法,告訴編譯器這個是異步方法

await:負責在異步方法內部返回一個線程中的執行邏輯,此時會回到函數外部的主線程中,當該線程中的這部分執行邏輯執行結束了之后才會繼續執行函數后面的邏輯

  • 在一個async異步函數中可以有多個await等待關鍵字

使用await等待異步內容執行完畢(一般和Task配合使用)
遇到await關鍵字時發生的事情:

  • 1.異步方法將被掛起
  • 2.將控制權返回給調用者
  • 3.當await修飾內容異步執行結束后,繼續通過調用者線程執行后面內容
//異步方法執行流程示意
public async void TestAsync()
{//1print("進入異步方法");//2.這步會在一個線程中執行,此時程序返回到函數外部的主線程中繼續執行await Task.Run(() =>{Thread.Sleep(5000);});//3.當第二步中的線程執行完畢了之后,就會繼續執行這之后的邏輯print("異步方法后面的邏輯");
}

使用async修飾異步方法的注意事項:

  • 1.在異步方法中使用await關鍵字(不使用編譯器會給出警告但不報錯),否則異步方法會以同步方式執行
  • 2.異步方法名稱建議以Async結尾
  • 3.異步方法的返回值只能是void、Task、Task<>
  • 4.異步方法中不能聲明使用ref或out關鍵字修飾的變量

5.4.使用例子

5.4.1.復雜邏輯計算

利用Task新開線程進行計算 計算完畢后再使用 比如復雜的尋路算法
CalcPathAsync(this.gameObject, Vector3.zero);

 public async void CalcPathAsync(GameObject obj, Vector3 endPos){print("開始處理尋路邏輯");int value = 10;await Task.Run(() =>{//處理復雜邏輯計算 我這是通過 休眠來模擬 計算的復雜性Thread.Sleep(1000);value = 50;//是多線程 意味著我們不能在 多線程里 去訪問 Unity主線程場景中的對象//這樣寫會報錯//print(obj.transform.position);});print("尋路計算完畢 處理邏輯" + value);obj.transform.position = Vector3.zero;}

5.4.2.計時器

顧名思義,就是按時間計時了

Timer();
print("主線程邏輯執行");

 public async void Timer(){UnityWebRequest q = UnityWebRequest.Get("");source = new CancellationTokenSource();int i = 0;while (!source.IsCancellationRequested){print(i);await Task.Delay(1000);++i;}}// Update is called once per frame
void Update()
{if (Input.GetKeyDown(KeyCode.Space))source.Cancel();
}

5.4.3.資源加載

Addressables的資源異步加載是可以使用async和await的

Resources.LoadAsync()這些早期的異步加載資源的方式在await這里用不了,只有使用協同程序進行使用。除非搭配一些第三方的插件https://github.com/svermeulen/Unity3dAsyncAwaitUtil(需要科學上網)

用到.Net庫中的一些API的時候可以考慮使用異步方法

用第三方插件實現的Resources.LoadAsync()實例:

using UnityEngine;/// <summary>
/// 用異步函數異步加載一個立方體到場景中
/// </summary>
public class Lesson6 : MonoBehaviour
{// Start is called before the first frame updatevoid Start(){LoadCubeAsync("cube");}/// <summary>/// 異步加載一個資源并實例化到場景中/// </summary>private async void LoadCubeAsync(string resName){print("開始加載一個資源");//獲取異步加載請求ResourceRequest request = Resources.LoadAsync<GameObject>(resName);//等待資源異步加載完成await request;print("加載完畢,開始實例化");GameObject cube = request.asset as GameObject;cube = Instantiate(cube, Vector3.zero, Quaternion.identity);}
}

①用來這插件之后可以讓await支持對ResourceRequest這個類的異步等待

②之后按異步方法的常規套路來處理等待加載完成之后的邏輯


四.總結

①Unity各個版本支持的C#版本是不同的,因為各個版本的Unity使用的腳本運行時和C#編譯器都是更新的,這能夠讓我們使用最新的C#來在我們的代碼中進行編程

②更新版本的C#一般會帶來新的方法和特性,使用這些方法和特性往往能夠讓我們的代碼更加簡潔

③在C#4中,加入了dynamic動態類型,能夠讓我們繞過編譯器檢查去在運行的時候動態地生成相應類型的變量,這在我們無法一開始確定對象的類型的時候還是比較有用的。但是它不支持IL2CPP,且需要把.Net兼容版本設置為.Net Framework,這意味著更大的包體,更低的執行效率,以及放棄了跨平臺的特性。因此我們一般不推薦使用這個

④在C#5中,加入了ThreadPool,Task,和異步方法Async與await關鍵字

⑤ThreadPool能夠幫助我們更高效地利用線程資源,但是無法精確地獲取每個線程的信息與控制

⑥Task是基于ThreadPool的優點的更高一層封裝,它能夠創建無返回值和有返回值的任務類型,并且能夠讓任務同步執行(用new方法創建的),讓關鍵任務進行阻塞,讓幾個任務按一定順序完成,同時可以用一個取消標記源類來控制任務的撤銷以及觸發相應的撤銷回調

⑦Async和await關鍵字合作來完成對一個異步方法的修飾,Async修飾的方法只能夠以void,Task,Task<>作為返回值await是用于掛起該函數并等待一個線程邏輯執行完畢之后再執行后續的函數邏輯,一個函數中可以包含多個await。

⑧異步方法通常用于復雜計算,計時器,資源加載等場景。其中Unity內置的一些資源加載的異步方法需要加入一些第三方插件才能夠支持運行。不過一般情況下用協同函數也能夠完成這樣的資源加載。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/bicheng/93916.shtml
繁體地址,請注明出處:http://hk.pswp.cn/bicheng/93916.shtml
英文地址,請注明出處:http://en.pswp.cn/bicheng/93916.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

水閘安全綜合監測系統解決方案

一、方案概述 水閘作為重要的水利工程設施&#xff0c;承擔著防洪、排澇、供水和灌溉等關鍵功能。其安全性直接關系到下游人民群眾的生命財產安全以及區域經濟的穩定發展。近年來&#xff0c;隨著極端天氣頻發和工程老化問題日益突出&#xff0c;水閘安全監測工作顯得尤為重要。…

基于單片機智能點滴輸液系統

傳送門 &#x1f449;&#x1f449;&#x1f449;&#x1f449;其他作品題目速選一覽表 &#x1f449;&#x1f449;&#x1f449;&#x1f449;其他作品題目功能速覽 概述 該系統基于單片機控制技術&#xff0c;結合傳感器和無線通信模塊&#xff0c;實現對輸液過程的實…

AI數據倉庫管理提升效率

內容概要在數字化轉型浪潮中&#xff0c;AI數據倉庫管理正重塑企業數據處理格局。本部分簡要介紹其核心機制&#xff0c;即通過智能API接入外部數據源實現多平臺數據無縫整合&#xff0c;隨后應用數據清洗技術去除冗余信息&#xff0c;確保數據質量。同時&#xff0c;加密存儲機…

使用 Docker 安裝長安鏈管理平臺 + 部署區塊鏈與示例合約

文章目錄簡介登錄官網GithubPodman 配置&#xff08;Docker 配置 registry 地址&#xff09;安裝長安鏈管理平臺下載源碼docker-compose.yml登錄管理平臺部署區塊鏈Dockerfile構建鏡像部署長安鏈訂閱區塊鏈部署合約下載示例合約部署示例合約投票管理文件哈希存證查找存證信息區…

Python訓練營打卡 DAY 41 簡單CNN

知識回顧 數據增強卷積神經網絡定義的寫法batch歸一化&#xff1a;調整一個批次的分布&#xff0c;常用與圖像數據特征圖&#xff1a;只有卷積操作輸出的才叫特征圖調度器&#xff1a;直接修改基礎學習率 卷積操作常見流程如下&#xff1a; 1. 輸入 → 卷積層 → Batch歸一化層…

云端賦能,智慧運維:分布式光伏電站一體化監控平臺研究

摘要 本文針對分布式光伏電站存在的監管困難、火災隱患、系統繁雜及運維不規范等行業痛點&#xff0c;提出AcrelCloud-1200光伏運維云平臺解決方案。平臺通過ANet-1E2S-4G網關集成多品牌逆變器數據&#xff0c;結合視頻監控與氣象站&#xff0c;實現電站全域監測&#xff1b;開…

CVPR 2025 | 具身智能 | HOLODECK:一句話召喚3D世界,智能體的“元宇宙練功房”來了

關注gongzhonghao【CVPR頂會精選】1.導讀1.1 論文基本信息論文標題&#xff1a;《HOLODECK: Language Guided Generation of 3D Embodied AI Environments》作者&#xff1a;Yue Yang*1, Fan-Yun Sun*2, Luca Weihs*4, Eli Vanderbilt4, Alvaro Herrasti4,Winson Han4, Jiajun …

迅為RK3568開發板搭建Ubuntu環境

本小節介紹開發所需 Ubuntu 環境的搭建方法。系統要求:Ubuntu 系統要求&#xff1a;Ubuntu18.04~21.10 版本。推薦使用 20.04 版本&#xff0c;內存 16GB 及以上&#xff0c;硬盤 100GB 及以上。Ubuntu 系統的用戶名不能包含中文字符。建議 Ubuntu 和 Windows 系統上安裝的 Dev…

【數據結構】用堆解決TOPK問題

設計一個算法&#xff0c;找出數組中最小的k個數。以任意順序返回這k個數均可。示例&#xff1a;輸入&#xff1a; arr [1,3,5,7,2,4,6,8], k 4 輸出&#xff1a; [1,2,3,4]比較替換堆頂的數時&#xff0c;不需要讓堆頂與數組的每一個數再進行比較&#xff0c;比較數組減去k個…

【深度長文】Anthropic發布Prompt Engineering全新指南

目錄 1.什么時候適合用提示工程? 2.如何進行提示工程 2.1 使用提示模板 2.1.1 使用提示模板和變量 2.1.2 何時使用提示模板和變量 2.1.3 提示模板示例 2.2 保持清晰和直接 2.2.1 如何保持清晰、具有上下文和具體 2.2.2 示例 ?2.3 使用示例&#xff08;多示例提示…

【基礎-判斷】HarmonyOS提供了基礎的應用加固安全能力,包括混淆、加密和代碼簽名能力

正確 解釋如下: 應用加固: 這是指對應用程序進行保護,使其更難被逆向工程、篡改或盜版。HarmonyOS 作為現代操作系統,確實提供了這樣的基礎安全能力。 混淆: HarmonyOS 的 SDK 提供了代碼混淆工具(通常基于 ProGuard 或類似技術)。開發者在構建應用時啟用混淆,可以將類…

HTML 框架:構建網頁布局的基石

HTML 框架&#xff1a;構建網頁布局的基石 引言 HTML 框架是網頁設計中不可或缺的一部分&#xff0c;它為網頁內容的布局提供了強大的支持。本文將深入探討 HTML 框架的概念、種類、應用以及如何有效地使用它們來構建網頁布局。 什么是 HTML 框架&#xff1f; HTML 框架是一種網…

[Linux]學習筆記系列 -- [mm][memblock]

文章目錄mm/memblock.c: Linux內核的“拓荒時代”內存管理器一、 核心問題&#xff1a;為什么需要 memblock&#xff1f;二、 核心原理與設計三、 在內核啟動流程中的角色四、 關鍵 API五、 總結include/linux/memblock.hmm/memblock.cmemblock_reserve 預留內存塊for_each_mem…

Java 面試八股文匯總(1000 道附答案解析)

在過 2 個月即將進入金九銀十了&#xff0c;然而面對今年的大環境而言&#xff0c;跳槽成功的難度比往年高了很多&#xff0c;很明顯的感受就是&#xff1a;對于今年的 java 開發朋友跳槽面試&#xff0c;無論一面還是二面&#xff0c;都開始考驗一個 Java 程序員的技術功底和基…

給純小白的Python操作 PDF 筆記

一、文件基礎打開與關閉 推薦用 with open(path, mode, encodingutf-8) as f:&#xff0c;自動完成 close()&#xff0c;避免泄露文件句柄。常見模式&#xff1a;r 讀&#xff0c;w 寫覆蓋&#xff0c;a 追加&#xff0c;rb/wb 二進制。Windows 默認編碼為 GBK&#xff0c;Linu…

vue使用vue-cropper實現圖片裁剪之單圖裁剪

vue制作的pc系統中(如若依系統)&#xff0c;需要實現按照固定尺寸進行裁剪后再進行圖片上傳&#xff0c;以下代碼講述的是實現單張圖片裁剪上傳。1.第一步需要安裝vue-croppernpm install vue-cropper2.第二步在需要的頁面進入代碼引入import {VueCropper} from "vue-crop…

后臺管理系統-5-vue3之子路由渲染首頁及卡片容器和表格容器實現

文章目錄 1 子路由的實現 1.1 router/index.js 1.2 views/Home.vue(首頁) 1.3 Main.vue 2 左上方的卡片 2.1 分欄間隔(Layout布局) 2.2 卡片容器(el-card) 2.3 整體代碼Home.vue 3 左下方的table(靜態實現) 3.1 準備數據 3.2 渲染表格(el-table) 3.3 整體代碼Home.vue 4 附錄 子…

在CentOS系統中查詢已刪除但仍占用磁盤空間的文件

在CentOS系統中查詢已刪除但仍占用磁盤空間的文件在CentOS系統中查詢已刪除但仍占用磁盤空間的文件1. 檢查磁盤整體使用情況2. 查找被刪除但仍被進程占用的文件3. 釋放磁盤空間4. 替代方案&#xff08;不終止進程&#xff09;注意事項補充工具在CentOS系統中查詢已刪除但仍占用…

正點原子【第四期】Linux之驅動開發學習筆記-1.1 Linux驅動開發與裸機開發的區別

前言&#xff1a; 本文是根據嗶哩嗶哩網站上“正點原子【第四期】手把手教你學Linux系列課程之 Linux驅動開發篇”視頻的學習筆記&#xff0c;該課程配套開發板為正點原子alpha/mini Linux開發板。在這里會記錄下正點原子 I.MX6ULL 開發板的配套視頻教程所作的實驗和學習筆記內…

Android SystemServer 中 Service 的創建和啟動方式

今天導師給我將講了一些如何新建一個系統服務&#xff0c;以及如何去初始化。 Android SystemServer 中 Service 的創建和啟動方式 在 Android 系統中&#xff0c;SystemServer 是系統服務的核心進程&#xff0c;負責啟動和管理各種系統服務。以下是 SystemServer 中服務創建和…