WPF C#命名规范及便捷语法

前言

C#从语言上来说还是比较好用的,有一些别的语言没有的但是很好用的语法这里推荐一下。

命名规约

  1. 【强制】代码中当且仅当私有成员可以使用下划线开始

  2. 【强制】类名类的属性方法名命名空间使用UpperCamelCase大驼峰风格,英文单词首字母大写,必须遵从驼峰形式,但以下情形例外(领域模型的相关明明)CEO / DBO 等。

    正例:SysuserController / ItemInfo / TcpHelper / GetInfo()

    反例:sysuserController / Iteminfo / TCPHelper / getInfo()

  3. 【强制】参数名成员变量局部变量都统一使用lowerCamelCase小驼峰风格,除首单词外其他单词首字母大写,必须遵从驼峰形式。

    正例:localCache / userList

  4. 【强制】常量命名全部大写,单词间用下划线隔开,力求语意表达完整清楚,不要嫌名字长。

    正例:MAX_STOCK_COUNT

    反例:MAX_COUNT

判断非空并取值

传统写法

1
if (resultVo != null && resultVo.code == 0){}

推荐写法(is 模式表达式)

1
if (resultVo is { code: 0 }){}

示例2

1
if (((Button)sender).Tag is ZRecordModel recordModel){}

示例3

1
2
if (quesResultsWindow != null && quesResultsWindow.Visibility == Visibility.Visible)
{}

优化后

1
2
if (quesResultsWindow is { Visibility: Visibility.Visible })
{}

??

1
2
//当a不为空时返回a,为null时返回b
var c = a ?? b;

?.

不为null时执行后面的操作。

例如:

1
2
3
4
5
6
7
int? firstX = null;
if (points != null)
{
  var first = points.FirstOrDefault();
  if (first != null)
  firstX = first.X;
}

在C# 6.0中,引入了一个 ?.的运算符,前面的代码可以改成如下形式:

1
int? firstX = points?.FirstOrDefault()?.X;

