Anonymous interface implementation

2019-01-20 20:17发布

问题:

I´ve read 'C# anonymously implement interface (or abstract class)' thread for implementing an interface anonymously. But I wondered if this is also possible using .NET 2.0 (NO LINQ) using delegates or any similar approach. I know from JAVA the following possible:

MyClass m = MyMethod(new MyInterface() {
    @override
    public void doSomething() {...}
}

(I hope I remember well, is a time ago that I used JAVA, but I suppose it was something similar). This might be helpful whenever a method needs an instance of an interface and is called only once so there is no need to create a new class for this single approach.

回答1:

.NET 2.0 also supported anonymous delegates, it's just that the syntax was a bit more verbose compared to lambdas, and type inference didn't work. And there were no extension methods in C# 2.0 (although you were able to use C# 3.0 and compile against .NET 2.0), which are the basis of LINQ and being able to operate on interfaces.

Compare:

  • .NET 2.0: delegate(int i) { return (i < 5); }
  • .NET 3.5: i => i < 5

.NET 2.0 also lacks common generic delegate signatures (Func and Action), but you can also easily define them yourself (for all combinations of parameters you like):

public delegate void Action<T>(T item);
public delegate Tresult Func<T, Tresult>(T item);

So, whatever approach your linked answer used to mimic anonymous interfaces can be represented using .NET 2.0 delegates, at the expense of added verbosity. Making you ask yourself: "is this really that shorter to write?"

[Update]

If your interface is a single method interface, like:

interface IFoo
{
    string Bar(int value);
}

class SomeOtherClass
{
    void DoSomething(IFoo foo);
}

then you might get rid of it entirely and simply use a delegate instead:

class SomeOtherClass
{
    void DoSomething(Func<int, string> bar);
}

new SomeOtherClass().DoSomething(delegate(int i) { return i.ToString(); });

If you have an interface with many methods that you want to be able to implement inline in many different places, you can use something like this:

interface IFoo
{
    string GetSomething();
    void DoSomething(int value);
}

// conditional compile, only if .NET 2.0
#if NET_2_0
public delegate void Action<T>(T item);
public delegate Tresult Func<Tresult>();
#endif

class DelegatedFoo : IFoo
{
    private readonly Func<string> _get;
    private readonly Action<int> _do;

    public DelegatedFoo(Func<string> getStuff, Action<int> doStuff)
    {
        _get = getStuff;
        _do = doStuff;
    }

    #region IFoo members simply invoke private delegates

    public string GetSomething()
    { return _get(); }

    public void DoSomething(int value)
    { _do(value); }

    #endregion
}

Which would allow you to pass delegates to the DelegatedFoo class inline:

var delegated = new DelegatedFoo(
    delegate() { return ""; }, // string GetSomething()
    delegate(int i) { }        // void DoSomething(int)
);

Using .NET 4 the C# 4.0 syntax it would look a bit cleaner due to syntactic sweetness of lambdas and named parameters:

var delegated = new DelegatedFoo(
    getStuff: () => "",
    doStuff:  i => { }
);


回答2:

I know that this may not be exactly what you are hoping for, but if you absolutely have to do it, you can use any of the mocking frameworks available to request an object which implements the interface and then add implementations for the methods. This is a standard practice in TDD.

Also, you can simply use anonymous delegates to achieve most of your needs as per John Skeet's advice in the question your mention.