Let's say I have an interface, like this:
public interface ILoggable
{
void Log(Func<string> message, Logger.Type type);
}
And some extension methods, like this:
public static class Logger
{
public static void Log(this ILoggable loggable, Func<string> message) { loggable.Log(message, Type.Information); }
public static void Log(this ILoggable loggable, string prefix, byte[] data, int len) { /* snip */ }
public static void Log(this ILoggable loggable, Exception ex) { /* snip */ }
// And so on...
}
Then in any class CoreService : ServiceBase, ILoggable
or such I implement that public void Log(Func<string> message, Logger.Type type)
to whatever I like (public modifier being kind of meh...) and use all the extension methods to do actual logging.
So far so good... or not so good? Is there something wrong with this approach? If not, then why the inconvenience:
catch (Exception ex) {
this.Log(ex); // this works
Log(ex); // this goes not
It seems like a reasonable approach to me in itself1 - but the requirement to explicitly state
this
is just part of how the language works around extension methods. I suspect this makes aspects of the language specification cleaner, and this requirement is sufficiently rare (and the workaround sufficiently easy) that it was felt to be better to go with the current solution than to make things more complicated just to avoid five characters in a relatively rare scenario.Member lookup for simple names (section 7.6.2 of the C# 4 spec) is complicated enough without making it worse. Don't forget that the simple name can refer to a type or a type parameter, as well as a method. There's a lot going on there already.
When I get to work I'll check if there are any annotations around section 7.6.5.2 (extension method invocation) which give "inside information" about this.
1 On reflection, it does seem slightly odd for the entity doing the logging to also want to log other things - the only kind of exception I'd expect it to see would be when the logging is failing, in which case logging the exception would fail too.