Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C# extension method for a method group

I want to implement an extension method for a method. Consider the following code sample (http://dotnetfiddle.net/HztiOo) :

using System;
using System.Collections.Generic;

public class Program
{
    public static void Main()
    {
        A a = new A();
        // Noticed that Next() is called twice
        Console.WriteLine(a.Next(1));
        Console.WriteLine(a.Next(1));

        // Works
        var withCache = ((Func<int,int>)a.Next).AddCaching();
        withCache = new Func<int,int>(a.Next).AddCaching();
        withCache = ExtensionMethods.AddCaching<int,int>(a.Next);

        // Doesn't work :(
        // withCache = a.Next.AddCaching<int,int>();
        // Func<int,int> withCache = a.Next.AddCaching();

        // Notice that Next() is only called once
        Console.WriteLine(withCache(1));
        Console.WriteLine(withCache(1));
    }
}

public class A
{
    public int Next(int n)
    {
        Console.WriteLine("Called Next("+n+")");
        return n + 1;
    }
}

public static class ExtensionMethods
{
    public static Func<TKey,TVal> AddCaching<TKey,TVal>(this Func<TKey,TVal> fetcher)
    {
        var cache = new Dictionary<TKey, TVal>();
        return k =>
        {
            if (!cache.ContainsKey(k)) cache[k] = fetcher(k);
            return cache[k];
        };
    }
}

I would like to be able to call the extension method without an explicit cast. In both "doesn't work" examples above, the type system should be able to figure out which overload to use on its own...

Why can't I just use a.Next.AddCaching<int,int>() ?

Note: this is just an example, I am not interested in discussing the best way to add a cache to a method invocation, as there are many other possibilities for this kind of extensions.

like image 314
Thomas Avatar asked Apr 02 '14 14:04

Thomas


1 Answers

According to Eric Lippert blog method group is typeless expression. And you can't do anything, just deal with it.

That's exact reason why you can't implicitly cast it to specific delegate and add extension method to it

like image 51
Uriil Avatar answered Oct 01 '22 03:10

Uriil