亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 編程 > C# > 正文

C#中函數的創建和閉包的理解

2020-01-24 02:01:08
字體:
來源:轉載
供稿:網友

動態創建函數

大多數同學,都或多或少的使用過?;仡櫹耤#中動態創建函數的進化:

C# 1.0中:

復制代碼 代碼如下:

public delegate string DynamicFunction(string name);
  public static DynamicFunction GetDynamicFunction()
  {
      return GetName;
  }
  static string GetName(string name)
  {
      return name;
  }
  var result = GetDynamicFunction()("mushroom");

3.0寫慣了是不是看起來很繁瑣、落后。 剛學委托時,都把委托理解成函數指針,也來看下用函數指針實現的:

復制代碼 代碼如下:

char GetName(char p);
typedef char (*DynamicFunction)(char p);
DynamicFunction GetDynamicFunction()
{
    return GetName;
}
char GetName(char p)
{
    return p;
};
char result = GetDynamicFunction()('m');

對比起來和c# 1.0幾乎一模一樣了(引用/指針差別),畢竟是同一家族的。

C# 2.0中,增加匿名函數:

復制代碼 代碼如下:

 public delegate string DynamicFunction(string name);
      DynamicFunction result2 = delegate(string name)
      {
          return name;
      };

C# 3.0中,增加Lambda表達式,華麗的轉身:

復制代碼 代碼如下:

 public static Func<string, string> GetDynamicFunction()
 {
        return name => name;
 }
 var result = GetDynamicFunction()("mushroom");

匿名函數不足之處
雖然增加Lambda表達式,已經極大簡化了我們的工作量。但確實有些不足之處:

復制代碼 代碼如下:

var result = name => name;

這些寫編譯時是報錯的。因為c#本身強類型語言的,提供var語法糖只是為了省去聲明確定類型的工作量。 編譯器在編譯時必須能夠完全推斷出各參數的類型才行。代碼中的name參數類型,顯然在編譯時無法推斷出來的。
復制代碼 代碼如下:

var result = (string name) => name;
Func<string, string> result2 = (string name) => name;
Expression<Func<string, string>> result3 = (string name) => name;

上面直接聲明name類型呢,很遺憾這樣也是報錯的。代碼中已經給出答案了,編譯器推斷不出右邊表達式是屬于Func<string, string>類型還是Expression<Func<string, string>>類型。

復制代碼 代碼如下:

 dynamic result = name => name;
 dynamic result1 = (Func<string,string>)(name => name);

用dynamic呢,同樣編譯器也分不出右邊是個委托,我們顯示轉換下就可以了。
復制代碼 代碼如下:

Func<string, string> function = name => name;
DynamicFunction df = function;

這里定義個func委托,雖然參數和返回值類型都和DynamicFunction委托一樣,但編譯時還是會報錯:不能隱式轉換Func<string, string>到DynamicFunction,2個類型是不兼容的。

理解c#中的閉包

談論到動態創建函數,都要牽扯到閉包。閉包這個概念資料很多了,理論部分這里就不重復了。 來看看c#代碼中閉包:

復制代碼 代碼如下:

Func<Func<int>> A = () =>
        {
            var age = 18;
            return () =>  //B函數
            {
                return age;
            };
        };
        var result = A()();

上面就是閉包,可理解為就是: 跨作用域訪問函數內變量,也有說帶著數據的行為。
C#變量作用域一共有三種,即:類變量,實例變量,函數內變量。子作用域訪問父作用域的變量(即函數內訪問實例/類變量)在我們看來理所當然的,也符合我們一直的編程習慣。
例子中匿名函數B是可以訪問上層函數A的變量age。對于編譯器而言,A函數是B函數的父作用域,所以B函數訪問父作用域的age變量是符合規范的。

復制代碼 代碼如下:

int age = 16;
        void Display()
        {
            Console.WriteLine(age); 
            int age = 18;
            Console.WriteLine(age);
        }

上面編譯會報錯未聲明使用,編譯器檢查到函數內聲明age后,作用域就會覆蓋父作用域的age,(像JS就undefined了)。

