• C# 知识点补漏(持续更新)


    将以前的一些笔记整理了一下,方便查询知识点

    2020-12-23

    • ?用法:

      int ? a=null;表示定义的类型可以为null, 通过a.Value来获取值,它对应的类型是NullAble<T>
      看下面一张图,假如terminalConfiguration为null,它会跳转到if语句中

      Object b = c??d;表示假c==null,返回d,否则返回c,该运算符从右往左运算,即a??b??c为a??(b??c)来计算

    • 字符串拼接
      不推荐使用+,使用string.Format或者$"{param1} {param2} is ..",后两种的底层实现是一样的,效率会更高
      +和string.concat的底层原理是一致的

    • AppDomain

      AppDomain是CLR的运行单元,它可以加载Assembly、创建对象以及执行程序。

      AppDomain是CLR实现代码隔离的基本机制。AppDomain是个静态概念,只是限定了对象的边界

      AppDomain被创建在进程中,一个进程内可以有多个AppDomain。一个AppDomain只能属于一个进程

    • IReadOnlyCollection阻止调用方转换为其他集合类型。 对于这种保护,必须使用类ReadOnlyCollection<T>

    • 一种优雅的转换方式
      string a = "123";
      if(a is object b){
      //then we can use b as objcet
      }
    • 获取变量或者类名推荐使用“nameof()”
      C# 6.0 引入了一个名为“nameof”的新的操作符,它的作用是接收元素而后返回元素名字。这个操作符能将class和class的所用成员,比如方法、变量以及属性作为参数而后返回一个它们的名字。这避免我们在代码中hardcode字符串,也避免使用反射来获得这些名字

    • Marshal.AllocHGlobal 方法 (Int32)
      通过使用指定的字节数,从进程的非托管内存中分配内存

      IntPtr hglobal = Marshal.AllocHGlobal(100); 
      Marshal.FreeHGlobal(hglobal);
    • 查看.sln看项目版本
      +---------------------------+---------------+-----------+----------------+
      |       Product name        |   Codename    | Version # | .NET Framework | 
      +---------------------------+---------------+-----------+----------------+
      | Visual Studio 4.0         | N/A           | 4.0.*     | N/A            |
      | Visual Studio 97          | Boston        | 5.0.*     | N/A            |
      | Visual Studio 6.0         | Aspen         | 6.0.*     | N/A            |
      | Visual Studio .NET (2002) | Rainier       | 7.0.*     | 1              |
      | Visual Studio .NET 2003   | Everett       | 7.1.*     | 1.1            |
      | Visual Studio 2005        | Whidbey       | 8.0.*     | 2.0, 3.0       |
      | Visual Studio 2008        | Orcas         | 9.0.*     | 2.0, 3.0, 3.5  |
      | Visual Studio 2010        | Dev10/Rosario | 10.0.*    | 2.04.0      |
      | Visual Studio 2012        | Dev11         | 11.0.*    | 2.04.5.2    |
      | Visual Studio 2013        | Dev12         | 12.0.*    | 2.04.5.2    |
      | Visual Studio 2015        | Dev14         | 14.0.*    | 2.04.6      |
      +---------------------------+---------------+-----------+----------------+ 
      VS 2017 对应 15
      Vs 2019 对应 16

      

    • Resize<T>(ref T[] array, int newSize)
      返回一个新的数组,长度是newSize,并把原数组里面的对应长度的值拷贝到新的数组

    • yield 关键字
      其实是一种语法糖,最终还是通过实现IEnumberable<T>、IEnumberable、IEnumberator<T>和IEnumberator接口实现的迭代功能。
      yield return实现了类似用foreach遍历数组的功能
      yield break是用来终止迭代的
      假如使用yield return 返回的是一个IEnumerable 类型的值

    • 浅拷贝和深拷贝
      浅拷贝的定义 —— 只对值类型(或string)类型分配新的内存地址。

      深拷贝的定义 —— 对值类型分配新的内存地址,引用类型、以及引用类型的内部字段分配的新的地址。

    • winform中的NotifyIcon控件
      NotifyIcon是一个比较特殊的组件,其特殊之处是既可以把它归类到控件中,也可以把它归类到组件中。这是因为将其拖放到设计窗体后,我们并不能马上看到它的界面(像组件),而是在运行时才能看到它(像控件)通知区域中的图标是一些进程的快捷方式,这些进程在计算机后台运行,如防病毒程序或音量控制。这些进程不会具有自己的用户界面。NotifyIcon 类提供了编写此功能的方法。Icon 属性定义显示在通知区域中的图标。图标的弹出菜单由 ContextMenu 属性确定。Text 属性分配工具提示文本。要在通知区域中显示图标,必须将 Visible 属性设置为 true

    • using()方式的使用
      必须确保代码再using的逻辑里面使用,比如memoryStream等流的使用或者数据库,串口的使用,以EFCore为例
    • IPropertyChanged事件使用方法

    • IEnumerable, ICollection, ObservableCollection

      IEnumerable只有一个GetEnumerator方法

       ICollection继承自IEnumerable,多了增加删除,count等方法

       ObservableCollection多了CollectionChanged和PropertyChanged事件,常用于UI

    • 元组的使用方法,当dictionary或者list不够用的时候,推荐使用ValueTuple
      (int intValue, string stringValue, string StringName) name = (intValue: 1, stringValue:"123", StringName: "33");
      var str = name.stringValue;
      var str2 = name.StringName;
      var number = name.intValue;
    • Tuple和ValueTuple
      Tuple是引用类型,ValueTuple是值类型,所以推荐用后者

    • 当我们定义接口中的属性时,对于容器一般定义为最顶层的IEnumerable, 那么假如他的实现类的子类需要用到如何办
      public class Test : ITest
      {
          // 公开接口
          public IEnumerable<string> Items => _Items;
          // 私有成员
          private readonly ObservableCollection<string> _Items = new ObservableCollection<string>();
          // 子类操作成员
          protected  ObservableCollection<string> MenuItems => _Items;
      
      }
    • 通常我们定义model都是定义的Immutable,意思是所有成员都是readonly的,只有在构造的时候传入值
      最典型的例子是string,任何操作都会重新创建一个新的string对象
      好处:便于多线程编程,便于作为hashTable的key,便于比较状态
      Immutable离不开2个关键字:const和readOnly
      read only允许在构造的时候改变它的值,但是const不允许,只支持在定义的时候赋值

    • 两种死循环的表达方式 while (true) , for (;;)

    • enum的一些用法
    • 获取登录用户名

      string username = System.Environment.UserName;

    • TaskAwaiter的使用
      public class TestTask : IDisposable
      {
          private readonly Command _command;
          private readonly CancellationTokenSource _cancellationTokenSource;
          private readonly Task _executingTask;
      
          public TestTask(Command command)
                  {
                      _command = command;
                      _cancellationTokenSource = new CancellationTokenSource();
                      _executingTask = _command.ExecuteAsync(_cancellationTokenSource.Token);
                  }
      
          public TaskAwaiter GetAwaiter()
          {
               return _executingTask.GetAwaiter();
          }
          public void Dispose()
          {
                 CancelInternal();
                 if (_executingTask.Status == TaskStatus.Running)
                 {
                          _executingTask.Wait();
                 }
      
                  _cancellationTokenSource.Dispose();
                  _executingTask.Dispose();
           }
      
          private void CancelInternal()
          {
               if (_cancellationTokenSource.IsCancellationRequested)
               {
                     return;
               }
      
                _cancellationTokenSource.Cancel();
           }
      }
      
      class Program
      {
          static void Main(string[] args)
         {
          var task = new TestTask(command);
          await task;
          }
      }
    • Expression和Lambda的区别
      看下面的图片,Expression是一个type,把Lambda包装成了一个变量
    • Lazy<T>的用法
      Lazy表示只有在第一次使用的时候才会去创建对象
      如下图,第一次为false,第二次为true

       在unitTest里面使用Substitute

    • 不要使用magic value
    • 对IEnumerable<T>的处理方式
    • 一种设计模式的理解
      IServiceResultFactory<TErrorCode>是总的接口,然后ServiceResultFactory<TErrorCode>是其实现类,CommandCreationResultFactory是ServiceResultFactory的包含特定TErrorCode的子类,那么为什么要多一个ICommandCreationResultFactory来继承自ServiceResultFactory<TErrorCode>.
      很显然,他是CommandCreationResultFactory的接口,它只做一件事,包含特定的TErrorCode,那么外部使用ICommandCreationResultFactory的时候,TErrorCode已经包含,并且因为CommandCreationResultFactory继承自ServiceResultFactory,它包含了所有的IServiceResultFactory<TErrorCode>里面的方法实现。


    • c#内存
      共有5个内存区域,堆,栈,常量区,静态区,方法区

    • 一个问题
    • 一个例子
      public class Test {
           public static void main(String[] args) {
               Child demo = new Child();
               demo.function();
               Console.WriteLine("…………………………………………………………………………………………………………………………");
               Child child = new Child();
               child.function();
           }
       }
      
      启动流程:
      
      1、  启动CLR,开始分配内存空间; 
      
      2、  开始加载Test.class文件,加载到方法区中,在加载的过程中静态的内容要进入静态区中;
      
      3、  在开始运行main方法,这时CLR就会把main调用到栈中运行,开始从方法的第一行往下运行;
      
      4、  在main方法中new Child();这时CLR就会在方法区中查找有没有Child文件,如果没有就加载Child.class文件,并且Child继承Parent类,所以也要查找有没有Parent类,如果没有也要加载Parent.class文件。
      
      5、  Child.class和Parent.class中的所有的非静态内容会加载到非静态的区域中,而静态的内容会加载到静态区中。静态内容(静态变量,静态方法)按照书写顺序加载。
      
      说明:类的加载只会执行一次。下次再创建对象时,可以直接在方法区中获取class信息。
      
      6、  开始给静态区中的所有静态的成员变量开始默认初始化。默认初始化完成之后,开始给所有的静态成员变量显示初始化。
      
      7、  所有静态成员变量显示初始化完成之后,开始调用构造函数
      ①有个隐式的super(); 
      
      ②显示初始化(给所有的非静态的成员变量)
      
      ③执行构造代码块
      
      之后才开始执行本类的构造方法中的代码
      
      super()是调用父类的构造函数,此处即为Parent的构造函数,在Parent的构造函数中也有个隐式三步:首先super(),再执行Parent的显示初始化,然后执行Parent的构造函数中的代码。
      
      Parent的执行完之后,回来继续执行Child自己的隐式三步中的第二步:显示初始化,然后执行Child的非静态代码块的,最后执行Child的构造函数中的代码
      
      8、对象创建完成,把内存的地址赋值给demo使用。
      
      9、执行demo.function()方法。
      
      10、由于后面又创建(new)了一个新的Child对象,因此重复一下【7】之后的步骤

    • 一些概念

      AppDomain: 程序启动得时候会默认创建一个appDomain域

      Application:Encapsulates a Windows Presentation Foundation application. Windows应用程序,WPF和winform都是继承自它

      Window:每一个xaml就是一个window,继承自它。

    • ref和out关键字表示都是传的地址

    • 分割字符串

    Regex分割

    string[] sArray=Regex.Split(str,"js",RegexOptions.IgnoreCase);

        Split分割

    // (以下string words = "1,2.3,,4";):
    string[] split = words.Split(new string[] { ",", "." }, 2, StringSplitOptions.RemoveEmptyEntries);//返回:{"1","2.3,,4"} 不保留空元素
    string[] split = words.Split(new string[] { ",", "." }, 6, StringSplitOptions.None);//返回:{"1","2","3","","4"} 保留空元素
    
    string[] split = words.Split(new Char[] { ',', '.' }, 2, StringSplitOptions.RemoveEmptyEntries);//返回:{"1","2.3,,4"} 不保留空元素
    string[] split = words.Split(new Char[] { ',', '.' }, 6, StringSplitOptions.None);//返回:{"1","2","3","","4"} 保留空元素

    2021-5-7

    Struct 和Class区别

    简单来说,struct是值类型,创建一个struct类型的实例被分配在栈上。class是引用类型,创建一个class类型实例被分配在托管堆上。但struct和class的区别远不止这么简单。

    概括来讲,struct和class的不同体现在:

    ● 类是引用类型,struct是值类型
    ● 在托管堆上创建类的实例,在栈上创建struct实例
    ● 类实例的赋值,赋的是引用地址,struct实例的赋值,赋的是值
    ● 类作为参数类型传递,传递的是引用地址,struct作为参数类型传递,传递的是值
    ● 类没有默认无参构造函数,struct有默认无参构造函数
    ● 类支持继承,struct不支持继承
    ● 类偏向于"面向对象",用于复杂、大型数据,struct偏向于"简单值",比如小于16字节,结构简单
    ● 类的成员很容易赋初值,很难给struct类型成员赋初值
    ● 类的实例只能通过new SomeClass()来创建,struct类型的实例既可以通过new SomeStruct()来创建,也可以通过SomeStruct myStruct;来创建

    2021-7-6

    使用IDisposable

    public class xxx : IDisposable
    {
            private bool _disposed;
    
            /// <summary>
            /// dispose method
            /// </summary>
            /// <param name="disposing">disposing</param>
            protected virtual void Dispose(bool disposing)
            {
                if (_disposed)
                    return;
    
                if (disposing)
                {
                    // dispose your objects
                }
    
                _disposed = true;
            }
    
            /// <inheritdoc/>
            public void Dispose()
            {
                Dispose(true);
                GC.SuppressFinalize(this);
            }
    }
            

     2021/8/30

    通过linq语句判断2个复杂对象是否相同

    public static bool AreDataEqual(this PairingEntryDto pairingEntryDto, PairingEntryDto other)
    {
                var result = pairingEntryDto.Id == other.Id &&
                             pairingEntryDto.LogTime == other.LogTime &&
                             pairingEntryDto.TerminalSerialNumber == other.TerminalSerialNumber &&
                             pairingEntryDto.ScalePairingHistory.Count == other.ScalePairingHistory.Count;
                if (!result)
                    return false;
                return !pairingEntryDto.ScalePairingHistory.Where((t, i) =>
                                                      t.Status != other.ScalePairingHistory[i].Status ||
                                                      t.PairingInformation != other.ScalePairingHistory[i].PairingInformation).Any();
    }

    2021/9/10

    public static Delegate? Combine (params Delegate?[]? delegates);的用法

    Delegate.Combine Method (System) | Microsoft Docs

    将多个delegate连接,invoke的时候按顺序执行,参数可为null

                Action aa = null;
                Action bb = delegate
                {
                    Console.WriteLine("B");
                };
                Action cc = (Action)Delegate.Combine(aa, bb);
                cc();    

    上图执行结果为:

    2021/9/13

    函数返回2个结果,设置成元组

    public (bool oldState, bool newState) UpdateInitializedState(bool IsInitialized)
    {
    var oldState = IsInitialized;
    var newState = IsInitialized;
    return (oldState, newState);
    }
  • 相关阅读:
    iOS开发实用干货——强化你的Xcode控制台
    Android App 性能优化实践
    AFNetworking 之于 https 认证
    点击 Run 之后发生了什么?
    happypack 原理解析
    JavaScript 笔记 ( Prototype )
    成立快两年的安卓绿色联盟,现在怎么样了?
    盘点20款主流应用FPS,最Skr帧率测试方法都在这里!
    探寻百度AI3.0背后的技术实践
    流畅购物哪家强?购物类应用“页面过度绘制”情况调查
  • 原文地址:https://www.cnblogs.com/xiaojidanbai/p/14180434.html
Copyright © 2020-2023  润新知