views:

164

answers:

1

Let's say I have an interface IMyInterface<T> that simply describes one function:

public interface IMyInterface<T>
{
    T MyFunction(T item);
}

I could just about replace this with Func<T, T>, but I want the interface for semantic reasons. Can I define an implicit conversion between that interface and Func<T,T> such that I could pass an anonymous delegate or lambda as an argument to a function that accepts this interface as a parameter, just like if I had used Func<T,T> instead?

To demonstrate, using the interface declared above I want a function like this:

public T TestFunction<T>(IMyInterface myInterface, T value)
{
    return myInterface.MyFunction(value);
}

That I can call like this:

TestFunction<string>( x => return x + " world", "hello");

And the result would be "hello world".

+3  A: 

Since interfaces in C# cannot contain definitions for operators (or any static methods for that matter), I believe the answer is no. The alternative is to use a class (can't be abstract unfortunately, since static members/operators fair no better here than in interfaces). This would allow you to define the implicit conversion operator and therefore be able to use the type precisely how you've specified.

In the class (which you could perhaps make virtual if required), you would define it something like the following.

public class MyClass<T>
{
    public static implicit operator MyClass<T>(Func<T, T> func)
    {
        return new MyClass<T>() { MyFunction = func };
    }

    public MyClass()
    {
    }

    public Func<T, T> MyFunction
    {
        get;
        set;
    }
}

Your definition of TestFunction in your question should then work exactly as you coded it.

public T TestFunction<T>(IMyInterface myInterface, T value)
{
    return myInterface.MyFunction(value);
}

And likewise the call to TestFunction:

TestFunction<string>(x => return x + " world", "hello");

This may not be precisely what you're looking for, but it's nonetheless reasonably close, and moreover very likely the best you'll be able to get.

Noldorin
How does TestFunction convert a lambda into IMyInterface? You define a class MyClass, not an interface. Some more editing required, I think...
Daniel Earwicker
@Earwicker: Take a closer look - the implicit conversion operator should do that for you, unless I'm mistaken. Also, if you read the start of my post I mention that it's not possible with an interface, and only a (non-abstract) class.
Noldorin
This is pretty much what I expected, but I've been known to overlook things before and hoped that would be the case this time. Sadly, it's not. In fact I already had my own concrete implementation that is eerily similar to what you posted.
Joel Coehoorn
Yeah, anything "better" would require support for static interfaces, and unfortunately that doesn't exist (maybe something for a future version of C#?). At least it's a positive sign in terms of design that we've come to very similar implementations. :)
Noldorin