復制代碼 代碼如下:

        Func<int> C = () =>
         {
             var age = 19;
             return age;
         };

上面聲明個同級函數C,那么A函數是無法訪C函數中的age變量的。 簡單來說就是不可跨作用域訪問其他函數內的變量。 那編譯器是怎么實現閉包機制的呢?

如上圖,答案是升級作用域,把A函數升級為一個實例類作用域。 在編譯代碼期間,編譯器檢查到B函數使用A函數內變量時,會自動生成一個匿名類x,把原A函數內變量age提升為x類的字段(即實例變量),A函數提升為匿名類x的實例函數。下面是編譯器生成的代碼(精簡過):

復制代碼 代碼如下:

class Program1
{
    static Func<Func<int>> CachedAnonymousMethodDelegate2;
    static void Main(string[] args)
    {
        Func<Func<int>> func = new Func<Func<int>>(Program1.B);
        int num = func()();
    }
    static Func<int> B()
    {
        DisplayClass cl = new DisplayClass();
        cl.age = 18;
        return new Func<int>(cl.A);
    }
}
sealed class DisplayClass
{
    public int age;
    public int A()
    {
        return this.age;
    }
}

我們再來看個復雜點的例子:

復制代碼 代碼如下:

static Func<int, int> GetClosureFunction()
    {
        int val = 10;
        Func<int, int> interAdd = x => x + val;
        Console.WriteLine(interAdd(10));
        val = 30;
        Console.WriteLine(interAdd(10));
        return interAdd;
    }
  Console.WriteLine(GetClosureFunction()(30));

輸出結果是20、40、60。 當看到這個函數內變量val通過閉包被傳遞的時候,我們就知道val不僅僅是個函數內變量了。之前我們分析過編譯器怎么生成的代碼,知道val此時是一個匿名類的實例變量,interAdd是匿名類的實例函數。所以無論val傳遞多少層,它的值始終保持著,直到離開這個(鏈式)作用域。

關于閉包,在js當中談論的比較多,同理,可以對比理解下:

復制代碼 代碼如下:

function A() {
    var age = 18;
    return function () {
        return age;
    }
}
A()();

閉包的優點

