简体   繁体   中英

C# - calling extension method without qualifying with class name, instance method syntax vs static syntax

I have an IResult<TResult> generic class and subclasses Success<TResult> and Failure<TResult> used for representing successful/failed results and associated information. To cut down on the cumbersome repetition of generic parameters all over the place (it's easy enough when TResult is just a class, but gets very ugly if there's nested generics), I have an extension method to help with building:

public static class SuccessExtensionsClass
{
    public static BuildSuccess<TResult> Success<TResult>(this TResult result)
    {
        return new Success<TResult>(result);
    }
}

Now I can do something like:

TResult blah = new TResult();

then

return blah.BuildSuccess();

So far so good. I don't need to supply the generic type to the extension method, as desired.

However, if I were to use the syntax:

BuildSuccess(blah)

I get a compiler error about the missing generic type parameter. Now, on the other hand, if I change it to:

BuildSuccess<TResult>(blah)

It can't find the method until I specify the class as with a normal static method:

SuccessExtensionClass.BuildSuccess<TResult>(blah)

works fine, as does:

SuccessExtensionClass.BuildSuccess(blah)

Why? Or, more specifically, what motivated this choice? The compiler has all the same information available in both cases, as the error about a missing generic type when called as BuildSuccess(blah) makes very clear. Is it just a design choice that extension methods can only be called without being qualified with their class name when in extension syntax? Is this for purposes of code clarity alone or is there another reason I'm not thinking of?

As a follow-up, why wouldn't the static syntax be subject to the same rule as instance method syntax, where the compiler will (only) resolve the name if you have explicitly imported the namespace?

edit for hopefully more clarity:

When in instance syntax, I don't have to call the extension method as:

blah.SuccessExtensionsClass.BuildSuccess()

but in static syntax I do need to call it as:

SuccessExtensionsClass.BuildSuccess(blah)

Is this simply to enforce clarity?

Extension methods are static methods that can be called with the first argument written before the method name, separated from it by a dot, so it looks as if it was an instance method:

blah.BuildSuccess()

In this example, blah is really the first argument to the static method. This is what extension methods are about.

You seem to desire another syntax, namely:

BuildSuccess(blah)

Of course, that syntax is legal already if you happen to be inside the class that defines the method. But if you want that syntax to apply more generally, what you seek is not extension methods but simply using static directives .

So drop the this modifier:

namespace Your.Relevant.Name
{
  public static class SuccessHelperMethods
  {
    public static Success<TResult> BuildSuccess<TResult>(TResult result)
    {
      return new Success<TResult>(result);
    }
  }
}

Then with:

using static Your.Relevant.Name.SuccessHelperMethods;

at the top of your compilation unit (code file), this syntax will be legal:

BuildSuccess(blah)

Note: The using static directive will not allow this syntax if you keep the this modifier (extension method declaration).

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