主页 >  滚动>正文
dotnet-csharp
时间 : 2023-03-25 16:37:37   来源 : 博客园
  • 为什么要从基础看起
    • 从.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 {     [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 = 2var 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;

标签:

相关文章

X 关闭

X 关闭