<bdo id="4g88a"><xmp id="4g88a">
  • <legend id="4g88a"><code id="4g88a"></code></legend>

    CSharp的lambda表達式匿名類擴展方法

    c#的lamba表達式

    之前已經寫過一些關于委托還有事件的文章,今天就來介紹一下lambda表達式。
    首先定義需要的函數以及委托

    {
    public delegate void DoNothingDelegate();
    public delegate void StudyDelegate(int id, string name);
    
    private void DoNothing()
    {
        Console.WriteLine("DoNothing");
    }
    
    private void Study(int id , string name)
    {
        Console.WriteLine($"{id} {name} 學習 .Net高級班 " );
    }
    }
    

    在.net farmwork 1.0,會這樣寫我們的匿名函數

    
       public void Show()
       {
           {
               //.netframework 1.0的寫法
               DoNothingDelegate doNothing = new DoNothingDelegate(DoNothing);
               StudyDelegate study = new StudyDelegate(Study);
           }
       }
    

    在.netframework 2.0,會這樣寫匿名函數, 增加了一個delegate關鍵字

     {
         DoNothingDelegate doNothing = new DoNothingDelegate (delegate ()
         {
             Console.WriteLine("DoNothing");
         });
         StudyDelegate study = new StudyDelegate( delegate (int id, string name)
         {
             Console.WriteLine($"{id} {name} 學習 .Net高級班 ");
         });
     }
    

    在.netframework3.0,去掉了delegate關鍵字了,在參數后增加了一個=> goes to

    {
        DoNothingDelegate doNothing = new DoNothingDelegate(() =>
        {
            Console.WriteLine("DoNothing");
        });
        StudyDelegate study = new StudyDelegate((int id, string name) =>
        {
            Console.WriteLine($"{id} {name} 學習 .Net高級班 ");
        });
    }
    

    在.netframework3.0后期,我們可以省略參數的信息

     StudyDelegate study = new StudyDelegate((id, name) =>
     {
         Console.WriteLine($"{id} {name} 學習 .Net高級班 ");
     });
    

    如果匿名方法體中只有一行代碼,可以省略方法題的大括號

    StudyDelegate study = new StudyDelegate((id, name) =>Console.WriteLine($"{id} {name} 學習 .Net高級班 "));
    

    只有一個參數的時候,參數的小括號也可以省略掉。

    public delegate void StudyNew(int id);
    StudyNew study = id => Console.WriteLine($"{id} 學習 .Net高級班 ");
    

    如果方法返回值?
    如果lambda表達式中只有一行代碼,且有返回值,可以省略return,

    Func<int> retNum= () => 1;
    

    lamba函數的本質是什么?

    這里使用ilspy進行反編譯來看一下匿名方法的實現是怎么樣的

    img

    本質上來說,其實就是一個方法--匿名方法, 在類里面會生成和lambad 表達式參數和返回值完全匹配的方法.

    匿名類

    有時候,可以需要創建一個臨時的類對象,保存數據,方便使用。
    一個普通的類對象

    
      public class Student
      {
          public int Id { get; set; }
          public int ClassId { get; set; }
    
          public string Name { get; set; }
    
          public int Age { get; set; }
    
          public string Description { get; set; }
    
          public void Study()
          {
              Console.WriteLine($"{this.Id} {this.Name} 跟著老師學習 .Net開發");
    
          }
    
          public void StudyQt()
          {
              Console.WriteLine($"{this.Id} {this.Name} 跟著老師學習C++ Qt");
          }
      }
    
    

    當創建一個普通的類對象的時候,這樣去創建一個類對象。

     Student student = new Student()
     {
         Id = 1,
         ClassId = 2,
         Name = "張三",
         Age = 20,
         Description = "這是一個學生"
     };
    

    現在嘗試最原始的方法去創建一個匿名類,

    object model = new
    {
        Id = 1,
        Name = "小樓一夜聽春雨",
        Age = 14,
        Description = "魔刀丁鵬"
    };
    

    為什么可以定義一個匿名的對象?

    因為C#中所有的對象都繼承自Object對象.

    當嘗試使用.去訪問其中的屬性就會報錯.

    C#是強類型語言(編譯時決定類型),object是在編譯時確定類型,因為Object沒有Id等屬性,所以無法通過.去訪問其中的變量.

    因此可以使用下面的方法去訪問我們的匿名對象中的屬性.

     dynamic model1 = new
     {
         Id = 2,
         Name = "天下第一的劍客",
         Age = 18,
         Description = "神劍山莊謝曉峰"
     };
    
     Console.WriteLine(model1.Id);
     Console.WriteLine(model1.Age);
     Console.WriteLine(model1.Amy); //報錯
    

    這里使用了dynamic關鍵字去避開了編譯器的檢查,會在運行時檢查,運行時決定類型.這個出現亂取的問題,導致程序崩潰.

    有什么方法可以正確的取出想訪問的屬性,又可以避免訪問不存在的屬性那?
    var關鍵字

      var model2 = new
      {
          Id = 3,
          Name = "天下第二的劍客",
          Age = 16,
          Description = "不會劍法的阿飛"
      };
    
      Console.WriteLine(model2.Id);
      Console.WriteLine(model2.Name);
      //Console.WriteLine(model2.Aniu); //報錯!無法訪問不存在的變量
    

    var類型就是弱類型的變量.

    使用的注意事項?

    1. 不能在匿名類里面聲明方法,同時在聲明匿名類的屬性時候,就給定匿名類的屬性初始值.
    2. 不能給屬性重新賦值.
    3. var聲明的變量必須初始化,必須能推算出類型,也不允許作為方法的參數類型.

    使用的建議?

    1. var配合匿名類型使用
    2. var偷懶,配合復雜類型時使用。
    3. 在不知道具體什么類型的時候就可以使用var來聲明

    缺陷

    在代碼閱讀的時候,不是很方便。

    建議在大家寫代碼的時候,盡量明確類型。

    擴展方法

    為什么需要擴展方法?

    1. 擴展:讓功能變得更加強大,讓不存在功能存在. ---新增邏輯處理
    2. 已經存在方法,正常調用,擴展的東西不影響已經存在的方法
    3. 如果需求變更,需要支持另外的一個新的功能。

    接著上面學生的用例,我們可以追加一些需求.

    Student student1 = new Student()
    {
        Id = 1,
        ClassId = 2,
        Name = "張三",
        Age = 20,
        Description = "這是一個學生"
    };
    
    student1.Study();
    student1.StudyQt();
    
    

    如果要增加一個需求--學習嵌入式---直接增加方法.
    傳統的方式對原有的類進行結構上的修改.

    期望:既可以增加新的功能,歷史代碼不變.直接增加類,在新的類中去完成.

    這里就可以使用擴展方法來完成需求.

     public static class MethodExtension
     {
         public static void StudyEmbedded(this Student student)
         {
             Console.WriteLine($"{student.Id} {student.Name} 跟著老師學習嵌入式開發");
         }
     }
    

    program.cs

    student.StudyEmbedded();
    

    可以看到做的操作就是:

    1. 把類變成靜態類
    2. 把方法的第一個參數+this修飾

    這樣就完成了一個擴展方法.靜態方法的調用--可以像實例方法一樣去調用.

    不用修改原有的任何類中的類,可以新增功能;

    有哪些場景?

    1. 有新的需求來的時候--擴展方法--保證歷史代碼功能
    2. 要應用第三方的DLL庫(提供的功能不完善,我們自己需要升級下----dll,不能修改原有的代碼)擴展方法
    3. 封裝幫助類庫
    4. asp.net core 中,到處都是擴展方法--框架的設計--最小化設計.提供一個最基本、最最最簡單的功能,提供給調用方.這種方式在使用的時候,如果想要增強功能,就可以擴展. 好處:
      1. 盡可能簡化代碼
      2. 靈活分配,需要就擴展什么.按需擴展,不會有代碼冗余.

    這里有個問題,我可以給任意類型寫擴展方法嘛? 注意:擴展object類型.

     public static string SubObj(this object str, int len = 10)
     {
         if (str is null)
         {
             return string.Empty;
         }
    
         if (str.ToString().Length <= 10)
         {
             return str.ToString();
         }
         else
         {
             str = $"{str.ToString().Substring(0, len)}....";
             return str.ToString();
         }
    
     }
    

    program.cs

     object o = "object 類型";
     o.SubObj();
      
     int i = 1;
     i.SubObj();//可以
    
     string sr = "你好";
     sr.SubObj();
    
    
     str.SubGeneric();
     student.SubGeneric(); //隱患
    

    總結:

    1. 擴展的類型具有繼承性,擴展父類,所有子類都擁有這個功能;擴展的功能可能不適用一些具體的類型;但是仍然可以調用;可以造成一些類型的功能的污染;----慎用
    2. 不建議擴展object,也不是很建議大家去泛型擴展.
    posted @ 2024-03-14 16:16  飄雨的河  閱讀(413)  評論(0編輯  收藏  舉報
    免费视频精品一区二区_日韩一区二区三区精品_aaa在线观看免费完整版_世界一级真人片
    <bdo id="4g88a"><xmp id="4g88a">
  • <legend id="4g88a"><code id="4g88a"></code></legend>