dotnet-csharp

发布时间 2023-03-25 15:34:24作者: 摧残一生
  • 为什么要从基础看起
    • 从.net framework3.5就开始接触c#,到现在.net7的崛起,期间有大量的新技术和框架冲击着我,MVC1.0的时候放弃过,感觉无所适从,linq也是近几年才开始使用,感觉现在写代码的方式已经被时代所淘汰,因此萌生出了从头捋顺一次。
    • 学习的时候并没有通过一个完整的体系去学习,而是在实践中去探索,这样带来一个问题,什么是最佳实践,应该如何去做技术选型。微软创造出了很多轮子,哪一个才是适合的?希望能从微软的官方文档中寻找到答案

.NET体系结构

  • 简而言之,.NET是公共语言运行时(CLR)的虚拟执行系统和一组类库的集合

  • CLR:公共语言结构(CLI)国际标准的实现

  • CLI:创建执行和开发环境的基础,语言和库可以无缝的协同工作。

  • c#编写的代码可以编译成复核CLI规范的中间语言(IL),IL代码和资源存储在.dll的程序集中

  • 程序运行流程

    1. 程序集加载到CLR中
    2. CLR直接执行实时编译(JIT),将IL代码转换为本机指令
    3. CLR可提供自动垃圾回收,异常处理和资源管理的服务

    CLR执行的代码成为"托管代码",而"非托管代码"被编译成面向特定平台的本机语言

  • 优势

    • 底层编译环境一样,c#生成的IL代码可与.Net其他语言进行交互(底层一样)
    • .NET还有大量的库,可以通过引用命名空间来使用