用于在执行成员访问 (?.) 或索引 (?[) 操作之前,测试是否存在 NULL。 这些运算符可帮助编写更少的代码来处理 null 检查,尤其是对于下降到数据结构。

1
int? count = customers?[0]?.Orders?.Count();

??=

1
2
3
4
if (classroomExamWindow == null)
{
classroomExamWindow = new ExamWindow(this);
}

替换为

1
classroomExamWindow ??= new ExamWindow(this);

out 变量

以前,需要将 out 变量的声明、使用为两个不同的语句,如下所示:

1
2
3
4
5
int numericResult;
if (int.TryParse(input, out numericResult))
WriteLine(numericResult);
else
WriteLine("Could not parse input");

现在,可将前面两行合并为一行表示:

1
2
3
4
if (int.TryParse(input, out int result))
WriteLine(result);
else
WriteLine("Could not parse input");

匿名类

1
2
3
4
var Aemployee=new {
JoinDate="2012-09-23",
aPeople=new {pName="张三",pAge=26,pSex="男"}
};

匿名方法

1
2
3
4
5
6
7
8
9
10
//匿名方法只使用一次
ChangeUserPwd(listUser, delegate(User u) {
Console.WriteLine(u.Name+"的新密码是:"+u.Password);
});
//使用Lambda表达式
ChangeUserPwd(
listUser, u=>
{
Console.WriteLine(u.Name + "的新密码是:" + u.Password);
});

case when

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
class Person
{
public int grade { get; set; }
public string name { get; set; }
public string level { get; set; }
}

IList<Person> persons= new List<Person>()
{
new Person{ grade = 50, name = "A_People", level = "None" },
new Person{ grade = 70, name = "B_People", level = "None" },
new Person{ grade = 91, name = "C_People", level = "None" }
};

foreach (Person p in persons)
{
switch (p)
{
case Person obj when obj.grade < 60:
{
obj.level = "不及格";
break;
}
case Person obj when obj.grade > 60 && obj.grade <= 70:
{
obj.level = "及格";
break;
}
case Person obj when obj.grade > 60 && obj.grade <= 70:
{
obj.level = "良好";
break;
}
case Person obj when obj.grade >= 90:
{
obj.level = "优秀";
break;
}
default:
{
Person.level = "None";
break;
}
}
Console.WriteLine($"{p.name} 成绩:{p.level}");
}

using

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
using (Process ffmpeg = new Process())
{
ffmpeg.StartInfo.UseShellExecute = false;
ffmpeg.StartInfo.WindowStyle = System.Diagnostics.ProcessWindowStyle.Hidden;
ffmpeg.StartInfo.RedirectStandardError = true;
ffmpeg.StartInfo.FileName = ffmpegpath;
ffmpeg.StartInfo.Arguments = "-i " + sourceFile;

ffmpeg.StartInfo.CreateNoWindow = true; // 不显示程序窗口
ffmpeg.Start();
var errorreader = ffmpeg.StandardError;
ffmpeg.WaitForExit();
var result = errorreader.ReadToEnd();

var duration = result.Substring(
result.IndexOf("Duration: ", StringComparison.Ordinal) + ("Duration: ").Length,
("00:00:00").Length);
return duration;
}

替换为

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
using Process ffmpeg = new Process();
ffmpeg.StartInfo.UseShellExecute = false;
ffmpeg.StartInfo.WindowStyle = System.Diagnostics.ProcessWindowStyle.Hidden;
ffmpeg.StartInfo.RedirectStandardError = true;
ffmpeg.StartInfo.FileName = ffmpegpath;
ffmpeg.StartInfo.Arguments = "-i " + sourceFile;

ffmpeg.StartInfo.CreateNoWindow = true; // 不显示程序窗口
ffmpeg.Start();
var errorreader = ffmpeg.StandardError;
ffmpeg.WaitForExit();
var result = errorreader.ReadToEnd();

var duration = result.Substring(
result.IndexOf("Duration: ", StringComparison.Ordinal) + ("Duration: ").Length,
("00:00:00").Length);
return duration;

switch

image-20231124112224109

模式匹配

模式匹配是C# 7.0引入的一项功能,它使我们能够更便捷地进行条件判断和类型转换。

通过模式匹配,我们可以根据对象的类型、结构、属性等特征进行匹配,并且在匹配成功后执行相应的代码块。

类型模式匹配:

1
2
3
4
object obj = 42;
if (obj is int i) {
Console.WriteLine($"obj是一个整数: {i}");
}

类型模式匹配和变量模式匹配的组合:

1
2
3
4
object obj = "hello";
if (obj is string s && s.Length > 0) {
Console.WriteLine($"obj是一个非空字符串: {s}");
}

属性模式匹配:

1
2
3
4
5
6
7
8
9
public class Person {
public string Name { get; set; }
public int Age { get; set; }
}

Person person = new Person { Name = "John", Age = 30 };
if (person is { Name: "John" }) {
Console.WriteLine("这个人的名字是John");
}

类型和属性匹配

1
2
3
4
5
6
7
private void BtnQuestionsClick(object sender, RoutedEventArgs e)
{
if (!(sender is Button { Tag: TiwenTongjiItem tongjiItem }))
{
return;
}
}

枚举模式匹配:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
enum Color { Red, Green, Blue }

Color color = Color.Green;
switch (color) {
case Color.Red:
Console.WriteLine("这是红色");
break;
case Color.Green:
Console.WriteLine("这是绿色");
break;
case Color.Blue:
Console.WriteLine("这是蓝色");
break;
}

集合模式匹配:

1
2
3
4
List<int> numbers = new List<int> { 1, 2, 3, 4, 5 };
if (numbers is { Count: > 0 }) {
Console.WriteLine("集合非空");
}

复杂一点

1
2
3
4
5
List<int> numbers = new List<int> { 1, 2, 3, 4, 5 };
if (numbers is { Count: 5, [2]: 3 })
{
Console.WriteLine("集合中有5个元素,且第三个元素是3");
}

合并模式:

1
2
3
4
int x = 5;
if (x is >= 0 and <= 10) {
Console.WriteLine("x是介于0和10之间的数");
}

switch 表达式中的模式匹配:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
public abstract class Shape { }

public class Circle : Shape {
public double Radius { get; set; }
}

public class Rectangle : Shape {
public double Width { get; set; }
public double Height { get; set; }
}

Shape shape = new Circle { Radius = 5 };
double area = shape switch {
Circle c => Math.PI * c.Radius * c.Radius,
Rectangle r => r.Width * r.Height,
_ => throw new InvalidOperationException("未知形状")
};

Console.WriteLine($"图形的面积是: {area}");