C#常用函数集合类语法糖VS快捷方式

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)

记录是一种值类型,用于存储多个不同类型的值。记录的元素是不可变的,一旦创建就不能修改。记录的元素可以是任何类型,包括值类型、引用类型、数组等。
记录可以用于快速定义一些简单的类型,如点、三角形。
记录会自动重写EqualsToString方法和解构声明。

// 定义点记录
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,然后依次按KC / 按住Ctrl,然后依次按K, U
光标多行插入:Shift + Alt +
快速生成和重构:在类中或成员属性上右键点击,选择快速操作和重构,可以生成构造方法、重写EqualsToString方法,成员属性的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++)
                {
2 个赞