C#数组操作实战:从求和到滑动窗口的22个经典练习(附完整代码)
C#数组与字符串算法实战:22个核心技巧精解
数组和字符串操作是C#开发者的基本功,也是面试和实际项目中的高频考点。本文将带你系统掌握从基础遍历到高级算法的22个核心技巧,每个案例都配有可运行的代码示例和工程应用场景分析。
1. 基础操作与数学计算
1.1 数组元素聚合运算
数组求和、求积和平均值是最基础的操作,但在实际项目中经常用于数据统计。下面是一个优化的聚合运算实现:
public static class ArrayOperations
{
public static int Sum(int[] arr) => arr.Aggregate(0, (acc, x) => acc + x);
public static long Product(int[] arr) =>
arr.Aggregate(1L, (acc, x) => acc * x);
public static double Average(int[] arr) =>
arr.Length == 0 ? 0 : (double)Sum(arr) / arr.Length;
}
工程应用:电商平台计算订单总金额、商品平均评分等场景。
1.2 极值查找与条件筛选
查找数组中的极值和满足条件的元素是常见需求:
public static (int min, int max) FindMinMax(int[] arr)
{
if (arr == null || arr.Length == 0)
throw new ArgumentException("数组不能为空");
int min = arr[0], max = arr[0];
for (int i = 1; i < arr.Length; i++)
{
min = Math.Min(min, arr[i]);
max = Math.Max(max, arr[i]);
}
return (min, max);
}
public static int[] FilterEvens(int[] arr) =>
arr.Where(x => x % 2 == 0).ToArray();
提示:使用LINQ可以简化代码,但在性能关键场景建议使用原生循环
2. 数组与字符串变换
2.1 反转操作的艺术
数组和字符串反转有多种实现方式,各有适用场景:
| 方法 | 时间复杂度 | 空间复杂度 | 适用场景 |
|---|---|---|---|
| Array.Reverse | O(n) | O(1) | 简单反转 |
| 双指针法 | O(n) | O(1) | 原地修改 |
| LINQ Reverse | O(n) | O(n) | 需要新对象 |
// 双指针反转数组
public static void ReverseArray(int[] arr)
{
for (int i = 0, j = arr.Length - 1; i < j; i++, j--)
{
(arr[i], arr[j]) = (arr[j], arr[i]);
}
}
// 字符串反转扩展方法
public static string Reverse(this string s) =>
string.Concat(s.Reverse());
2.2 回文检测优化技巧
回文检测需要考虑大小写和标点符号:
public static bool IsPalindrome(string s)
{
s = new string(s.Where(char.IsLetterOrDigit).ToArray())
.ToLowerInvariant();
return s == s.Reverse();
}
性能优化:对于超长字符串,可以提前终止比较:
for (int i = 0; i < s.Length / 2; i++)
{
if (s[i] != s[s.Length - 1 - i])
return false;
}
return true;
3. 算法思维训练
3.1 两数之和的多种解法
给定数组和目标值,找出两数之和等于目标值的索引:
// 暴力解法 O(n²)
public static (int, int) TwoSumBruteForce(int[] nums, int target)
{
for (int i = 0; i < nums.Length; i++)
for (int j = i + 1; j < nums.Length; j++)
if (nums[i] + nums[j] == target)
return (i, j);
throw new Exception("No solution");
}
// 哈希表优化 O(n)
public static (int, int) TwoSumOptimized(int[] nums, int target)
{
var dict = new Dictionary<int, int>();
for (int i = 0; i < nums.Length; i++)
{
int complement = target - nums[i];
if (dict.TryGetValue(complement, out int index))
return (index, i);
dict[nums[i]] = i;
}
throw new Exception("No solution");
}
3.2 滑动窗口算法精要
滑动窗口是处理子串/子数组问题的利器,典型应用如求最长无重复字符子串:
public static int LongestUniqueSubstring(string s)
{
var lastIndex = new Dictionary<char, int>();
int maxLen = 0, start = 0;
for (int end = 0; end < s.Length; end++)
{
if (lastIndex.TryGetValue(s[end], out int index))
start = Math.Max(start, index + 1);
lastIndex[s[end]] = end;
maxLen = Math.Max(maxLen, end - start + 1);
}
return maxLen;
}
窗口模板:
- 初始化左右指针
- 移动右指针扩展窗口
- 满足条件时移动左指针收缩窗口
- 更新结果
4. 高级数据结构应用
4.1 矩阵旋转的位运算优化
N×N矩阵顺时针旋转90度的最优解:
public static void RotateMatrix(int[,] matrix)
{
int n = matrix.GetLength(0);
for (int layer = 0; layer < n / 2; layer++)
{
int first = layer;
int last = n - 1 - layer;
for (int i = first; i < last; i++)
{
int offset = i - first;
int top = matrix[first, i];
// 左→上
matrix[first, i] = matrix[last-offset, first];
// 下→左
matrix[last-offset, first] = matrix[last, last-offset];
// 右→下
matrix[last, last-offset] = matrix[i, last];
// 上→右
matrix[i, last] = top;
}
}
}
4.2 栈的经典应用:括号匹配
使用栈检查括号序列有效性:
public static bool IsValidParentheses(string s)
{
var stack = new Stack<char>();
var pairs = new Dictionary<char, char>
{
[')'] = '(',
[']'] = '[',
['}'] = '{'
};
foreach (char c in s)
{
if (pairs.ContainsValue(c))
stack.Push(c);
else if (stack.Count == 0 || stack.Pop() != pairs[c])
return false;
}
return stack.Count == 0;
}
变体问题:计算最长有效括号子串长度:
public static int LongestValidParentheses(string s)
{
var stack = new Stack<int>();
stack.Push(-1);
int max = 0;
for (int i = 0; i < s.Length; i++)
{
if (s[i] == '(')
stack.Push(i);
else
{
stack.Pop();
if (stack.Count == 0)
stack.Push(i);
else
max = Math.Max(max, i - stack.Peek());
}
}
return max;
}
5. 字符串处理进阶
5.1 字符串压缩算法对比
不同压缩算法的实现与选择:
// 基础压缩
public static string CompressBasic(string s)
{
if (string.IsNullOrEmpty(s)) return s;
var sb = new StringBuilder();
int count = 1;
for (int i = 1; i <= s.Length; i++)
{
if (i < s.Length && s[i] == s[i-1])
count++;
else
{
sb.Append(s[i-1]).Append(count);
count = 1;
}
}
return sb.Length < s.Length ? sb.ToString() : s;
}
// 优化版(仅存储字符)
public static string CompressOptimized(string s)
{
var sb = new StringBuilder();
int count = 0;
for (int i = 0; i < s.Length; i++)
{
count++;
if (i == s.Length - 1 || s[i] != s[i+1])
{
sb.Append(s[i]);
if (count > 1) sb.Append(count);
count = 0;
}
}
return sb.ToString();
}
5.2 最长公共前缀的二分查找解法
传统解法与优化解法的对比:
// 水平扫描法
public static string LongestCommonPrefix(string[] strs)
{
if (strs.Length == 0) return "";
string prefix = strs[0];
for (int i = 1; i < strs.Length; i++)
{
while (strs[i].IndexOf(prefix) != 0)
{
prefix = prefix[..^1];
if (string.IsNullOrEmpty(prefix)) return "";
}
}
return prefix;
}
// 二分查找优化
public static string LongestCommonPrefixBinary(string[] strs)
{
if (strs.Length == 0) return "";
int minLen = strs.Min(s => s.Length);
int low = 1, high = minLen;
while (low <= high)
{
int mid = (low + high) / 2;
if (IsCommonPrefix(strs, mid))
low = mid + 1;
else
high = mid - 1;
}
return strs[0][..((low + high) / 2)];
}
private static bool IsCommonPrefix(string[] strs, int len)
{
string prefix = strs[0][..len];
return strs.All(s => s.StartsWith(prefix));
}
6. 实战技巧与性能优化
6.1 避免装箱拆箱
值类型操作中的性能陷阱:
// 不好的写法(有装箱)
ArrayList list = new ArrayList();
list.Add(1); // 装箱
int num = (int)list[0]; // 拆箱
// 优化写法(使用泛型)
List<int> genericList = new List<int>();
genericList.Add(1); // 无装箱
int num = genericList[0]; // 无拆箱
6.2 字符串拼接优化
不同拼接方式的性能对比(单位:毫秒):
| 方法 | 100次 | 1000次 | 10000次 |
|---|---|---|---|
| +操作符 | 0.12 | 3.45 | 280.5 |
| StringBuilder | 0.08 | 0.15 | 1.2 |
| string.Concat | 0.05 | 0.3 | 25.4 |
// 推荐写法
var sb = new StringBuilder();
for (int i = 0; i < 10000; i++)
sb.Append(i.ToString());
string result = sb.ToString();
6.3 数组与集合的选择
不同数据结构的特性对比:
| 结构 | 随机访问 | 插入删除 | 内存使用 | 适用场景 |
|---|---|---|---|---|
| 数组 | O(1) | O(n) | 紧凑 | 固定大小数据 |
| List | O(1) | O(n) | 动态 | 频繁增删 |
| LinkedList | O(n) | O(1) | 较高 | 频繁插入删除 |
// 预分配数组大小
int[] arr = new int[100];
// 动态扩容List
var list = new List<int>(100); // 建议设置初始容量
7. 工程实践与异常处理
7.1 防御性编程实践
健壮的数组操作需要考虑各种边界条件:
public static int SafeArrayAccess(int[] arr, int index)
{
if (arr == null)
throw new ArgumentNullException(nameof(arr));
if (index < 0 || index >= arr.Length)
throw new IndexOutOfRangeException(
$"Index {index} out of range [0, {arr.Length - 1}]");
return arr[index];
}
7.2 自定义异常设计
为特定业务场景创建专属异常:
public class InvalidArrayOperationException : Exception
{
public int ErrorCode { get; }
public string Operation { get; }
public InvalidArrayOperationException(
string message, int code, string operation)
: base(message)
{
ErrorCode = code;
Operation = operation;
}
}
// 使用示例
throw new InvalidArrayOperationException(
"Array size mismatch", 1001, "Matrix multiplication");
8. 单元测试与调试技巧
8.1 为数组算法编写测试
使用xUnit测试框架示例:
public class ArrayTests
{
[Theory]
[InlineData(new[] {1,2,3}, 6)]
[InlineData(new[] {5}, 5)]
[InlineData(new int[0], 0)]
public void SumArray_ShouldReturnCorrectSum(int[] input, int expected)
{
int actual = ArrayOperations.Sum(input);
Assert.Equal(expected, actual);
}
[Fact]
public void ReverseArray_ShouldHandleNull()
{
int[] arr = null;
Assert.Throws<ArgumentNullException>(() => ArrayOperations.Reverse(arr));
}
}
8.2 调试复杂算法的技巧
使用Visual Studio调试器的进阶功能:
- 条件断点:右键断点→条件
- 数据断点:调试→窗口→断点→新建数据断点
- 即时窗口:调试时输入表达式求值
- 内存窗口:查看数组内存布局
// 调试示例:观察滑动窗口变化
var window = new List<int>();
for (int i = 0; i < nums.Length; i++)
{
// 在此处设置条件断点:i > 3
window.Add(nums[i]);
if (window.Count > k)
window.RemoveAt(0);
}
9. 性能分析与优化
9.1 基准测试工具使用
使用BenchmarkDotNet进行性能测试:
[MemoryDiagnoser]
public class AlgorithmBenchmarks
{
private readonly int[] data = Enumerable.Range(1, 1000).ToArray();
[Benchmark]
public int LinqSum() => data.Sum();
[Benchmark]
public int ManualSum()
{
int sum = 0;
foreach (int num in data) sum += num;
return sum;
}
}
// 输出结果:
// | Method | Mean | Error | StdDev | Allocated |
// |---------- |---------:|---------:|---------:|----------:|
// | LinqSum | 1.234 us | 0.0234 us | 0.0207 us | 32 B |
// | ManualSum | 0.543 us | 0.0102 us | 0.0096 us | - |
9.2 算法复杂度实战分析
常见算法的时间复杂度对比:
// O(1) - 常数时间
int GetFirst(int[] arr) => arr[0];
// O(log n) - 二分查找
int BinarySearch(int[] arr, int target)
{
int left = 0, 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;
}
// O(n²) - 冒泡排序
void BubbleSort(int[] arr)
{
for (int i = 0; i < arr.Length - 1; i++)
for (int j = 0; j < arr.Length - i - 1; j++)
if (arr[j] > arr[j + 1])
(arr[j], arr[j + 1]) = (arr[j + 1], arr[j]);
}
10. 跨语言对比与选择
10.1 C#与Python数组操作对比
相同算法的不同语言实现差异:
# Python实现两数之和
def two_sum(nums, target):
seen = {}
for i, num in enumerate(nums):
complement = target - num
if complement in seen:
return (seen[complement], i)
seen[num] = i
return None
关键区别:
- Python使用字典而非泛型Dictionary
- 没有类型声明,更简洁但缺乏类型安全
- enumerate替代C#的for循环索引
10.2 何时选择C#处理数组
适合使用C#的场景:
- 需要强类型检查和编译时验证
- 处理大型数值数据集(性能优势)
- 与.NET生态集成(如ASP.NET、Entity Framework)
- 需要多线程处理的场景(Task Parallel Library)
11. 设计模式应用
11.1 策略模式实现多种排序
将排序算法封装为可互换的策略:
public interface ISortStrategy
{
void Sort(int[] arr);
}
public class BubbleSort : ISortStrategy { /* 实现 */ }
public class QuickSort : ISortStrategy { /* 实现 */ }
public class ArraySorter
{
private ISortStrategy _strategy;
public ArraySorter(ISortStrategy strategy) => _strategy = strategy;
public void SetStrategy(ISortStrategy strategy) => _strategy = strategy;
public void Sort(int[] arr) => _strategy.Sort(arr);
}
// 使用
var sorter = new ArraySorter(new BubbleSort());
sorter.Sort(data);
sorter.SetStrategy(new QuickSort());
sorter.Sort(data);
11.2 迭代器模式处理多维数组
实现自定义的数组遍历方式:
public class MatrixIterator : IEnumerable<int>
{
private readonly int[,] _matrix;
public MatrixIterator(int[,] matrix) => _matrix = matrix;
public IEnumerator<int> GetEnumerator()
{
for (int i = 0; i < _matrix.GetLength(0); i++)
for (int j = 0; j < _matrix.GetLength(1); j++)
yield return _matrix[i, j];
}
IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
}
// 使用
var matrix = new int[3,3] { {1,2,3}, {4,5,6}, {7,8,9} };
foreach (int num in new MatrixIterator(matrix))
Console.WriteLine(num);
12. 并发与并行处理
12.1 并行数组操作
使用Parallel类加速数组处理:
public static void ParallelArrayOperations(int[] arr)
{
// 并行初始化数组
Parallel.For(0, arr.Length, i => arr[i] = i * 2);
// 并行求和
long sum = 0;
Parallel.ForEach(arr, num => Interlocked.Add(ref sum, num));
// 并行转换
Parallel.For(0, arr.Length, i => arr[i] = (int)Math.Sqrt(arr[i]));
}
注意:并行操作适合CPU密集型任务,对于简单操作可能因线程开销反而变慢
12.2 线程安全集合使用
并发环境下的集合选择:
// 线程安全字典
var concurrentDict = new ConcurrentDictionary<int, string>();
Parallel.For(0, 100, i => concurrentDict[i] = i.ToString());
// 阻塞集合
var blockingCollection = new BlockingCollection<int>();
Task.Run(() =>
{
foreach (var item in blockingCollection.GetConsumingEnumerable())
Console.WriteLine(item);
});
Parallel.For(0, 100, i => blockingCollection.Add(i));
blockingCollection.CompleteAdding();
13. 内存优化技巧
13.1 ArrayPool减少GC压力
使用数组池重用数组内存:
var pool = ArrayPool<int>.Shared;
int[] array = pool.Rent(1024); // 从池中获取数组
try
{
// 使用array...
for (int i = 0; i < array.Length; i++)
array[i] = i;
}
finally
{
pool.Return(array); // 归还到池中
}
13.2 Span高效内存访问
使用Span减少内存分配:
int[] arr = { 1, 2, 3, 4, 5 };
Span<int> span = arr.AsSpan();
// 切片操作不分配新数组
Span<int> slice = span.Slice(1, 3);
// 栈上分配
Span<int> stackSpan = stackalloc int[10];
for (int i = 0; i < stackSpan.Length; i++)
stackSpan[i] = i;
14. 实际项目案例
14.1 电商价格分析系统
典型数组操作场景:
public class PriceAnalyzer
{
public (decimal min, decimal max, decimal avg) AnalyzePrices(decimal[] prices)
{
if (prices == null || prices.Length == 0)
throw new ArgumentException("价格数据不能为空");
decimal min = prices[0], max = prices[0], sum = 0;
foreach (var price in prices)
{
min = Math.Min(min, price);
max = Math.Max(max, price);
sum += price;
}
return (min, max, sum / prices.Length);
}
public int[] FindPromotionDays(decimal[] dailySales, decimal threshold)
{
var days = new List<int>();
for (int i = 0; i < dailySales.Length; i++)
if (dailySales[i] > threshold)
days.Add(i + 1); // 第几天
return days.ToArray();
}
}
14.2 游戏开发中的数组应用
游戏状态管理示例:
public class GameBoard
{
private readonly int[,] _cells;
private readonly int _size;
public GameBoard(int size)
{
_size = size;
_cells = new int[size, size];
}
public void Randomize()
{
var rnd = new Random();
for (int i = 0; i < _size; i++)
for (int j = 0; j < _size; j++)
_cells[i, j] = rnd.Next(0, 2); // 0或1
}
public int CountAliveNeighbors(int x, int y)
{
int count = 0;
for (int i = Math.Max(0, x-1); i <= Math.Min(_size-1, x+1); i++)
for (int j = Math.Max(0, y-1); j <= Math.Min(_size-1, y+1); j++)
if (!(i == x && j == y) && _cells[i, j] == 1)
count++;
return count;
}
}
15. 前沿技术展望
15.1 SIMD指令加速数组运算
使用System.Numerics进行向量化计算:
public static unsafe float SimdSum(float[] arr)
{
int vectorSize = Vector<float>.Count;
var accVector = Vector<float>.Zero;
int i = 0;
// 向量化部分
for (; i <= arr.Length - vectorSize; i += vectorSize)
{
var v = new Vector<float>(arr, i);
accVector += v;
}
// 剩余部分
float result = 0;
for (; i < arr.Length; i++)
result += arr[i];
// 累加向量中的元素
for (int j = 0; j < vectorSize; j++)
result += accVector[j];
return result;
}
15.2 机器学习中的数组应用
使用ML.NET处理数据:
var data = new List<InputData>();
// 填充数据...
var context = new MLContext();
var pipeline = context.Transforms
.Concatenate("Features", nameof(InputData.Features))
.Append(context.Regression.Trainers.Sdca(
labelColumnName: nameof(InputData.Label)));
var model = pipeline.Fit(context.Data.LoadFromEnumerable(data));
16. 调试与问题排查
16.1 常见数组越界问题
典型错误模式及修复:
// 错误写法
for (int i = 0; i <= arr.Length; i++) // 应该使用 < 而不是 <=
Console.WriteLine(arr[i]);
// 正确写法
for (int i = 0; i < arr.Length; i++)
Console.WriteLine(arr[i]);
// 多维数组错误
int[,] matrix = new int[3,3];
for (int i = 0; i <= matrix.GetLength(0); i++) // 错误
for (int j = 0; j <= matrix.GetLength(1); j++) // 错误
matrix[i,j] = i + j;
16.2 性能问题诊断
使用Stopwatch分析代码:
var sw = new Stopwatch();
sw.Start();
// 测试代码
var arr = new int[1000000];
for (int i = 0; i < arr.Length; i++)
arr[i] = i * 2;
sw.Stop();
Console.WriteLine($"耗时: {sw.ElapsedMilliseconds}ms");
17. 编码规范与最佳实践
17.1 数组命名与使用准则
| 规范类型 | 不良实践 | 推荐实践 |
|---|---|---|
| 命名 | int[] a | int[] studentScores |
| 初始化 | int[] arr; | int[] arr = new int[10]; |
| 长度检查 | if(arr != null) | if(arr?.Length > 0) |
| 遍历 | for(int i=0;i<10;i++) | foreach(var item in arr) |
17.2 异常处理原则
健壮的数组操作异常处理:
public void ProcessArray(int[] arr)
{
try
{
if (arr == null) throw new ArgumentNullException(nameof(arr));
if (arr.Length == 0) throw new ArgumentException("数组不能为空");
// 业务逻辑...
}
catch (IndexOutOfRangeException ex)
{
Console.WriteLine($"数组越界: {ex.Message}");
throw; // 重新抛出
}
catch (Exception ex)
{
Console.WriteLine($"处理失败: {ex.Message}");
throw new ArrayProcessingException("处理失败", ex);
}
}
18. 扩展方法与LINQ技巧
18.1 有用的数组扩展方法
创建自定义扩展方法:
public static class ArrayExtensions
{
public static void Shuffle<T>(this T[] array)
{
var rng = new Random();
int n = array.Length;
while (n > 1)
{
int k = rng.Next(n--);
(array[n], array[k]) = (array[k], array[n]);
}
}
public static T[] Slice<T>(this T[] source, int start, int length)
{
var slice = new T[length];
Array.Copy(source, start, slice, 0, length);
return slice;
}
}
// 使用
var numbers = Enumerable.Range(1, 10).ToArray();
numbers.Shuffle();
var subArray = numbers.Slice(2, 5);
18.2 LINQ高级查询技巧
复杂数组查询示例:
var salesData = new[]
{
new { Month = "Jan", Amount = 1000 },
new { Month = "Feb", Amount = 1500 },
// ...
};
// 多条件分组
var query = salesData
.GroupBy(s => s.Amount > 1200 ? "High" : "Low")
.Select(g => new { Category = g.Key, Total = g.Sum(x => x.Amount) });
// 滑动窗口平均值
int windowSize = 3;
var movingAvg = Enumerable.Range(0, salesData.Length - windowSize + 1)
.Select(i => salesData
.Skip(i)
.Take(windowSize)
.Average(x => x.Amount));
19. 跨平台注意事项
19.1 不同运行时中的数组差异
.NET Framework vs .NET Core差异:
| 特性 | .NET Framework | .NET Core |
|---|---|---|
| 默认数组大小上限 | 2GB | 取决于系统 |
| Array.Sort算法 | 快速排序 | 内省排序 |
| 空数组处理 | 可能返回null | 总是返回空数组 |
19.2 序列化兼容性问题
JSON序列化时的数组处理:
var arr = new int[] { 1, 2, 3 };
// System.Text.Json (推荐)
string json = JsonSerializer.Serialize(arr);
int[] deserialized = JsonSerializer.Deserialize<int[]>(json);
// Newtonsoft.Json (旧项目)
string json = JsonConvert.SerializeObject(arr);
int[] deserialized = JsonConvert.DeserializeObject<int[]>(json);
20. 可视化与调试辅助
20.1 数组内容可视化输出
创建友好的数组显示格式:
public static string ToMatrixString<T>(this T[,] matrix, string delimiter = "\t")
{
var sb = new StringBuilder();
for (int i = 0; i < matrix.GetLength(0); i++)
{
for (int j = 0; j < matrix.GetLength(1); j++)
sb.Append(matrix[i, j]).Append(delimiter);
sb.AppendLine();
}
return sb.ToString();
}
// 使用
var matrix = new int[3,3] { {1,2,3}, {4,5,6}, {7,8,9} };
Console.WriteLine(matrix.ToMatrixString());
20.2 调试时查看复杂结构
使用DebuggerDisplay特性:
[DebuggerDisplay("Count = {Count}")]
public class CustomArray<T>
{
private readonly T[] _items;
public CustomArray(int size) => _items = new T[size];
public int Count => _items.Length;
[DebuggerBrowsable(DebuggerBrowsableState.RootHidden)]
public T[] Items => _items;
}
21. 安全编码实践
21.1 输入验证模式
安全的数组处理方法:
public static void ProcessUserInput(int[] userInput)
{
// 验证null
if (userInput == null)
throw new ArgumentNullException(nameof(userInput));
// 验证大小
const int maxSize = 1000;
if (userInput.Length > maxSize)
throw new ArgumentException($"输入数组不能超过{maxSize}个元素");
// 验证内容
for (int i = 0; i < userInput.Length; i++)
{
if (userInput[i] < 0)
throw new ArgumentException($"第{i}个元素不能为负数");
}
// 安全处理...
}
21.2 防止缓冲区溢出
安全复制数组的方法:
public static void SafeCopy(int[] source, int[] destination)
{
if (source == null || destination == null)
throw new ArgumentNullException();
// 计算实际可复制的长度
int length = Math.Min(source.Length, destination.Length);
if (length == 0) return;
Array.Copy(source, destination, length);
}
22. 性能关键代码优化
22.1 避免边界检查
使用unsafe代码提升性能:
public static unsafe int UnsafeSum(int[] arr)
{
int sum = 0;
fixed (int* ptr = arr)
{
for (int i = 0; i < arr.Length; i++)
sum += ptr[i]; // 不进行边界检查
}
return sum;
}
警告:unsafe代码需要特别小心,仅用于性能关键路径
22.2 内存局部性优化
优化数据访问模式:
// 不好的访问模式(列优先)
for (int j = 0; j < cols; j++)
for (int i = 0; i < rows; i++)
matrix[i, j] = ComputeValue();
// 好的访问模式(行优先)
for (int i = 0; i < rows; i++)
for (int j = 0; j < cols; j++)
matrix[i, j] = ComputeValue();
原理:现代CPU缓存对顺序访问更友好
更多推荐
所有评论(0)