Overriding LINQ extension methods

眉间皱痕 提交于 2019-12-05 10:30:47

Extension methods are static methods, and you can't override a static method. Nor can you "override" an actual instance method with a static/extension method.

You'll have to use your optimized extension explicitly. Or implicitly by referencing your own extension's namespace instead of System.Linq.

Or explicitly check the type in your extension and call the correct one based on the runtime type.

This seems like a problem better suited for inheritance than extension methods. If you want different functionality based on the runtime type, then make the base method virtual and override it in the derived classes.

I see a lot of confusion over this aspect of extension methods. You have to understand that they aren't mixins, they don't actually get injected into the class. They're just syntactic sugar that the compiler recognizes and "allows" you to execute it as if it were a regular instance method. Imagine that it wasn't an extension method, just a static method instead:

public static void BlowHorn (IBoat boat) {
    Console.WriteLine ("Patched on horn for {0}: TWEET", boat.GetType().Name);
}

How would you "override" this method from the IBoat implementation? You can't. The only thing you can do is put type checking into this static method, or write some dynamic method invocation code, either using a dynamic block in C# 4 or Reflection in earlier versions.

To make this even clearer, have a look at this code from the System.Linq.Enumerable class out of Reflector:

public static TSource ElementAt<TSource>(this IEnumerable<TSource> source, 
    int index)
{
    TSource current;
    if (source == null)
    {
        throw Error.ArgumentNull("source");
    }
        IList<TSource> list = source as IList<TSource>;
    if (list != null)
    {
        return list[index];
    }
// ...
}

This is one of the core extension methods in the .NET Framework. It allows optimization by explicitly checking if the parameter implements IList<T>. Other than this, it has no way of knowing whether or not the underlying concrete type actually supports indexed access. You'd have to do it this same way; create another interface like IHorn or something, and in your extension, check whether or not the IBoat also implements IHorn, same as the Enumerable class does here.

If you don't control the code for either the IBoat classes or the extension methods, then you're out of luck. If you do, then use multiple-interface inheritance, explicit type checking, or dynamic code, those are your options.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!