C#基础与进阶扩展合集-基础篇(持续更新)

目录

本文分两篇,进阶篇点击:C#基础与进阶扩展合集-进阶篇

一、基础入门

Ⅰ 关键字

Ⅱ 特性

Ⅲ 常见异常

Ⅳ 基础扩展

1、哈希表 

2、扩展方法

3、自定义集合与索引器

4、迭代器与分部类

5、yield return

6、注册表

7、不安全代码

8、方法描述 

二、扩展类型

1、BigInteger

2、Half

3、Decimal

4、可空值类型

5、可空引用类型

6、空合并

7、转义字符

8、StringBuilder

9、FormattableString 

10、元组 

 11、switch表达式

三、其它

1、名称空间取别名

2、预处理器指令

3、隐藏方法

4、显示和隐式实现接口

5、泛型约束

6、字典初始化方式

7、集Set

8、有序集合

9、只读字段与属性 

10、字符串前$与@

11、字符串常用操作

12、List转字符串

13、检查是否跨线程


本文分两篇,进阶篇点击:C#基础与进阶扩展合集-进阶篇

一、基础入门

Ⅰ 关键字

1、record 

record(记录),编译器会在后台创建一个类。支持类似于结构的值定义,但被实现为一个类,方便创建不可变类型,成员在初始化后不能再被改变 (C#9新增)

在运行时通过构造函数给成员赋值

2、init 

 init关键字,代替set(C#9新增)

特性:只能通过构造函数和对象初始化器来设置属性值

public string Name { get; init; }

若用旧的.NET框架版本使用.NET 5代码,需手动添加虚拟类,如下:

namespace System.Runtime.CompilerServices

    internal static class IsExternalInit { }
}

3、with 

 with关键字(C#9新增),内部调用<>Clone浅copy方法,使用如下:

 MyMath myMath2=myMath1 with { };//浅拷贝

4、base 

base关键字,

作用1:子类实例化时默认调用父类的无参构造函数,base可指定调用父类对应的有参构造函数;

作用2:在子类中通过base调用父类被子类重写的虚方法;

5、params

params,修饰方法参数,

1、被修饰的参数必须为一维数组

2、被修饰参数为最后参数,后面不允许有其它参数

6、ref、out、in

1、被ref或out或in修饰的参数通过引用方式传递;

2、传参时也必须带关键字ref(out、in);

3、ref修饰的参数传参时必须提前定义并初始化,out可在传参时定义;

4、out修饰的参数必须在控制离开方法之前对该参数赋值;

5、in修饰的值类型参数,方法内为只读变量(可避免复制值的开销)

7、sealed

sealed,有封装的意思,一般用于修饰类或方法

1、修饰类时,该类不可被继承;

2、修饰方法时,一般用于virtual与抽象方法的继承类,sealed一般与override同时存在,被修饰的已重写的方法不可被其派生类重写。

8、lock

 lock, 确保代码正常执行,不会被其他线程中断;将代码定义为互斥段,同一时刻只能由一个线程执行,其他线程必须等待(解决多线程同时抢占同一资源产生的冲突问题)

示例如下:

        _root:指需要跟踪的对象(通常实例化一个object作为跟踪对象)

        {   _list.Clear();   }:指定义为互斥段的代码块; 

lock(_obj){Count--;}

9、readonly

readonly,用于修饰字段为只读字段 :

1、在运行时可通过构造函数赋值;

10、checked、unchecked

        1、如果将一个代码块标记为checked,CLR就会对该代码块执行溢出检查,溢出会抛出OverflowException异常,也可在表达式中使用checked关键字;

        2、也可在配置项目文件中添加CheckForOverflowUnderflow设置,可对所有未标记的代码进行溢出检查,如:<CheckForOverflowUnderflow>true</CheckForOverflowUnderflow>,可使用unchecked关键字来标记不进行溢出检查;

checked
{
    byte a = 255;
    a = (byte)(a + 3);
}

11、throw

抛出一个异常

throw new Exception("my exception...");

12、as与is

as,用于检查在兼容引用类型之间的转换,不会抛出异常,若不兼容则返回null,通常需对返回对象进行null判断;

        注意:as不用在类型间的转换,会报错;

                   ②as不能用在值类型数据,会报错;

is,用于检查对象是否与给定类型兼容(可强制转换成给定类型),通常用于强制转换之前的检查(不兼容类型间强制转换会抛出异常),这样的写法通常CLR会进行两次类型的检查,会降低性能(若满足as用法尽量用as转换);


Ⅱ 特性

特性,指C#中对类及程序集成员的进一步描述

        更多了解点击:C#进阶-特性   常用如下:

  1.  [Key],指示该属性为主键(仅对属性、字段、索引器有效);
  2.  [StringLength(maximumLength:50,MinimumLength =2)],限制字符串长度(仅对属性、字段、参数、索引器有效);
  3.  [EmailAddress],识别邮箱格式(仅对属性、字段、参数、索引器有效);
  4.  [Required],不可为空(仅对属性、字段、参数、索引器有效);
  5.  [Display(Name="电话号码")],显示别名;
  6. [CallerMemberName],获取调用该方法的成员名(仅对参数有效);
  7. [CallerFilePath],获取调用该方法的文件路径(仅对参数有效);
  8. [CallerLineNumber],获取调用该方法的行数(仅对参数有效);
  9. [Compare(“Password”, ErrorMessage = “”)],比较两个属性的值是否相同;
  10. [DataType(DataType.Password)],标记某属性为密码类型;


Ⅲ 常见异常

  1. ArgumentException,方法接受实参时,检查实参未包含期望的值抛出,其派生有ArgumentNullException(空异常)和ArgumentOutOfRangeException(索引超出范围);
  2. NotSupportedException,当不支持一个方法时抛出;
  3. StackOverflowException,当为栈分配的内存满了导致溢出时抛出;
  4. OverflowException,在checked(关键字中有介绍)上下文中执行算术运算,当得到的值超出变量类型的取值范围时抛出;
  5. IOException基类,文件I/O导致的异常,其派生有FileLoadException、FileNotFoundException、EndOfStreamException、DriveNotFoundException。。。
  6. InvalidOperationException,当没有按正确顺序调用类的方法(如缺少初始化调用)时抛出;
  7. TaskCanceledException,当任务取消或超时的时候抛出;
  8. NullReferenceException,当使用的 null 引用导致需要引用的对象时抛出;

 更多异常详解:微软文档Exception-C#


Ⅳ 基础扩展

1、哈希表 

了解哈希表:C#-关于Hashtable 

2、扩展方法

扩展方法详解:C#-扩展方法定义及其使用

3、自定义集合与索引器

 自定义集合与索引器详解:C#-自定义集合与索引器

4、迭代器与分部类

迭代器与分部类详解:C#-关于迭代器与分部类 

5、yield return

yield示例详解:C#-yield return实现数据迭代 

6、注册表

了解注册表相关操作:C#-注册表的读取、创建、修改、删除操作

7、不安全代码

了解指针(不安全代码): C#-关于指针使用(不安全代码)

8、方法描述 

对自定义方法添加描述:C#-方法的功能、参数、返回值描述 


二、扩展类型

1、BigInteger

如果需要的数字比64位的long类型能够表示的值更大,则可使用BigInteger类型,该类型无关键字无位数限制,可以一直增长下去,直到没有可用内存。

BigInteger bigInteger =111111111111111111;

2、Half

.NET5新增,16位单精度浮点数,无关键字,其有效位数为10位,指数位为5位;

注意:硬编码的一个非整数值(1.92171),一般默认为double类型,需强转;

Half half = (Half)1.92171;

3、Decimal

关键字decimal,.NET高精度浮点类型,128位,1位符号位、96位用作整数,剩下的位指定了比例因子。

注意:要把数字指定为该类型,在其数字后面加上字符M(或m);

decimal deci = 11111.11M;

4、可空值类型

①在类型定义中使用“?”,这将允许赋值null,如:int? a = null;

②编译器会将该语句变成Nullable<T>类型,如:Nullable<int> a=null;

③Nullable<T>不会增加引用类型的开销,仍然是struct值类型,只不过添加了一个布尔标志,用来指定值是否为null;

④总是可把不可为空的值赋值给可空值类型;

5、可空引用类型

①主要为了减少NullReferenceException类型的异常,可启用可空引用类型获得编译器的帮助:1、在项目文件中指定Nullable将其设为enable,如:<Nullable>enable</Nullable>;

        2、使用预处理器指令启用:#nullable enable,禁用:#nullable disable,恢复项目文件中设置:#nullable restore

②启用后给引用类型赋值(string c = null;)编译器会报警告,若要赋值null,需加上“?”,如:string? c = null;

6、空合并

 string? s=null;
string s2 = s?.ToLower()??string.Format("");//使用null条件运算符和空合并运算符
Console.WriteLine($@"\t{s2}\t{{}}");

7、转义字符

转义序列字符
\'单引号
\"双引号
\\反斜杠
\0
\a警告
\b退格
\f换页
\n换行
\r回车
\t水平制表符
\v垂直制表符

8、StringBuilder

StringBuilder sb = new StringBuilder("111111");//动态字符串默认容量16字符,成倍增加
sb.Append("abcdefghjklmnopq");
Console.WriteLine(sb.Length);//获取有效长度
Console.WriteLine(sb.Capacity);//获取容量

9、FormattableString 

FormattableString str = $"time:{t},number:{a}";//格式化字符串类型
Console.WriteLine("格式str:{0}",str.Format);//获取格式化字符串的原始字符串
for (int i = 0; i < str.ArgumentCount; i++)
{
    Console.WriteLine("Arg{0}:{1}", i, str.GetArgument(i));//获取参数值
}

10、元组 

 元组,把多个类型合为一个类型,不需要创建类、结构、记录

            var t=(String:"sss",Int32: 32);
            t.Int32 = 2;
            t.String = "Auston";

.Net提供了Tuple<T>旧类型

                  ValueTuple<T>新类型(推荐)有更好的内置支持

 11、switch表达式

int number = 5;  
string message = number switch  
{  
    1 => "One",  // expression  
    2 => "Two",  // expression 
    _ => "More than two"  // default expression 
};  


三、其它

1、名称空间取别名

主要用于解决名称空间二义性问题: 

using Sys = System;

Sys.Console.WriteLine("Hello, Auston!");

2、预处理器指令

  1. #define,定义符号;
  2. #undef,删除符号定义;
  3. #if、#elif、#else、#endif,条件语句,支持部分逻辑运算符;
  4. #warning、#error,编译器遇到后会报错或警告,并显示后面文本;
  5. #region、#endregion,将一段代码视为给定名称的一个块;
  6. #line,用于改变编译器在警告和错误中显示的文件名和行号信息,如,#line 123 "Test.cs";
  7. #pragma,抑制(disable)或还原(restore)指定的编译警告;
  8. #nullable,启用(enable)或禁用(disable)可空引用类型

3、隐藏方法

在基类和派生类中存在签名相同的方法,且无virtual与override修饰时,派生类就会隐藏基类方法;

要隐藏方法,可在方法声明中加new关键字修饰,否则编译器会警告,大多数情况下应重写方法,而不是隐藏方法,隐藏方法会造成对于给定类的实例调用错误方法的危险;

可在派生类中使用base调用基类方法;

Pig pig = new();
pig.Hobby();
pig.BaseHobby();

class Animal
{
    public void Hobby() => Console.WriteLine("Like run...");
}
class Pig : Animal
{
    new public void Hobby() => Console.WriteLine("Like eat...");
    public void BaseHobby() => base.Hobby();
}

4、显示和隐式实现接口

隐式实现接口示例:

MyLog myLog = new MyLog();
myLog.Log("this is a log!");
interface ILogger
{
    void Log(string message);
}

class MyLog : ILogger
{
    public void Log(string message) => Console.WriteLine(message);
}

显示实现接口,被实现成员没有访问修饰符,并且方法前带有接口前缀;

对于显示实现接口,使用MyLog类型变量时,不能访问该接口,因为它是非公有的,只有使用接口类型可调用Log()方法;

使用显示实现接口原因:①为了解决不同接口相同签名方法的冲突;②向类外的代码隐藏接口方法,但仍满足接口契约;

示例如下:

ILogger myLog = new MyLog();
myLog.Log("this is a log!");
interface ILogger
{
    void Log(string message);
}

class MyLog : ILogger
{
    void ILogger.Log(string message) => Console.WriteLine(message);
}

5、泛型约束

约束说明
where T : struct使用结构约束时,T必须为值类型
where T : class使用类约束时,T必须为引用类型
where T : class?T必须是可空的或者不可为空的引用类型
where T : notnullT必须是不可为空的类型,可为值类型或引用类型
where T : unmanagedT必须是不可为空的非托管类型
where T : IFoo类型T必须实现接口IFoo
where T : Foo类型T必须派生自基类Foo
where T : new()构造函数约束,指定T必须有无参构造函数。不能为有参构造函数指定约束
where T1 : T2使用约束时,可指定类型T1派生自泛型类型T2

6、字典初始化方式

Dictionary<int, string> dic = new Dictionary<int, string>() { { 1, "111" }, { 2, "bbb" } };
Dictionary<int, string> dic2 = new Dictionary<int, string>() { [1] = "111", [2] = "aaa" };
Console.WriteLine("{0}\t{1}", dic[1], dic2[1]);

7、集Set

 包含不重复的元素的集合称为,“集(set)”;

.NET Core包含两个集,他们都实现ISet<T>接口:

①HashSet<T>,包含不重复元素的无序散列表;

②SortedSet<T>,包含不重复元素的有序列表;

集的提供另一个Add()方法,其返回类型为bool值,说明是否添加了元素,若该元素已存在,就不添加,并返回false;

HashSet<int> set = new HashSet<int>() { 2, 1, 7, 0, 1, 2 };
foreach (int i in set)
    Console.Write($"{i} ");//输出2 1 7 0
SortedSet<int> set2 = new SortedSet<int>() { 2, 1, 7, 0, 1, 2 };
foreach (int i in set2)
    Console.Write($"{i} ");//输出0 1 2 7

8、有序集合

有序集合包括有序集、有序列表、有序字典,功能几乎完全相同,但其性能有很大差异,有序列表使用的内存少,有序字典的元素检索速度快。 

9、只读字段与属性 

只读字段(readonly修饰的字段 ),在运行时通过构造函数赋值

只读属性,(set被private修饰),使用属性初始化或在构造函数里初始化,如下:

public int Id { get; } = 23;

10、字符串前$与@

字符串插值:字符串前带$前缀,允许在字符串类计算表达式;

verbatim字符串:字符串前带@前缀,解决反斜杠转义问题,常用于文件路径;

string a = "hello";
Console.WriteLine($"a:{a}");
Console.WriteLine(@"\file\a.txt");

11、字符串常用操作

①字符串取指定索引范围子字符串,Substring方法:

string currentDir = Assembly.GetExecutingAssembly().Location;
currentDir = currentDir.Substring(0, currentDir.LastIndexOf('\\'));

12、List转字符串

for循环,累加:性能较好,代码量较多;

Linq(Aggregate累加器),性能较差,简单;

 list.Aggregate("", ((c, s) => c + (s + ",")));

String.Join:性能比较好,简单(推荐

String.Join(",", list);

13、检查是否跨线程

System.Windows.Application.Current.Dispatcher.CheckAccess()

  • 86
    点赞
  • 23
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值