C# 里面的小知识
最近在B站刷视频的时候刷到了一个C#冷知识系列的视频,恰好最近从头开始看官方文档,就想着把他整理成文档当作自己的随笔。
视频链接:C# 的一些冷知识
这边不考虑性能什么方面的问题,只是分享,可能用不到到但是不能不知道。
函数的传参
先来一个一般正常函数的示例:
// 正常传参调用函数 (位置传参,参数和函数声明的参数要一一对应)
Foo("Tom", 18, true); // output: Tom, 18, True
// 定义一个函数 Foo
void Foo(string name, int age, bool alive) =>
Console.WriteLine($"{name},{age},{alive}");
现在我们试试命名参数来进行调用函数:
Foo(name:"Tom", age:18, alive:true); // output: Tom, 18, True
适用场景
看上面的示例感觉更麻烦了这样有意义吗?
当然有,有些函数的形参是有默认值的例如:
void Foo(string name, int age = 18, bool alive = true) =>
Console.WriteLine($"{name},{age},{alive}");
我现在只想传输 name
和 alive
这两个参数的时候我们可以利用命名参数来跳过传输 age
这个参数。示例:
Foo("Tom", alive:false); // output: Tom, 18, False
// 在 命名参数 后面还可以使用 位置参数 如下
Foo("Tom", age:23, true); // output: Tom, 23, True
官方文档链接:命名实参和可选实参
枚举类型的数据格式
默认情况下,枚举成员的关联常数值为类型 int
;它们从零开始,并按定义文本顺序递增 1。可以显式指定任何其他整数数值类型作为枚举类型的基础类型。 还可以显式指定关联的常数值,如下面的示例所示:
enum ErrorCode : ushort
{
None = 0,
Unknown = 1,
ConnectionLost = 100,
OutlierReading = 200
}
// 又或者
enum ErrorCode : byte
{
None = 0x01,
Unknown,
ConnectionLost,
OutlierReading
}
能使用的类型有:byte
、sbyte
、short
、ushort
、int
、uint
、long
或 ulong
。
详细参见官方文档:枚举类型
显式实现接口
我们知道一个类是可以继承多个接口的,但是有种情况:如果一个类实现的两个接口包含签名相同的成员这时后我们该这么办呢?
这时后我们就可以使用显式实现接口的方式来实现接口:
public interface IControl
{
void Paint();
}
public interface ISurface
{
void paint();
}
public class SampleClass : IControl, ISurface
{
// 这时候 IControl 和 ISurface 的 paoint 的实现都是这个
public void Paint()
{
Console.WriteLine("Paint method in SampleClass");
}
}
调用:
SampleClass sample = new SampleClass();
IControl control = sample;
ISurface surface = sample;
// 下面几行都调用的同样的方法。
sample.Paint();
control.Paint();
surface.Paint();
但你可能不希望为这两个接口都调用相同的实现。 若要调用不同的实现,根据所使用的接口,可以显式实现接口成员。
public class SampleClass : IControl, ISurface
{
// 显式接口实现不需要修饰符
void IControl.Paint()
{
System.Console.WriteLine("IControl.Paint");
}
void ISurface.Paint()
{
System.Console.WriteLine("ISurface.Paint");
}
}
这时候调用:
SampleClass sample = new SampleClass();
IControl control = sample;
ISurface surface = sample;
//sample.Paint(); // Compiler error.
control.Paint();
surface.Paint();
详细参见官方文档:显式接口实现
模式匹配
附带官方文档的链接:模式匹配
“模式匹配”是一种测试表达式是否具有特定特征的方法。 C# 模式匹配提供更简洁的语法,用于测试表达式并在表达式匹配时采取措施。
Null 检查
来试试最常见的判断一个变量是不是为空:
string msg = "This is not the null string.";
// 判断字符串是不是为 null
if (msg is not null)
{
Console.WriteLine(msg);// msg 不是 null 的话则打印
}
声明模式
借助声明模式,还可声明新的局部变量。 当声明模式与表达式匹配时,将为该变量分配转换后的表达式结果,如以下示例所示:
int? isNull= null;
if (isNull is int number)
{
Console.WriteLine($"The nullable int 'isNull' has the value {number}");
}
else
{
Console.WriteLine("The nullable int 'isNull' doesn't hold a value");
}
上述代码是声明模式,用于测试变量类型并将其分配给新变量。 语言规则使此方法比其他方法更安全。 变量 number
仅在 if
子句的 true 部分可供访问和分配。 如果尝试在 else
子句或 if
程序块后等其他位置访问,编译器将出错。
另外我们在使用if
的时候还会经常使用||
和&&
这个我们模式匹配也是可以的对应or
和and
如下示例:
// 例如我们要判断一个变量是否等于某些常量
int num = 5;
if(num == 1 || num == 3 || num == 5 || num == 7) // 这是我们以前常用的写法
Console.WriteLine("'num' belongs to '1, 3, 5, 7'.");
// 我们也可以使用模式匹配的方式
if (num is 1 or 3 or 5 or 7)
Console.WriteLine("'num' belongs to '1, 3, 5, 7'.");
// 判断这个 num 是否在某个区间之内
if (num is >=0 and <10)
Console.WriteLine("'num' is between 0 and 9");
模式匹配还能用于更复杂的的场景,例如元组,数组:
// 元组
var pair = (2, 5);
if (pair is ( > 2, < 6))
Console.WriteLine(pair.ToString());
else
Console.WriteLine(" 'pair' does not meet the conditions. ");
// 列表模式(C#11 以下不能使用列表模式)
int[] arr = { 1, 2, 5, 6, 8 };
if (arr is [1, not 4, _, _, _])
Console.WriteLine("arr does meet the conditions.");
else
Console.WriteLine("arr does not meet the conditions.");