【问题标题】:Anonymous interface implementation匿名接口实现
【发布时间】:2014-07-24 10:26:40
【问题描述】:

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

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

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

【问题讨论】:

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


    【解决方案1】:

    .NET 2.0 也支持匿名委托,只是语法比 lambda 更冗长,并且类型推断不起作用。 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 => { }
    );
    

    【讨论】:

    • 好吧,我实际上并没有寻找更短的方法,而是寻找一种内联方式来执行此操作。这是因为创建在特定上下文中只使用一次的类型对我来说很烦人。
    • 好吧,正如另一个答案中所述,在 .NET 中是不可能的(即使在当前的 .NET 4.5 中也是如此)。如果您的接口是单方法接口,那么它在功能上等同于委托,您可以匿名创建它。如果没有,您要么必须使用鸭子类型/代理框架(Castle、LinFu 和其他)(另一方面,它仍然不允许您内联),或者,您可以创建一个类实现你的接口,但实际上只调用实例化期间设置的委托。
    • 是的,我的接口是单方法的,那如何使它成为委托(不改变接口本身ofc)?
    • @HimBromBeere:添加了几个例子。
    • 哇,我想要 .NET 4.0... 这个表达式让我想起了 Javascript:getStuff = function(...) {...}
    【解决方案2】:

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

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2015-09-30
      • 2016-07-31
      • 1970-01-01
      • 1970-01-01
      • 2010-09-16
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多