適合每位開發(fā)人員的 60 個 C# 代碼片段
嘿! 今天,我有一些特別的東西要與大家分享 - 60 個 C# 代碼片段的匯編,我發(fā)現(xiàn)它們對我自己的工作非常有幫助。
在本文中,我們不僅要了解這些片段如何解決日常編程問題,還要了解它們?yōu)楹稳绱斯ぷ鳌?這是為了建立更深入的理解,而不僅僅是快速復制粘貼工作。
如果您一直在使用 C# 并且曾經(jīng)發(fā)現(xiàn)自己陷入問題,不確定如何有效地解決它,那么這些片段適合您。 如果您對 C# 比較陌生并且正在嘗試了解如何更有效地使用該語言,那么它們也適合您。
好了,說夠了。 讓我們一起開始探索這些代碼片段。 我希望你發(fā)現(xiàn)它們和我一樣有用。
在我們繼續(xù)之前,在提供的示例中,我嘗試添加一點幽默感并列出一些用例。 希望這也能讓你開心,因為至少我總是更容易記住有趣的事情:)讓我們開始吧!
10 個復雜的所有類型片段
1、二分查找
public int BinarySearch(int[] arr, int target)
{
int left = 0;
int right = arr.Length - 1;
while (left <= right)
{
int mid = left + (right - left) / 2;
if (arr[mid] == target)
return mid;
if (arr[mid] < target)
left = mid + 1;
else
right = mid - 1;
}
return -1;
}
將此代碼視為搜索方法中的福爾摩斯。 您知道,與其浪費時間到處尋找特定的物品,不如直接切入正題不是很好嗎? 這正是二分查找的作用——它通過劃分和征服來節(jié)省你的時間(和理智)!
用例:
- 在已排序的用戶列表中搜索特定用戶。
- 在已排序的圖書館數(shù)據(jù)庫中查找特定的書籍。
2、冒泡排序
public void BubbleSort(int[] arr)
{
int len = arr.Length;
for (int i = 0; i < len - 1; i++)
for (int j = 0; j < len - i - 1; j++)
if (arr[j] > arr[j + 1])
{
int temp = arr[j];
arr[j] = arr[j + 1];
arr[j + 1] = temp;
}
}
就像你有時把所有衣服扔到空中然后排列它們一樣(來吧,我們都會這樣做,對吧?),冒泡排序會隨機排列數(shù)組中的數(shù)字,直到它們處于完美的順序。 雖然這不是最快的排序,但它絕對是一個有趣的觀看方式。
用例:
- 按升序?qū)ε判邪穹謹?shù)進行排序。
- 按價格組織產(chǎn)品列表。
3、圖上的深度優(yōu)先搜索(DFS)
public void DFS(int v, bool[] visited, List<int>[] adj)
{
visited[v] = true;
Console.Write(v + " ");
foreach (int neighbour in adj[v])
{
if (!visited[neighbour])
DFS(neighbour, visited, adj);
}
}
DFS就像那個朋友,當你們一起去徒步旅行時,只需探索每一個角落。 在考慮嘗試一條新道路之前,它會盡可能深入地探索一條道路。 當您需要對圖表的所有節(jié)點進行徹底、全面的搜索時,請使用它。
用例:
- 在迷宮中尋找路徑。
- 分析網(wǎng)絡(luò)連接。
4、斐波那契數(shù)列
public void PrintFibonacci(int n)
{
int a = 0, b = 1, c;
for(int i = 0; i < n; i++)
{
Console.Write(a + " ");
c = a + b;
a = b;
b = c;
}
}
想要享受一些優(yōu)雅的數(shù)字嗎? 斐波那契數(shù)列就像數(shù)字的交響曲,每個數(shù)字都是前兩個數(shù)字的和諧融合。 此代碼片段可幫助您生成由“n”項組成的斐波那契數(shù)列。
用例:
- 解決數(shù)學中與遞歸序列相關(guān)的問題。
- 在與搜索和排序甚至密碼學相關(guān)的算法中。
5、階乘計算
public int Factorial(int n)
{
if (n == 0)
return 1;
else
return n * Factorial(n - 1);
}
還記得你以為自己可以吃無數(shù)塊餅干,然后意識到自己可能吃不完 10 塊嗎? 嗯,階乘有點像這樣——它們涉及將所有正整數(shù)乘以某個數(shù)字,并且它們很快就會變大! 當您需要計算階乘時,請使用此代碼片段。
用例:
- 在計算統(tǒng)計組合和排列時。
- 用于某些搜索和查詢優(yōu)化算法。
6、矩陣乘法
public int[,] MultiplyMatrix(int[,] a, int[,] b)
{
int[,] result = new int[a.GetLength(0),b.GetLength(1)];
for (int i = 0; i < result.GetLength(0); i++)
{
for (int j = 0; j < result.GetLength(1); j++)
{
result[i, j] = 0;
for (int k = 0; k < a.GetLength(1); k++) // or k<b.GetLength(0)
result[i, j] += a[i, k] * b[k, j];
}
}
return result;
}
矩陣乘法就像一個聚會,其中第一個矩陣的每一行都與第二個矩陣的每一列混合在一起。 結(jié)果呢? 一個全新的矩陣,其元素是根據(jù)乘法對的總和創(chuàng)建的。 因此,當您希望矩陣舉辦派對時,此片段將成為您的 DJ!
用例:
- 在計算機圖形學中將 3D 對象轉(zhuǎn)換為不同的比例或位置。
- 用數(shù)值方法求解線性方程組。
7、回文檢查器
public bool IsPalindrome(string str)
{
str = str.ToLower();
int i = 0, j = str.Length - 1;
while (i < j)
{
if (str[i++] != str[j--])
return false;
}
return true;
}
如果您不確定某個單詞或短語是否是秘密回文,此功能可以為您提供支持。
用例:
- 檢查單詞是否為文字游戲或拼圖的回文。
- 生物信息學中驗證 DNA 序列的對稱性。
8、埃拉托斯特尼篩法(查找 n 以內(nèi)的所有素數(shù))
public List<int> SieveOfEratosthenes(int n)
{
bool[] prime = new bool[n + 1];
for (int i = 0; i <= n; i++)
prime[i] = true;
for (int p = 2; p * p <= n; p++)
{
if (prime[p] == true)
{
for (int i = p * p; i <= n; i += p)
{
prime[i] = false;
}
}
}
List<int> primeNumbers = new List<int>();
for (int i = 2; i <= n; i++)
{
if (prime[i])
{
primeNumbers.Add(i);
}
}
return primeNumbers;
}
埃拉托斯特尼篩法是一種古老(但卻是黃金)的算法,用于找出給定數(shù)字“n”之前的所有素數(shù)。 這就像一個篩子篩掉合數(shù),只留下素數(shù)。
用例:
- 為加密應用程序生成素數(shù)。
- 在數(shù)論和數(shù)學問題中的應用。
9、快速排序算法
public void QuickSort(int[] arr, int low, int high)
{
if (low < high)
{
int pi = Partition(arr, low, high);
QuickSort(arr, low, pi - 1);
QuickSort(arr, pi + 1, high);
}
}
int Partition(int[] arr, int low, int high)
{
int pivot = arr[high];
int i = (low - 1);
for (int j = low; j <= high - 1; j++)
{
if (arr[j] < pivot)
{
i++;
Swap(arr, i, j);
}
}
Swap(arr, i + 1, high);
return (i + 1);
}
void Swap(int[] arr, int a, int b)
{
int temp = arr[a];
arr[a] = arr[b];
arr[b] = temp;
}
QuickSort,顧名思義,是一種快速高效的排序算法。 它選擇一個主元元素,然后圍繞該主元對數(shù)組進行分區(qū)。
用例:
- 在時間復雜度很重要的軟件應用程序中對數(shù)據(jù)進行排序。
- 在選擇算法中,選擇是根據(jù)某些條件完成的。
10、查找鏈表的長度(迭代)
public int GetLength(ListNode head)
{
int count = 0;
ListNode current = head;
while (current != null)
{
count++;
current = current.next;
}
return count;
}
這個函數(shù)會遍歷鏈表,就像你來回踱步一樣,不耐煩地等待你的咖啡因修復,并計算節(jié)點的數(shù)量。
用例:
- 確定動態(tài)構(gòu)建的數(shù)據(jù)結(jié)構(gòu)的大小。
- 評估鏈表的長度以解決各種數(shù)據(jù)操作問題。
10 個詞典片段
1、使用Linq 填充字典
string[] fruits = { "apple", "banana", "cherry" };
var fruitsDictionary = fruits.Select((fruit, index) => new { fruit, index })
.ToDictionary(x => x.fruit, x => x.index);
我們都注重效率,Linq 是一個很棒的工具,可以幫助我們在單個語句中填充字典。 在此代碼片段中,我將獲取一個水果數(shù)組并將其轉(zhuǎn)換為字典,使用水果名稱作為鍵,使用索引作為值。
用例:
- 快速將對象列表轉(zhuǎn)換為查找表。
- 將數(shù)組轉(zhuǎn)換為字典以便于訪問。
2、創(chuàng)建嵌套字典
Dictionary<string, Dictionary<string, int>> nestedDictionary =
new Dictionary<string, Dictionary<string, int>>();
nestedDictionary["Fruits"] = new Dictionary<string, int> { { "Apple", 1 }, { "Banana", 2 } };
嵌套字典就像數(shù)據(jù)結(jié)構(gòu)的初始:字典中的字典。 當您需要存儲復雜的數(shù)據(jù)并且需要維護不同實體之間的關(guān)系時,這些功能非常有用。
用例:
- 存儲實體之間的復雜關(guān)系。
- 表示產(chǎn)品列表中的多級類別。
3、使用ConcurrentDictionary進行線程安全操作
ConcurrentDictionary<string, int> concurrentDictionary = new ConcurrentDictionary<string, int>();
concurrentDictionary.TryAdd("Apple", 1);
concurrentDictionary.TryUpdate("Apple", 2, 1);
當您需要同時添加或更新條目時,它可確保線程安全操作。 這就像在繁忙的十字路口有一個交通管制員。
用例:
- 實現(xiàn)涉及字典的多線程操作。
- 并行計算場景下更新共享資源。
4、使用 Linq 按鍵對字典進行排序
Dictionary<string, int> fruits = new Dictionary<string, int> { { "Apple", 1 }, { "Banana", 2 }, { "Cherry", 3 } };
var sortedDictionary = fruits.OrderBy(x => x.Key).ToDictionary(x => x.Key, x => x.Value);
有時,按鍵對字典進行排序可能是一個方便的功能,特別是當您想要按特定順序顯示條目時。 使用 Linq,您可以輕松實現(xiàn)這一點,使您的字典成為一個有序的集合。
用例:
- 對字典條目進行排序以供顯示。
- 為需要排序輸入的算法準備數(shù)據(jù)。
5、字典作為簡單的緩存
public class SimpleCache<TKey, TValue>
{
private Dictionary<TKey, TValue> cache = new Dictionary<TKey, TValue>();
public TValue Get(TKey key, Func<TKey, TValue> valueFactory)
{
if (!cache.TryGetValue(key, out TValue value))
{
value = valueFactory(key);
cache[key] = value;
}
return value;
}
}
我覺得這特別酷。 使用字典,您可以構(gòu)建一個簡單的緩存,以避免昂貴的計算或網(wǎng)絡(luò)調(diào)用。 您可以使用密鑰和工廠函數(shù)調(diào)用 Get。 如果鍵不在字典中,它將使用該函數(shù)創(chuàng)建值,將其添加到字典中,然后返回它。
用例:
- 避免計算算法中的重復計算。
- 緩存來自數(shù)據(jù)庫或 API 的常用數(shù)據(jù)。
6、UsingDictionary.ValueCollection
Dictionary<string, int> fruits = new Dictionary<string, int> { { "Apple", 1 }, { "Banana", 2 } };
Dictionary<string, int>.ValueCollection fruitValues = fruits.Values;
許多人忘記了可以使用 Values 屬性將字典值作為集合直接訪問。 當您只需要使用字典中的值而不是鍵時,這會很方便。
用例:
- 總結(jié)字典中的所有值。
- 查找字典中的最小值或最大值。
7、使用 AsParallel 進行并行操作
Dictionary<string, int> largeDictionary = ... // Large dictionary
var modifiedDictionary = largeDictionary.AsParallel().Select(kvp => new { kvp.Key, Value = kvp.Value * 2 }).ToDictionary(x => x.Key, x => x.Value);
LINQ 中的 AsParallel 方法提供了一種并行執(zhí)行操作的方法,這可以在處理大型字典時顯著提高性能。 請注意,您應該謹慎使用它,因為它可能不會為較小的字典帶來好處,甚至可能由于并行性的開銷而降低性能。
用例:
- 對大型字典執(zhí)行耗時的操作。
- 對字典中的每個值應用函數(shù)進行數(shù)據(jù)轉(zhuǎn)換。
8、UsingDictionary<TKey, TValue>.KeyCollection
Dictionary<string, int> fruits = new Dictionary<string, int> { { "Apple", 1 }, { "Banana", 2 } };
Dictionary<string, int>.KeyCollection fruitKeys = fruits.Keys;
與我們之前討論的 ValueCollection 類似,KeyCollection 使您可以直接訪問字典中的鍵。 這是迭代鍵而不用擔心值的好方法。
用例:
- 檢查字典中是否存在某個鍵。
- 迭代所有鍵以進行數(shù)據(jù)分析。
9、使用HashSet<T>刪除重復項
Dictionary<string, int> fruitsWithDuplicates = new Dictionary<string, int> { { "Apple", 1 }, { "Apple", 1 }, { "Banana", 2 } };
Dictionary<string, int> fruitsWithoutDuplicates = new HashSet<string>(fruitsWithDuplicates.Keys).ToDictionary(x => x, x => fruitsWithDuplicates[x]);
HashSet<T> 是一個經(jīng)常被忽視但功能強大的工具,用于從集合中刪除重復項。 當與字典結(jié)合使用時,它可以用于刪除重復的鍵并創(chuàng)建新的字典。
用例:
- 從用戶輸入字典中刪除重復項。
- 預處理期間清理數(shù)據(jù)。
10、使用SortedDictionary進行自動排序
SortedDictionary<string, int> sortedFruits = new SortedDictionary<string, int> { { "Apple", 1 }, { "Banana", 2 } };
SortedDictionary<TKey, TValue> 自動對字典中的鍵進行排序。 當您不斷需要數(shù)據(jù)處于排序狀態(tài)時,它會很有用。 但請注意,排序過程可能會帶來性能成本。
用例:
- 實現(xiàn)優(yōu)先級隊列。
- 維護二分搜索操作的排序數(shù)據(jù)。
10 個線程片段
1、任務(wù).運行快捷方式
Task.Run(() =>
{
// Long running operation...
});
Task.Run 是啟動后臺任務(wù)的便捷快捷方式。 這相當于創(chuàng)建一個新任務(wù)然后調(diào)用 Start(),但代碼更少。 誰不喜歡簡潔?
用例:
- 開始一項不需要立即關(guān)注的新操作。
- 在不阻塞主線程的情況下進行繁重的計算。
2、取消令牌
CancellationTokenSource cts = new CancellationTokenSource();
Task.Run(() =>
{
// Check the cancellation token regularly
while (!cts.Token.IsCancellationRequested)
{
// Do some work...
}
}, cts.Token);
// Cancel the task
cts.Cancel();
取消令牌可讓您優(yōu)雅地停止正在執(zhí)行的任務(wù)。 這就像友好地拍一下你的肩膀,告訴你的任務(wù)是時候停止了。
用例:
- 退出應用程序時停止后臺操作。
- 當不再需要時取消長時間運行的操作。
3、使用Interlocked.Increment進行安全更新
int counter = 0;
Parallel.For(0, 10000, i => Interlocked.Increment(ref counter));
Interlocked 類為多個線程共享的變量提供原子操作。 Interlocked.Increment 是一種在多線程環(huán)境中安全遞增計數(shù)器的方法。 它確保您的計數(shù)不會錯過任何一個節(jié)拍。
用例:
- 多線程場景下更新共享計數(shù)器。
- 確保基于線程的競爭條件不會導致錯誤的結(jié)果。
4、與Mutex同步
Mutex mutex = new Mutex();
mutex.WaitOne();
try
{
// Do some work...
}
finally
{
mutex.ReleaseMutex();
}
互斥體就像線程的紅綠燈。 它們確保一次只有一個線程可以訪問一段代碼,從而防止出現(xiàn)令人不快的意外情況。
用例:
- 保護代碼的關(guān)鍵部分免遭同時訪問。
- 跨多個線程同步操作。
5、使用BlockingCollection進行線程安全數(shù)據(jù)處理
BlockingCollection<int> data = new BlockingCollection<int>();
Task.Run(() =>
{
while (!data.IsCompleted)
{
int item;
if (data.TryTake(out item))
{
// Process item...
}
}
});
BlockingCollection<T> 提供了一種線程安全的方式來跨多個線程處理數(shù)據(jù)。 這就像為您的共享數(shù)據(jù)提供一個安全的保管庫。
用例:
- 實施生產(chǎn)者-消費者場景。
- 在多個線程之間安全地交換數(shù)據(jù)。
6、任務(wù)延續(xù) withContinueWith
Task<int> t = Task.Run(() => 42);
t.ContinueWith((antecedent) => Console.WriteLine(antecedent.Result));
任務(wù)延續(xù)允許您指定任務(wù)完成后應該發(fā)生的情況。 這就像設(shè)置一排多米諾骨牌,其中一個會觸發(fā)下一個。
用例:
- 任務(wù)完成時執(zhí)行操作。
- 創(chuàng)建依賴任務(wù)鏈。
7、任務(wù)中的異常處理
Task task = Task.Run(() => { throw new Exception("Oops!"); });
try
{
task.Wait();
}
catch (AggregateException ex)
{
Console.WriteLine(ex.InnerExceptions[0].Message); // Prints "Oops!"
}
如果任務(wù)中的異常處理不正確,可能會導致整個應用程序崩潰。 通過這個技巧,您可以優(yōu)雅地處理任務(wù)中的異常,就像處理一杯香檳一樣。
用例:
- 捕獲并處理任務(wù)中拋出的異常。
- 使您的應用程序能夠適應后臺任務(wù)中的錯誤。
8、ThreadLocal 的線程本地存儲
ThreadLocal<int> threadLocal = new ThreadLocal<int>(() => 42);
Console.WriteLine(threadLocal.Value); // Prints 42
ThreadLocal<T> 允許您定義每個線程唯一的數(shù)據(jù)。 這就像為每個線程提供了自己的私有存儲柜。
用例:
- 實現(xiàn)線程特定的數(shù)據(jù)以優(yōu)化性能。
- 存儲不應跨線程共享的狀態(tài)。
9、使用SemaphoreSlim限制并發(fā)
SemaphoreSlim semaphore = new SemaphoreSlim(2); // Limit to 2 threads
Task.Run(() =>
{
semaphore.Wait();
try
{
// Do some work...
}
finally
{
semaphore.Release();
}
});
信號量非常適合控制對容量有限的資源的訪問。 它就像夜總會的保鏢,控制可以進入的線程數(shù)量。
用例:
- 限制可以訪問資源的線程數(shù)量。
- 通過限制并發(fā)防止資源耗盡。
10、跨線程同步的手動重置事件
ManualResetEvent mre = new ManualResetEvent(false);
Task.Run(() =>
{
// Wait for the event to be set
mre.WaitOne();
// Do some work...
});
// Set the event
mre.Set();
手動重置事件是跨多個線程同步操作的絕佳工具。 它就像比賽中的發(fā)令槍,向所有線程發(fā)出開始運行的信號。
用例:
- 同步多個線程的啟動時間。
- 等待另一個線程滿足某個條件。
10 個集合片段
1、只讀集合
List<string> myList = new List<string> {"A", "B", "C"};
ReadOnlyCollection<string> myReadOnlyList = myList.AsReadOnly();
您可以使用 AsReadOnly 方法創(chuàng)建只讀集合。 這可以確保集合不會被意外修改,這在處理重要數(shù)據(jù)時至關(guān)重要。 就像博物館里的無價之寶一樣,它只能看,但不能觸摸!
用例:
- 當您想要共享集合但不希望它被修改時。
- 防止代碼中出現(xiàn)不必要的副作用。
2、隱式類型數(shù)組
var array = new[] { "A", "B", "C" };
您可以使用 new[] 關(guān)鍵字創(chuàng)建隱式類型數(shù)組。 這可以節(jié)省輸入并保持代碼干凈簡單。 這就像數(shù)組創(chuàng)建的洗碗機!
用例:
- 當你想創(chuàng)建一個內(nèi)聯(lián)數(shù)組時。
- 當數(shù)組的類型從上下文中顯而易見時。
3、隊列和堆棧
Queue<int> queue = new Queue<int>();
queue.Enqueue(1);
queue.Enqueue(2);
int first = queue.Dequeue();
Stack<int> stack = new Stack<int>();
stack.Push(1);
stack.Push(2);
int last = stack.Pop();
Queue 和 Stack 類提供了處理有序集合的有效方法。 隊列遵循“先進先出”(FIFO) 策略,堆棧遵循“后進先出”(LIFO) 策略。 這些非常適合模擬現(xiàn)實世界的情況,例如售票亭的隊列或一堆盤子。
用例:
- 當您需要實施 FIFO 或 LIFO 策略時。
- 模擬現(xiàn)實世界的情況。
4、用于快速查找的HashSet
HashSet<string> hashSet = new HashSet<string> { "A", "B", "C" };
bool containsA = hashSet.Contains("A"); // True
HashSet 是一個提供快速查找特定元素是否存在的集合。 它就像收藏界的 Google,只是速度更快!
用例:
- 當需要頻繁檢查集合是否包含某個元素時。
- 從集合中刪除重復項。
5、LINQ查詢
List<int> list = new List<int> { 1, 2, 3, 4, 5 };
IEnumerable<int> evenNumbers = list.Where(x => x % 2 == 0);
LINQ 提供了一種強大的聲明性方式來查詢集合。 只需一行代碼,您就可以進行過濾、排序、轉(zhuǎn)換等等。 這就像您的收藏有一位私人助理!
用例:
- 當需要對集合執(zhí)行復雜操作時。
- 對集合進行過濾或排序。
6、可觀察集合
ObservableCollection<string> collection = new ObservableCollection<string>();
collection.CollectionChanged += (s, e) => { /* Handle change */ };
collection.Add("A");
可觀察集合使您可以輕松地對集合中的更改做出反應。 這就像每當有人發(fā)布新的貓視頻時都會收到通知!
用例:
- 當您需要根據(jù)集合中的更改更新 UI 時。
- 記錄對集合的更改。
7、并發(fā)收集
ConcurrentDictionary<int, string> concurrentDictionary = new ConcurrentDictionary<int, string>();
System.Collections.Concurrent 命名空間提供了多個可以在多個線程中安全使用的集合。 這使您不必處理鎖和其他同步原語。 它就像一個預先打包的、無麻煩的多線程解決方案!
用例:
- 當需要從多個線程訪問集合時。
- 避免手動同步。
8、IComparer和IEqualityComparer接口
class MyComparer : IComparer<int>
{
public int Compare(int x, int y)
{
// Reverse order
return y.CompareTo(x);
}
}
List<int> list = new List<int> { 1, 2, 3, 4, 5 };
list.Sort(new MyComparer());
IComparer<T> 和 IEqualityComparer<T> 接口允許您自定義元素的比較方式以及它們是否被視為相等。 這就像決定自己的游戲規(guī)則一樣!
用例:
- 當您需要以特定方式對集合進行排序時。
- 根據(jù)特定標準比較元素。
9、使用GroupBy對元素進行分組
List<int> list = new List<int> { 1, 2, 3, 4, 5 };
var groups = list.GroupBy(x => x % 2 == 0 ? "Even" : "Odd");
GroupBy 方法允許您根據(jù)特定標準對元素進行分組。 這就像按顏色和尺寸整理襪子抽屜一樣!
用例:
- 當您需要根據(jù)特定標準對元素進行分組時。
- 對每個組分別進行操作。
10、AnyandAll方法
List<int> list = new List<int> { 1, 2, 3, 4, 5 };
bool anyEven = list.Any(x => x % 2 == 0); // True
bool allPositive = list.All(x => x > 0); // True
Any 和 All 方法提供了一種聲明性方式來檢查集合中的任何或所有元素是否滿足條件。 這就像快速檢查盒子里是否還有巧克力,或者籃子里的所有蘋果是否都熟了!
用例:
- 當您需要檢查任何或所有元素是否滿足條件時。
- 避免手動編寫循環(huán)。
10 個代表和活動片段
1、組播代表
Action<int> action1 = x => Console.WriteLine($"Action 1: {x}");
Action<int> action2 = x => Console.WriteLine($"Action 2: {x}");
Action<int> combined = action1 + action2;
combined(5); // Executes both actions
您可以將多個委托合并為一個多播委托。 這就像邀請所有朋友參加同一個聚會!
用例:
- 當你想通知多個監(jiān)聽者時。
- 簡化執(zhí)行多個回調(diào)的代碼。
2、弱事件模式
public class WeakEventHandler<TEventArgs>
{
private readonly WeakReference _targetReference;
private readonly MethodInfo _method;
public WeakEventHandler(EventHandler<TEventArgs> eventHandler)
{
_targetReference = new WeakReference(eventHandler.Target);
_method = eventHandler.Method;
}
public void Invoke(object sender, TEventArgs e)
{
if (_targetReference.IsAlive)
_method.Invoke(_targetReference.Target, new object[] { sender, e });
}
}
即使事件源仍然存在,弱事件模式也允許對偵聽器進行垃圾收集。 這就像在沒有人注意到的情況下離開聚會一樣!
用例:
- 當您想避免長期對象中的內(nèi)存泄漏時。
- 確保短命監(jiān)聽器不會延長監(jiān)聽器的壽命。
3、通用委托
public delegate TResult MyFunc<T1, T2, TResult>(T1 arg1, T2 arg2);
您可以定義適用于任何類型的通用委托。 它就像代表代表類型的瑞士軍刀!
用例:
- 當您需要一個適用于不同類型的委托時。
- 編寫更多可重用且類型安全的代碼。
4、具有自定義 EventArgs 的事件
public class MyEventArgs : EventArgs
{
public string Message { get; set; }
}
public class MyClass
{
public event EventHandler<MyEventArgs> MyEvent;
protected virtual void OnMyEvent(string message)
{
MyEvent?.Invoke(this, new MyEventArgs { Message = message });
}
}
您可以定義自定義 EventArgs 以提供有關(guān)事件的更多信息。 這就像發(fā)送詳細的報告而不是簡短的通知!
用例:
- 當您需要提供活動的附加信息時。
- 創(chuàng)建更具表現(xiàn)力和信息量的活動。
5、委托中的協(xié)變和逆變
Func<object> objectFunc = () => new object();
Func<string> stringFunc = objectFunc; // Covariance
Action<string> stringAction = str => Console.WriteLine(str);
Action<object> objectAction = stringAction; // Contravariance
協(xié)變和逆變允許您以保留類型兼容性的方式分配委托。 這就像將方釘安裝到圓孔中,但是以類型安全的方式!
用例:
- 當您需要互相分配代表時。
- 創(chuàng)建更靈活且可重用的委托代碼。
6、匿名代表
Func<int, int> square = delegate(int x) { return x * x; };
您可以匿名定義委托,而無需聲明單獨的方法。 這就像創(chuàng)建一家快閃店而不是一家永久性商店!
用例:
- 當您想內(nèi)聯(lián)定義委托時。
- 讓委托代碼靠近使用它的地方。
7、異步委托
Func<int, int> slowFunc = x => { Thread.Sleep(1000); return x * x; };
IAsyncResult asyncResult = slowFunc.BeginInvoke(5, null, null);
// Do other work...
int result = slowFunc.EndInvoke(asyncResult); // Waits for the result
您可以使用 BeginInvoke 和 EndInvoke 方法異步執(zhí)行委托。 這就像寫信而不是打電話一樣!
用例:
- 當您需要執(zhí)行長時間運行的操作時。
- 讓您的 UI 保持響應能力。
8、委托作為實例變量
class MyClass
{
private Func<int, int> _myFunc = x => x * x;
public void SetFunc(Func<int, int> func)
{
_myFunc = func;
}
public int Compute(int x)
{
return _myFunc(x);
}
}
您可以使用委托作為實例變量來創(chuàng)建高度可定制的類。 這就像在汽車行駛時更換發(fā)動機一樣!
用例:
- 當您需要自定義類的行為時。
- 創(chuàng)建靈活且可擴展的類。
9、EventHandler委托
public class MyClass
{
public event EventHandler<string> MyEvent;
protected virtual void OnMyEvent(string value)
{
MyEvent?.Invoke(this, value);
}
}
EventHandler<T> 委托提供了聲明事件的標準方法。 這就像在活動中普遍接受的握手!
用例:
- 當你需要聲明一個事件時。
- 確保您的事件與 .NET 約定兼容。
10、代表表達
Func<int, bool> isEven = x => x % 2 == 0;
List<int> numbers = Enumerable.Range(0, 10).ToList();
List<int> evenNumbers = numbers.Where(isEven).ToList();
委托是封裝表達式并傳遞它們的好方法。 這就像在你的口袋里攜帶一個便攜式數(shù)學方程!
用例:
- 當您需要傳遞復雜的表達式時。
- 讓您的代碼更具表現(xiàn)力和靈活性。
10 個異常處理片段
1、Try-Catch-Finally 語句
try
{
// Potentially dangerous code here...
}
catch (SpecificException ex)
{
// Handle a specific exception
}
catch
{
// Handle any other exceptions
}
finally
{
// Cleanup code that always executes
}
經(jīng)典的 try-catch-finally 語句。 它就像一張安全網(wǎng),可以防止任何意外的空中飛人跌倒!
用例:
- 執(zhí)行可能拋出異常的代碼時。
- 確保清理代碼始終運行。
2、拋出新的異常
catch (Exception ex)
{
throw new MyException("Something bad happened", ex);
}
使用附加信息重新引發(fā)異常。 這就像退回有缺陷的產(chǎn)品,但附有投訴信!
用例:
- 當您需要向異常添加附加信息時。
- 創(chuàng)建詳細的異常歷史記錄。
3、過濾異常
catch (Exception ex) when (ex.Message.Contains("specific"))
{
// Handle the exception
}
根據(jù)條件過濾異常。 它就像一個例外的保鏢,只允許某些人進入!
用例:
- 當你只想處理某些異常時。
- 創(chuàng)建更具可讀性和更高效的異常處理代碼。
4、內(nèi)部異常
catch (Exception ex)
{
Console.WriteLine(ex.InnerException);
}
訪問異常的內(nèi)部異常。 就像剝洋蔥,露出它的層一樣!
用例:
- 當您需要發(fā)現(xiàn)異常的根本原因時。
- 顯示或記錄更詳細的異常信息。
5、聚合異常
try
{
// Parallel or async code that throws multiple exceptions...
}
catch (AggregateException ae)
{
ae.Handle(ex =>
{
// Handle each exception
return true;
});
}
處理從并行或異步代碼引發(fā)的多個異常。 就像一張網(wǎng)捕捉一群蜜蜂一樣!
用例:
- 執(zhí)行可能引發(fā)多個異常的并行或異步代碼時。
- 單獨處理每個異常。
6、非捕獲異常處理程序
try
{
// Dangerous code...
}
catch (Exception ex) when (LogException(ex))
{
}
bool LogException(Exception ex)
{
// Log the exception and return false
return false;
}
記錄異常而不捕獲它們。 就像閉路電視攝像機觀察一切但不干預!
用例:
- 當您需要記錄異常但允許它們傳播時。
- 監(jiān)視代碼中的異常。
7、ExceptionDispatchInfo類
ExceptionDispatchInfo capturedException;
try
{
// Dangerous code...
}
catch (Exception ex)
{
capturedException = ExceptionDispatchInfo.Capture(ex);
}
// Later...
capturedException?.Throw();
捕獲并重新拋出異常,同時保留原始堆棧跟蹤。 這就像一個例外的時間膠囊!
用例:
- 當您需要跨線程或異步方法拋出異常時。
- 保留異常的原始堆棧跟蹤。
8、自定義例外
public class MyException : Exception
{
public MyException(string message) : base(message) { }
public MyException(string message, Exception inner) : base(message, inner) { }
}
為特定錯誤場景創(chuàng)建自定義異常。 這就像為特定的亡命徒制作一張通緝海報!
用例:
- 當您需要在代碼中表示特定的錯誤條件時。
- 創(chuàng)建更具表現(xiàn)力和更詳細的例外。
9、檢查異常來源
catch (Exception ex)
{
if (ex.Source == "MyAssembly")
{
// Handle the exception
}
}
檢查異常的來源。 這就像追蹤電話的來源一樣!
用例:
- 當您需要處理來自特定來源的異常時。
- 區(qū)分來自不同程序集或類的異常。
10、MVC中的OnException方法
public class MyController : Controller
{
protected override void OnException(ExceptionContext filterContext)
{
// Handle exceptions for the entire controller
}
}
處理整個 MVC 控制器的異常。 就像建筑物的安全檢查員一樣!
用例:
- 當您想要處理 MVC 控制器中的所有異常時。
- 將異常處理代碼集中在 MVC 應用程序中。