1.對變量的保護。想暴露一個變量值,但又怕聲明類或實例變量會被其他函數污染,這時就可以設計個閉包,只能通過函數調用來使用它。
2.邏輯連續性和變量保持。 A()是執行一部分邏輯,A()()僅接著A()邏輯繼續走下去,在這個邏輯上下文期間,變量始終都被保持著,可以隨意使用。

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
亚洲free性xxxx护士白浆| 久久香蕉频线观| 国产在线精品播放| 久久久久久久久久久91| 国产一区红桃视频| 国产精品高潮呻吟久久av黑人| 日韩成人在线电影网| 性欧美长视频免费观看不卡| 亚洲香蕉伊综合在人在线视看| 欧美日韩性视频| 97超级碰碰碰久久久| 日韩精品免费一线在线观看| 国产美女扒开尿口久久久| 国产精品人人做人人爽| 国产一区二区激情| 国产精品久久一| 日韩精品中文字幕在线| 国产日韩精品一区二区| 久久久影视精品| 在线观看日韩视频| 成人国产精品久久久| 亚洲高清一二三区| 亚洲二区在线播放视频| 97在线免费视频| 亚洲国产精品福利| 91av中文字幕| 国产精品久久久久久久久久久不卡| 久久影视电视剧凤归四时歌| 国产一区二区三区直播精品电影| 一区二区三区黄色| 欧美另类极品videosbestfree| 国产欧美最新羞羞视频在线观看| 久久久久久久97| 欧美成年人在线观看| 国产精品海角社区在线观看| 欧美重口另类videos人妖| 国产精品久久久久久久久久久久久| 国产精品一区二区久久| 国产精品最新在线观看| 国内精品一区二区三区四区| 91精品久久久久久久| 成人国产精品av| 午夜精品久久久久久久久久久久| 国产一区二区精品丝袜| 欧美日韩黄色大片| 日韩av最新在线观看| 97视频免费在线看| 久久综合久久美利坚合众国| 日韩欧美中文字幕在线播放| 精品国产31久久久久久| 成人写真视频福利网| 国内揄拍国内精品少妇国语| 国产精品91久久久久久| 久久亚洲私人国产精品va| 久久露脸国产精品| 欧美韩日一区二区| 136fldh精品导航福利| 日韩a**站在线观看| 久久久av网站| 亚洲激情视频在线播放| 欧美成人黄色小视频| 不卡伊人av在线播放| 国产精品免费小视频| 成人做爰www免费看视频网站| 亚洲xxx视频| 成人国产精品av| 精品自在线视频| 亚洲自拍偷拍一区| 亚洲第一免费网站| 精品中文字幕在线2019| 国产精品网址在线| 91美女福利视频高清| 久久99国产精品自在自在app| 91福利视频在线观看| 亚洲一区中文字幕在线观看| 亚洲欧美国产一区二区三区| 欧美又大又硬又粗bbbbb| 麻豆国产va免费精品高清在线| 日韩av手机在线| 91久久久精品| 97精品国产91久久久久久| 久久99视频精品| 久久这里有精品视频| 日韩大片在线观看视频| 91精品国产91久久久久久吃药| 另类美女黄大片| 影音先锋欧美精品| 亚洲精品91美女久久久久久久| 亚洲国产精品99久久| 久久精品91久久久久久再现| 91久热免费在线视频| 全球成人中文在线| 日韩中文字幕免费看| 欧美日韩一区二区免费视频| 91国语精品自产拍在线观看性色| 欧美电影免费观看网站| 欧美丝袜一区二区三区| 欧美成人精品在线播放| 欧美人成在线视频| 亚洲日本欧美中文幕| 中文字幕精品在线| 成人性教育视频在线观看| 国产精品网站视频| 色悠悠国产精品| 国产精品久久久一区| 中文字幕在线国产精品| 久久国产天堂福利天堂| 秋霞午夜一区二区| 欧美激情亚洲视频| 精品国产一区二区三区久久狼5月| 精品视频久久久久久久| 91亚洲国产成人久久精品网站| 久久久久久久久久久人体| 在线观看国产精品日韩av| 91中文精品字幕在线视频| 欧美国产日韩一区二区| 国内外成人免费激情在线视频| 俺也去精品视频在线观看| 日韩在线观看免费全集电视剧网站| 欧美视频精品一区| 性色av一区二区三区红粉影视| 亚洲性夜色噜噜噜7777| 欧美日韩国产丝袜美女| 日韩成人中文字幕在线观看| 日韩欧美在线免费观看| 97视频在线观看免费高清完整版在线观看| 51ⅴ精品国产91久久久久久| 这里只有精品视频在线| 国语自产精品视频在免费| 国产成人精品日本亚洲专区61| 亚洲精品小视频在线观看| 国产精品热视频| 日韩av一区二区在线观看| 亚洲精品永久免费| 视频在线观看99| 久久影视三级福利片| 91久久夜色精品国产网站| 久久免费精品日本久久中文字幕| 欧美性猛交99久久久久99按摩| 亚洲一区二区三区在线免费观看| 欧美大尺度激情区在线播放| 国产成人a亚洲精品| 欧美日韩国产va另类| 亚洲国产成人精品久久久国产成人一区| 中国china体内裑精亚洲片| 国产91精品久久久| 国产自产女人91一区在线观看| 成人亚洲综合色就1024| 久久97久久97精品免视看| 中文字幕久久久av一区| 亚洲电影天堂av| 亚洲午夜性刺激影院| 国产精品亚洲片夜色在线| 国产精品日韩专区| 欧美激情在线观看视频| 日韩在线视频中文字幕| 欧美成人免费小视频| 美日韩精品免费观看视频| 亚洲天堂av高清| 欧美性猛交xxxxx免费看| 国产精品免费网站| 国产日产欧美a一级在线| 日日狠狠久久偷偷四色综合免费| 亚洲最新视频在线|