简体   繁体   中英

Declaring a static method in one class and using it as a method of another class

I am doing the Nerd Dinner tutorial for ASP.NET MVC and I met one construction in the C# language that seemed very strange. The title of this question is a bit vague, because I have trouble defining what this is. This also made it difficult for me to search about the topic, hence I decide to ask a question about it.

In the Nerd Dinner tutorial I see the following code fragment:

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);
        }
    }
}

And later they show:

//
// 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);
    }
}

The parts that puzzle me are:

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

and

ModelState.AddRuleViolations(dinner.GetRuleViolations());

It looks like you define the AddRuleViolations function in the ControllerHelpers class and then invoke it as if it was an instance function of the ModelState property. Is this observation correct? If yes, why would you need this? It looks very strange to me to define a method in one class as if it was a method of another class.

Note: ModelState is a property of the current class and not a class it self.

It's because it's an extension method . That's what the "this" bit is at the start of the first parameter.

The idea of extension methods is that they allow you to effectively add functionality to existing classes. So if you have:

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

then you can call it like this:

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

that actually gets compiled as if you'd written:

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

Extension methods have to be declared in top-level non-generic static classes. They're heavily used in LINQ.

That observation is indeed correct; this is an extension method , as noted by the this modifier before the parameter-type:

this ModelStateDictionary modelState

The compiler will then resolve calls to the method looking like an instance method of ModelStateDictionary , but note that it is still actually a static call - so:

obj.SomeStaticMethod(arg1, arg2);

is actually compiled as:

TheDeclaringType.SomeStaticMethod(obj, arg1, arg2);

which can result in oddities such as obj can be null and the call will still work .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM