匿名接口实现

时间:2014-07-24 10:26:41

标签: java c# .net-2.0 anonymous-class

我已经阅读了'C# anonymously implement interface (or abstract class)'线程,用于匿名实现接口。但我想知道使用.NET 2.0(NO LINQ)使用委托或任何类似的方法是否也可以。我从JAVA了解到以下可能:

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

(我希望我记得很清楚,就在不久之前我使用过JAVA,但我想这是类似的东西)。当方法需要接口的实例并且只调用一次时,这可能会有所帮助,因此不需要为此单个方法创建新类。

2 个答案:

答案 0 :(得分:1)

.NET 2.0也支持匿名委托,只是语法比lambdas更冗长,类型推断不起作用。并且在C#2.0中没有扩展方法(尽管您可以使用C#3.0并针对.NET 2.0进行编译),这是LINQ的基础并且能够在接口上运行。

比较

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

.NET 2.0也缺少常见的通用委托签名(FuncAction),但您也可以自己轻松定义它们(对于您喜欢的所有参数组合):

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

因此,无论采用何种方法,用于模仿匿名接口的链接答案都可以使用.NET 2.0委托来表示,但代价是增加了详细程度。让你自问:“这真的 更短吗?”

<强> [更新]

如果您的界面是单一方法界面,例如:

interface IFoo
{
    string Bar(int value);
}

class SomeOtherClass
{
    void DoSomething(IFoo foo);
}

那么你可以完全摆脱它,而只需使用代理:

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

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

如果您有一个界面,其中包含许多您希望能够在许多不同位置内联实现的方法,您可以使用以下内容:

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
}

允许您将代理传递给内联DelegatedFoo类:

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

使用 .NET 4 C#4.0语法,由于lambdas和命名参数的语法甜度,它看起来会更清晰:

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

答案 1 :(得分:0)

我知道这可能不是您所希望的,但如果您必须这样做,您可以使用任何可用的模拟框架来请求实现该接口的对象,然后为这些方法添加实现。这是TDD的标准做法。

此外,您可以根据John Skeet在您提到的问题中的建议,使用匿名代表来满足您的大部分需求。