2010-11-18 83 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

相关问题