Overriding LINQ extension methods
- by Ruben Vermeersch
Is there a way to override extension methods (provide a better implementation), without explicitly having to cast to them? I'm implementing a data type that is able to handle certain operations more efficiently than the default extension methods, but I'd like to keep the generality of IEnumerable. That way any IEnumerable can be passed, but when my class is passed in, it should be more efficient.
As a toy example, consider the following:
// Compile: dmcs -out:test.exe test.cs
using System;
namespace Test {
public interface IBoat {
void Float ();
}
public class NiceBoat : IBoat {
public void Float () {
Console.WriteLine ("NiceBoat floating!");
}
}
public class NicerBoat : IBoat {
public void Float () {
Console.WriteLine ("NicerBoat floating!");
}
public void BlowHorn () {
Console.WriteLine ("NicerBoat: TOOOOOT!");
}
}
public static class BoatExtensions {
public static void BlowHorn (this IBoat boat) {
Console.WriteLine ("Patched on horn for {0}: TWEET", boat.GetType().Name);
}
}
public class TestApp {
static void Main (string [] args) {
IBoat niceboat = new NiceBoat ();
IBoat nicerboat = new NicerBoat ();
Console.WriteLine ("## Both should float:");
niceboat.Float ();
nicerboat.Float ();
// Output:
// NiceBoat floating!
// NicerBoat floating!
Console.WriteLine ();
Console.WriteLine ("## One has an awesome horn:");
niceboat.BlowHorn ();
nicerboat.BlowHorn ();
// Output:
// Patched on horn for NiceBoat: TWEET
// Patched on horn for NicerBoat: TWEET
Console.WriteLine ();
Console.WriteLine ("## That didn't work, but it does when we cast:");
(niceboat as NiceBoat).BlowHorn ();
(nicerboat as NicerBoat).BlowHorn ();
// Output:
// Patched on horn for NiceBoat: TWEET
// NicerBoat: TOOOOOT!
Console.WriteLine ();
Console.WriteLine ("## Problem is: I don't always know the type of the objects.");
Console.WriteLine ("## How can I make it use the class objects when the are");
Console.WriteLine ("## implemented and extension methods when they are not,");
Console.WriteLine ("## without having to explicitely cast?");
}
}
}
Is there a way to get the behavior from the second case, without explict casting? Can this problem be avoided?