类型和遍历

  • 值类型和引用类型

    • 值类型

      • 简单类型(char是值类型),枚举类型(enum),结构类型(struct),null的值类型(int?),元组值类型

      • 元组值类型(c# 7.0)

        // 1.直接声明
        (double, int) t1 = (4.5, 3)
        Cosole.WriteLine($"elements is {t1.Item1} and {t1.Item2}");
        // 2.有变量名
        (double Sum, int Count) t2 = (4.5, 3);
        Console.WriteLine($"Sum of {t2.Count} elements is {t2.Sum}.");
        
    • 引用类型

      • 类类型:基类为object的继承类,string(UTF-16代码单元序列),用户定义类(class C{})
      • 接口类型(interface I{})
      • 数组 int[], int[,] int[i] [j]
      • 委托类型(delegate int D{})
      • record类型
    • record类型(C# 9.0)

      只读属性的轻量级、不可变数据类型

      • record Class(class可省略)引用类型记录

        public record Params([property: JsonPropertyName("param1")] string Param1,[property:JsonPropertyName("param2")] int Param2);
        // 等价于
         public class Person : IEquatable<Params>
         {
             [JsonPropertyName("param1")]
             public string Param1 { get; set; }
             [JsonPropertyName("param2")]
             public int Param2 { get; set; }
         }
        // 可继承
        public record ExtParams(string Param1, int Param2 string Param3, string Param4):Params(Param1,Param2)
        // 与元组值类型合用
        Params params = new Params("param1", 2);
        var (item1, item2) = params;
        Console.WriteLine($"item1={item1},item2={item2}");//输出:item1=item1,item2=2
        // 使用with克隆
        var pClone1 = params with { }; // Param1 = Param1,Param2 = 2
        var pClone2 = params with { Param2=4 }; // Param1 = Param1,Param2=4
        // 可拥有自定义属性
        public record class Params1(double p1, double p2)
        {
            public double p3 { get; set; }
        }
        
      • record Struct(c# 10.0)值类型记录

        // 与record class类似
        public record struct RecordS1(int r1, int r2);
        
      • record Class和record Struct不同点

        • record Calss 的实例不可写 record Struct可读可写(readonly除外)

          public record class RecordS1(int r1, int r2);
          public readonly record struct RecordS2(int r1, int r2);
          public record struct RecordS3(int r1, int r2);
          var record1 = new RecordS1(1, 2);
          record1.r1 = 2;	//错误
          var record2 = new RecordS2(1, 2);
          record2.r1 = 2;	//错误
          var record3 = new RecordS3(1, 2);
          record3.r1 = 2;	//通过
          
        • 拥有自定义属性不同:record Structural自定义属性必须初始化

           // record class
           public record class RecordS1(int r1, int r2)
           {
           	public int r3 { get; set; }
           }
           // readonly record struct
           public readonly record struct RecordS2(int r1, int r2)
           {
           	public int r3 { get; } = default;//必须初始化,r3无法赋值
           }
           //  record struct
           public record struct RecordS3(int r1, int r2)
           {
           	public int r3 { get; set; } = default;//必须初始化
           }
          
  • 装箱 拆箱

    • 装箱 将值类型的放到引用类型中
    • 拆箱 从引用类型中拿出值类型来

C#类型和成员

  • Flag特性

    • 指示可以将枚举作为位域(即一组标志)处理

      [Flags]
      public enum Seasons
      {
           None = 0,
           Summer = 1,
           Autumn = 2,
           Winter = 4,
           Spring = 8,
           All = Summer | Autumn | Winter | Spring
      }
      Seasons season = Seasons.All
      // 加上后输出season.ToString()为Summer,Autumn,Winter,Spring
      // 不加上输出season.ToString()为15
      // 加上后如何输出15 (int)season
      

C# 程序构建基块

  • 可访问性

    • public 不受限制
    • private 仅限于此类
    • protected 仅限于此类或其派生类
    • internal 仅可访问当前程序集(exe或dll)
    • protected internal 同一程序集或派生类
    • private protected 此类或派生类
  • 属性

    在类或方法上的标签

    • 定义

      // 创建了一个Help的属性,引用Attribute基类
      public class HellpAttribute:Attribute{
      	string _url;
      	string _topic;
      	public HelpAttribute(string url)=> _url=url;
      	public string Url => _url;
      	public string Topic{
      		get => _topic;
      		set => _topic = value;
      	}
      }
      
    • 使用

      // 在类和方法上添加了属性
      [Help("url")]
      public class Widget{
      	[Help("url/features", Topic = "Display")]
      	public void Display(string text) { }
      }
      
    • 解析和操作 - 利用反射

      // 通过Type获得通用的属性
      Type widgetType = typeof(Widget);
      // 获得class类的属性
      object[] widgetAtt = widgetType.GetCustomAttribytes(typeof(HelpAttribute), false);
      if(widgetAtt.Length > 0){
      	HelpAttribute attr = (HelpAttribute)widgetAttr[0];
      	// 输出 attr.Url attr.Topic
      }
      // 获得Display方法的属性
      System.Reflection.MethodInfo method = widgetType.GetMethod(nameof(Widget.Display));
      
      object[] displayMethodAttr = method.GetCustomAttributes(typeof(HelpAttribute), false);
      if(displayMethodAttr.Length >0){
      	HelpAttribute attr = (HelpAttribute)displayMethodAttr[0];
      	// 输出 attr.Url attr.Topic
      }
      
  • 弃元在元组的使用

    人为取消的占位符(_)

    // 方式一:返回了多个返回值,通过元组返回
    var (_, _,pop1, _, pop2) = QueryData("New", 1960, 2010);
    static (string, double, int, int, int)QueryData(string name, int year1, int year2){
    	return (name, year1, year1-year2, yrear2, yrea1+yrea2);
    }
    // 方式二 使用Deconstruct(解构)方法并结合out返回元组
    public class Person{
        public Person(){}
        // 使用结构方法
        public Deconstruct(out string fname, out string lname, out string city, out string state){
            fname = "w";
            lname = "h";
            city = "wf";
            state = "1";
        }
    }
    var p = new Person();
    var (fName, _, city, _) = p;