2012-05-24 13 views
2

我的代碼中有一個操作方法如下:爲什麼我的外部C#函數的參數列表中存在「this」?

catch (Exception e) 
    { 
     log(e); 
     return Content(ExceptionExtensions.GetFormattedErrorMessage(e)); 
    } 

的函數調用看起來像這樣:

public static class ExceptionExtensions 
{ 
    public static string GetFormattedErrorMessage(this Exception e) 

      if (e == null) 
     { 
      throw new ArgumentNullException("e"); 
     } 

有人能解釋爲什麼有一個「本」在參數列表的開始?

回答

8

這是擴展方法的簽名。它們是在.NET3.5(C#3)中引入的。如果沒有this,編譯器會將其作爲靜態方法簽名。 下面的代碼:

public class Foo 
{ 
    public void FooBar() 
    { 

    } 
} 
public static class FooEx 
{ 
    public static void Bar(this Foo f) 
    { 
     f.FooBar(); 
    } 
    public static void StaticBar(Foo f) 
    { 
     f.FooBar(); 
    } 
} 

你可以這樣調用靜態方法:

FooEx.StaticBar(new Foo()); 

和擴展方法是這樣的:

new Foo().Bar(); 

和擴展方法爲靜態方法:

FooBar.Bar(new Foo()); 

因此,要將擴展方法轉換爲靜態方法,您只需從簽名中刪除this關鍵字。 但是,如果你想一個靜態方法轉換成一個擴展方法,你必須:

  1. this關鍵字添加到簽名
  2. 把方法變成非嵌套public static
  3. 充分利用該方法public

Scott Hanselman has a good article對語法的選擇,以及如何訪問修飾符它符合現有的CLR以最小的改動編譯器。

總之,他得出結論,在編譯之後,生成的靜態方法的IL代碼和擴展方法的代碼沒有區別。 關鍵字this指示編譯器將某些元數據放在擴展方法的周圍。

我的猜測是,他們已經爲this關鍵字了,因爲1.it已經存在,並且2.它的現有含義與其他現有關鍵字相比,最適合擴展方法的上下文。

+1

也許增加一些OP可以這樣調用函數的東西:'e.GetFormattedErrorMessage()'。 – Marlon

+0

對不起,如果這聽起來像一個愚蠢的問題,但你能猜出它爲什麼這樣編碼的任何原因。此外,如果我想將其改爲靜態方法,我怎麼能這樣做,哪些是劣勢? –

+0

@SamanthaJ擴展方法*是*靜態方法,它們可以使用正常的靜態方法語法或擴展方法(準實例方法)語法來調用。出於這個原因,我相信,目前的例子不會編譯,雖然我沒有編譯器方便檢查。 – phoog

-1

「this」是傳遞給Exception方法的錯誤,類似於在函數中使用「this」。它只是指正在通過的例外。

+0

-1:不,「'this'」是傳遞給'GetFormattedErrorMessage'擴展方法的'Exception'。 –

2

因爲這就是你如何定義'擴展'方法。它可以讓編譯器知道這個特定的方法應該被允許直接在對象上調用,它可以讓你寫這樣的代碼:

GetFormattedErrorMessage(e); 

,而不是爲:

e.GetFormattedErrorMessage(); 

我不知道爲什麼你發佈的代碼是以這種方式調用函數。你應該能夠直接在異常對象上調用該函數。擴展方法本質上就是擴展你以前無法修改的內置類/類型的行爲的方法。

相關問題