C#常用函数
重要文件操作
逐行读取
下代码为逐行读取到List集合中
List<string> lines = new List<string>();
using (StreamReader reader = new StreamReader(datafile))
{
string line;
while ((line = reader.ReadLine()) != null)
{
lines.Add(line);
}
}
全部写入
string result = "我的报告...\n完成啦...\n"; // \n是换行
StreamWriter sw = new StreamWriter(FileName);
sw.Write(result);
sw.Flush();
重要字符串操作
按字符裁剪字符串
Split函数的参数是按哪个字符裁剪字符串,返回裁剪完的数组
string input = "Hello, World!";
string[] splited = input.Split(',');
按位置裁取字字符串
Substring函数第一个参数为裁剪开始位置,第二个参数为裁剪长度
string input = "Hello, World!";
string subString = input.Substring(7, 5);
字符串转int、double
想转换为哪种类型,就用哪种类型.Parse。
string intStr = "123";
int intValue = int.Parse(intStr);
string doubleStr = "3.14";
double doubleValue = double.Parse(doubleStr);
double保留指定位数小数转字符串
如F5为保留五位小数,F2为保留两位小数
double pi = 3.1415926535;
string str = pi.ToSring("F5"); // 保留五位小数
WinForm常用组件操作
文件选择器
打开文件
OpenFileDialog ofd = new OpenFileDialog();
ofd.Title = "打开文件";
ofd.Filter = "文本文件|*.txt";
if (ofd.ShowDialog() == DialogResult.OK)
{
string filePath = ofd.FileName;
}
保存文件
SaveFileDialog sf = new SaveFileDialog();
sf.Title = "选择保存路径";
sf.Filter = "文本数据|*.txt";
sf.FileName = "result";
if(sf.ShowDialog()==DialogResult.OK)
{
StreamWriter sw = new StreamWriter(sf.FileName);
sw.Write(report);
sw.Flush();
}
富文本框
// 设置文本
richTextBox1.Text = "这是一段普通文本";
// 追加文本
richTextBox1.AppendText("\n这是追加的文本");
// 获取文本
string content = richTextBox1.Text;
// 清空文本
richTextBox1.Clear();
表
// 添加列
dataGridView1.Columns.Add("Column1", "点名");
dataGridView1.Columns.Add("Column2", "x");
dataGridView1.Columns.Add("Column3", "y");
// 添加行
dataGridView1.Rows.Add("K1", 100, 200);
// 设置单元格值
dataGridView1.Rows[0].Cells[0].Value = "张三丰";
// 获取单元格值
string name = dataGridView1.Rows[0].Cells[0].Value.ToString();
int age = Convert.ToInt32(dataGridView1.Rows[0].Cells[1].Value);
图表区
// 清空图表
chart1.Series.Clear();
chart1.ChartAreas.Clear();
// 添加ChartArea
ChartArea chartArea = chart1.ChartAreas.Add("Default");
// 设置X轴范围
chartArea.AxisX.Minimum = 2630; // X轴最小值
chartArea.AxisX.Maximum = 2770; // X轴最大值
// 设置Y轴范围
chartArea.AxisY.Minimum = 520; // Y轴最小值
chartArea.AxisY.Maximum = 640; // Y轴最大值
// 添加点Series
Series points = chart1.Series.Add("顶点");
points.ChartType = SeriesChartType.Point;
points.Color = Color.Red;
points.MarkerSize = 8;
points.MarkerStyle = MarkerStyle.Circle;
// 添加线Series
Series line = chart1.Series.Add("边");
line.ChartType = SeriesChartType.Line;
line.Color = Color.Blue;
line.BorderWidth = 2;
foreach (Point p in pointDatas.getPoints())
{
// 画一个带标记的点
points.Points[points.Points.AddXY(p.x, p.y)].Label = p.name;
//画一个无标记的点
points.Points.AddXY(p.x, p.y)
}
foreach (Triangle.Edge edge in pointDatas.getEdges())
{
// 两点画一条线
line.Points.AddXY(edge.p1.x, edge.p1.y);
line.Points.AddXY(edge.p2.x, edge.p2.y);
line.Points.AddXY(double.NaN, double.NaN); // 截断线
}
常用数据结构和排序方法
List
List集合有序(插入顺序),元素可重复,可索引元素
List<string> lines = new List<string>();
lines.Add("aaa"); // 添加元素
lines.Remove("aaa"); // 删除元素
lines.Contains("aaa"); // 判断是否存在
lines.Count; // 元素数量
string str = lines[0]; // 根据索引访问元素
foreach(var str in lines) {
// 遍历集合
}
HashSet
HashSet集合无序(不维护顺序),元素不重复
HashSet<string> set = new HashSet<string>();
set.Add("aaa"); // 添加元素
set.Remove("aaa"); // 删除元素
set.Contains("aaa"); // 判断是否存在
set.Count; // 元素数量
foreach(var str in set) {
// 遍历集合
}
SortSet
SortedSet集合有序(根据元素排序),元素不重复。其中元素需要为数值或者实现IComparable<T>接口。
SortedSet<int> set = new SortedSet<int>();
set.Add(11); // 添加元素
set.Remove(11); // 删除元素
set.Contains(11); // 判断是否存在
set.Count; // 元素数量
foreach(var a in set) {
// 遍历集合
}
Dictionary
字典是一种键值对的集合,每个键值对由一个键和一个值组成。键是唯一的,值可以重复。字典中的元素是无序的。
Dictionary<string, int> dict = new Dictionary<string, int>();
dict.Add("aaa", 11); // 添加元素
dict.Remove("aaa"); // 删除元素
dict.ContainsKey("aaa"); // 判断是否存在
dict.Count; // 元素数量
int value = dict["aaa"]; // 根据键访问值
foreach(var kv in dict) {
// 遍历集合
}
foreach(var (k, v) in dict) {
// 遍历集合 (直接解构,需要新版.Net)
}
foreach(var k in dict.Keys) {
// 遍历键
}
foreach(var v in dict.Values) {
// 遍历值
}
元组
元组是一种值类型,用于存储多个不同类型的值。元组的长度是不可变的,一旦创建就不能修改。元组的元素可以是任何类型,包括值类型、引用类型、数组等。
// 定义元组
var tuple = (1, "hello", 3.14);
// 访问元组元素
int a = tuple.Item1;
string b = tuple.Item2;
double c = tuple.Item3;
// 不使用var定义元组的方式
(int, int, int) tuple2 = (0, 0, 0);
int a = tuple2.Item1;
int b = tuple2.Item2;
int c = tuple2.Item3;
// 指定元组元素名
(int x, int y, int z) tuple3 = (0, 0, 0);
int a = tuple3.x;
int b = tuple3.y;
int c = tuple3.z;
// 元组的元素可以重新赋值
tuple3.x = 100;
// 元组可作为字典的键,可以用于格网划分
Dictionary<(int, int), string> dict = new Dictionary<(int, int), string>();
dict.Add((1, 2), "hello");
string a = dict[(1, 2)];
List集合排序
使用Sort()排序
对于一些数值,和一些实现了IComparable<T>接口的类型,集合可以直接使用Sort()排序。注意,Sort()方法对集合本身排序,修改原集合。
List<int> list = new List<int>();
list.Add(4);
list.Add(2);
list.Add(3);
list.Sort(); // 升序排序
使用OrderBy()排序
可以使用OrderBy()根据对象中的属性排序。OrderBy()方法返回一个新的集合,不修改原集合。
例如,下面是一个Students类
public class Student
{
public int age;
public string name;
public Student(int age, string name)
{
this.age = age;
this.name = name;
}
}
对集合中的四位学生按年龄升序排序
// 初始化一个List<Student>集合,添加4位不同年龄的学生
List<Student> students = new List<Student>() {
new Student(10, "张三"),
new Student(4, "李四"),
new Student(50, "王五"),
new Student(208, "张三丰") // 练得身形似鹤形,千株松下两函经
};
List<Student> sortedList = students.OrderBy(student => student.age).ToList();
常用语法糖 (.Net 8.0)
使用语法糖可以减少一定样板代码,提高编写速度。如果你想使用尽可能多的语法糖,你需要尽可能新的.Net版本。
下面总结了3个比赛可能比较高频可用的语法糖:
变量自动推断var
var可以自动推断变量的类型,无需显式指定。
// 例如我们有如下字段
public Dictionary<(int, int, int), List<Point>> gird = new Dictionary<(int, int,int), List<Point>>();
// 直接取用字典中的值,把类型推断的任务交给编译器
var points = gird[(1, 2, 3)];
// 而不用
List<Point> points = gird[(1, 2, 3)];
记录(Record)
记录是一种值类型,用于存储多个不同类型的值。记录的元素是不可变的,一旦创建就不能修改。记录的元素可以是任何类型,包括值类型、引用类型、数组等。
记录可以用于快速定义一些简单的类型,如点、三角形。
记录会自动重写Equals、ToString方法和解构声明。
// 定义点记录
public record Point(int id, int x, int y, int z);
// 记录不仅可以只定义属性,还可以定义方法,具体看使用场景
public record Point2(int id, int x, int y, int z) {
public String getName() => $"{x.ToString("F3")} {y.ToString("F3")} {z.ToString("F3")}";
}
解构声明
解构声明可以将重写结构方法的类直接解构为变量,无需显式访问记录的属性。
public class MyPoint(int x, int y, int z)
{
// 重写解构方法
public void Deconstruct(out double X, out double Y, out double Z)
{
X = x;
Y = y;
Z = z;
}
}
var p = new MyPoint(1, 2, 3);
// 直接解构
var (x, y, z) = p;
// 忽略某些不关心变量(使用_忽略y)
var (x, _, z) = p;
// 记录类会自动实现解构声明,无需显式实现
public record Point(int id, int x, int y, int z);
var point = new Point(1001, 2, 3, 4);
// 直接解构
var (id, x, y, z) = point;
// 元组也可以直接解构
var tuple = (1, "hello", 3.14);
var (a, b, c) = tuple;
Dictionary字典的键值对也包含解构声明,可以直接解构字典中的键值对。
Dictionary<(int, int), string> dict = new Dictionary<(int, int), string>();
dict.Add((1, 2), "hello");
// 在foreach循环中解构键值对
foreach (var (key, value) in dict)
{
Console.WriteLine($"Key: {key.Item1}, {key.Item2}, Value: {value}");
}
// 等效写法
foreach (var kv in dict)
{
var key = kv.Key;
var value = kv.Value;
Console.WriteLine($"Key: {key.Item1}, {key.Item2}, Value: {value}");
}
快捷键和快捷操作
注释/解除注释: 按住Ctrl,然后依次按K, C / 按住Ctrl,然后依次按K, U
光标多行插入:Shift + Alt + ↑ 或 ↓
快速生成和重构:在类中或成员属性上右键点击,选择快速操作和重构,可以生成构造方法、重写Equals、ToString方法,成员属性的getter和setter。
常用算法
dms 弧度互转
public double dms_rad(double dms)
{
double d = (int)dms;
double m = (int)((dms - d) * 100);
double s = ((dms - d) * 100-m)*100;
double rad = (d + m / 60 + s / 3600) * PI / 180;
return rad;
}
public double rad_dms(double rad)
{
rad = rad * 180 / PI;
double d = (int)rad;
double m = (int)((rad - d) * 60);
double s = ((rad - d) * 60 - m) * 60;
double dms = (d + m / 100 + s / 10000);
return dms;
}
矩阵求逆(高斯消元法)
public static double[,] MatrixInverse(double[,] matrix)
{
int n = matrix.GetLength(0);
if (matrix.GetLength(1) != n)
throw new ArgumentException("Input matrix must be square.");
// 创建增广矩阵 [matrix|I]
double[,] augmented = new double[n, 2 * n];
for (int i = 0; i < n; i++)
{
for (int j = 0; j < n; j++)
{
augmented[i, j] = matrix[i, j];
}
augmented[i, i + n] = 1.0;
}
// 高斯消元法
for (int i = 0; i < n; i++)
{
// 寻找主元行
int maxRow = i;
for (int k = i + 1; k < n; k++)
{
if (Math.Abs(augmented[k, i]) > Math.Abs(augmented[maxRow, i]))
maxRow = k;
}
// 交换当前行和主元行
if (maxRow != i)
{
for (int j = 0; j < 2 * n; j++)
{
double temp = augmented[i, j];
augmented[i, j] = augmented[maxRow, j];
augmented[maxRow, j] = temp;
}
}
// 如果主元为0,矩阵不可逆
if (Math.Abs(augmented[i, i]) < 1e-10)
throw new InvalidOperationException("Matrix is not invertible.");
// 归一化当前行
double pivot = augmented[i, i];
for (int j = i; j < 2 * n; j++)
{
augmented[i, j] /= pivot;
}
// 消去其他行
for (int k = 0; k < n; k++)
{
if (k != i && Math.Abs(augmented[k, i]) > 1e-10)
{
double factor = augmented[k, i];
for (int j = i; j < 2 * n; j++)
{
augmented[k, j] -= factor * augmented[i, j];
}
}
}
}
// 提取逆矩阵部分
double[,] inverse = new double[n, n];
for (int i = 0; i < n; i++)
{
for (int j = 0; j < n; j++)
{
inverse[i, j] = augmented[i, j + n];
}
}
return inverse;
}
``` // 如果主元为0,矩阵不可逆
if (Math.Abs(augmented[i, i]) < 1e-10)
throw new InvalidOperationException("Matrix is not invertible.");
// 归一化当前行
double pivot = augmented[i, i];
for (int j = i; j < 2 * n; j++)
{
augmented[i, j] /= pivot;
}
// 消去其他行
for (int k = 0; k < n; k++)
{
if (k != i && Math.Abs(augmented[k, i]) > 1e-10)
{
double factor = augmented[k, i];
for (int j = i; j < 2 * n; j++)
{