2010-11-18 46 views
2

我正在爲ASP.NET MVC做Nerd Dinner tutorial,我遇到了一種C#語言的構造,這看起來很奇怪。這個問題的標題有點含糊,因爲我很難定義這是什麼。這也使我很難搜索這個話題,因此我決定提出一個問題。在一個類中聲明一個靜態方法並將它用作另一個類的方法

Nerd Dinner tutorial我看到下面的代碼片段:

public static class ControllerHelpers { 

    public static void AddRuleViolations(this ModelStateDictionary modelState, IEnumerable<RuleViolation> errors) { 

     foreach (RuleViolation issue in errors) { 
      modelState.AddModelError(issue.PropertyName, issue.ErrorMessage); 
     } 
    } 
} 

後來他們表明:

// 
// GET: /Dinners/Edit/2 

public ActionResult Edit(int id) { 

    Dinner dinner = dinnerRepository.GetDinner(id); 

    return View(dinner); 
} 

// 
// POST: /Dinners/Edit/2 

[AcceptVerbs(HttpVerbs.Post)] 
public ActionResult Edit(int id, FormCollection formValues) { 

    Dinner dinner = dinnerRepository.GetDinner(id); 

    try { 

     UpdateModel(dinner); 

     dinnerRepository.Save(); 

     return RedirectToAction("Details", new { id=dinner.DinnerID }); 
    } 
    catch { 

     ModelState.AddRuleViolations(dinner.GetRuleViolations()); 

     return View(dinner); 
    } 
} 

讓我困惑的部分是:

public static void AddRuleViolations(this ModelStateDictionary modelState, IEnumerable<RuleViolation> errors) 

ModelState.AddRuleViolations(dinner.GetRuleViolations()); 

看起來您在ControllerHelpers類中定義AddRuleViolations函數,然後像調用ModelState屬性的實例函數那樣調用它。這個觀察是否正確?如果是,爲什麼你需要這個?我覺得在一個類中定義一個方法就好像它是另一個類的方法一樣。

注意:ModelState是當前類的屬性,而不是它自己的類。

回答

10

這是因爲它是extension method。這就是「this」位在第一個參數的開始處。

擴展方法的思想是,它們允許您有效地將功能添加到現有的類。所以,如果您有:

public static class StringExtensions 
{ 
    public static string Reverse(this string text) 
    { 
     char[] chars = text.ToCharArray(); 
     Array.Reverse(chars); 
     return new string(chars); 
    } 
} 

那麼你可以這樣調用:

string x = "hello world"; 
string y = x.Reverse(); 

,如果你會寫,實際上被編譯:

string x = "hello world"; 
string y = StringExtensions.Reverse(x); 

擴展方法必須是在頂級非泛型靜態類中聲明。他們在LINQ中大量使用。

+0

啊謝謝。如果沒有擴展方法關鍵字,我找不到任何關於它的內容。 – 2010-11-18 14:06:42

3

那個觀察確實是正確的;這是一個擴展方法,由參數型前this修改說明:

this ModelStateDictionary modelState 

然後,編譯器將解決的方法尋找ModelStateDictionary實例方法調用,但要注意它仍然是實際上一個靜態調用 - 這樣:

obj.SomeStaticMethod(arg1, arg2); 

實際上編譯爲:

TheDeclaringType.SomeStaticMethod(obj, arg1, arg2); 

這可能會導致古怪如obj可以null和電話仍然可以工作

+0

感謝您的回答。所以如果我調用'obj.SomeStaticMethod',並且'obj'爲'null',並且在函數內部執行'obj = new Object()'。而且是否可以用值類型來做到這一點? – 2010-11-18 14:08:02

+0

'Matthijs'你可以在方法*中給它一個值*,但該參數不是'ref'(並且不能),所以它將**從不**顯示回*方法外部。 'structs'不能爲空('Nullable '除外),但同樣適用:因爲它不是'ref',任何重新分配都不會反映在方法之外。 – 2010-11-18 14:12:04

相關問題