C# - using extension methods to provide default interface implementation
c#, extension-methods, interface
Solution
I'd generally recommend a base class, however, if that's out, you can do something like this:
public interface IAnimal { }
public interface INoisyAnimal : IAnimal {
string MakeSound();
}
public static class AnimalExtensions {
public static string MakeSound(this IAnimal someAnimal) {
if (someAnimal is INoisyAnimal) {
return (someAnimal as INoisyAnimal).MakeSound();
}
else {
return "Unknown Noise";
}
}
}
public class Dog : INoisyAnimal {
public string MakeSound() {
return "Bark";
}
}
public class Porcupine : IAnimal { }
This makes every `IAnimal` look like a `INoisyAnimal` even if it isn't really one. For example:
IAnimal dog = new Dog();
IAnimal porcupine = new Porcupine();
Console.WriteLine(dog.MakeSound()); // bark
Console.WriteLine(porcupine.MakeSound()); // Unknown Noise
However, this still isn't an actual implementation of the interface. Notice that despite appearances
Console.WriteLine(porcupine is INoisyAnimal); // false
Another option might be to create a wrapper to extend your base class when new functionality is needed:
public class NoisyAnimalWrapper : INoisyAnimal {
private readonly IAnimal animal;
public NoisyAnimalWrapper(IAnimal animal) {
this.animal = animal;
}
public string MakeSound() {
return "Unknown Noise";
}
}
public static class AnimalExtensions {
public static INoisyAnimal Noisy(this IAnimal someAnimal) {
return someAnimal as INoisyAnimal ??
new NoisyAnimalWrapper(someAnimal);
}
}
Then you can create a `INoisyAnimal` from any `IAnimal` whenever you need to:
INoisyAnimal dog = new Dog();
INoisyAnimal porcupine = new Porcupine().Noisy();
Console.WriteLine(dog.MakeSound()); // bark
Console.WriteLine(porcupine.MakeSound()); // Unknown Noise
You could also make the wrapper generic (e.g. `NoisyAnimal<T> where T : IAnimal, new`) and get rid of the extension method altogether. Depending on your actual use case, this may be preferable to the previous option.
Problem
I'm just learning about C# extension methods, and was wondering if I can use it to provide a default implementation for an interface. Say: ``` public interface Animal { string MakeSound(); } public static string MakeSound(this Animal) { return ""; } ``` Then ``` public class Dog : Animal { string MakeSound() { return "Bark"; } } public class Porcupine : Animal { } ``` And last: ``` Animal dog = new Dog(); Animal porcupine = new Porcupine(); Print(dog.MakeSound()); Print(porcupine.MakeSound()); ``` I'd like the porcupine and any other animals that have not explicitly implemented `MakeSound` to use the default extension method that returns an empty string, but dog and any animal that does have an explicit implementation return its own implementation such as "Bark". So my questions: 1. Is this doable? 2. If not, is there any other way to implement default behavior for an interface? Abstract class instead of interface is not an option because C# doesn't support multiple inheritance and my classes are inheriting behavior of another class.