使用Func键<>通过接口? [英] Using a Func<> over an interface?

查看:172
本文介绍了使用Func键<>通过接口?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个已经存在的泛型类

I have an already existing generic class

public class Foo<T>
{
    private T _item;
    public Foo(T item){ _item = item;}
}



我要创建将返回T.结果
的某些属性我在这里看到两个解决方案的方法。

I have to create a method which will return a certain property of T.
I see two solutions here.


  1. 创建接口:

  1. Creating an interface :

public const string TestVar = "bar";
public interface INamable { string Name { get; } }
public class Bar : INamable
{
    public string Name { get { return TestVar; } }
}

public class Foo<T> where T : INamable
{
    private T _item;
    public Foo(T item) { _item = item; }
    public string GetName() { return this._item.Name; }
}

[TestMethod()]
public void TestInterface()
{
    var bar = new Bar();
    var foo = new Foo<Bar>(bar);
    Assert.AreEqual(TestVar, foo.GetName());
}


  • 传递一个FUNC:

  • Passing a Func :

    public const string TestVar = "bar";
    public class Bar
    {
        public string Name { get { return TestVar; } }
    }
    
    public class Foo<T>
    {
        private T _item;
        private Func<T, string> _funcName;
        public Foo(T item, Func<T, string> funcName) { _item = item; _funcName = funcName; }
        public string GetName() { return _funcName.Invoke(_item); }
    }
    
    [TestMethod()]
    public void TestFunc()
    {
        var bar = new Bar();
        var foo = new Foo<Bar>(bar, b => b.Name);
        Assert.AreEqual(TestVar, foo.GetName());
    }
    


  • 我去的第二个解决方案,因为我没有创建一个接口,而且我很懒。只要有一个参数添加到已调用foo的构造。

    I go with the second solution, since I don't have to create an interface, and I'm lazy. Just have to add one parameter to the already call of the foo constructor.

    此外,Foo类仍然可以使用所有种类类的使用,我更喜欢这个方式。

    Moreover, the Foo class can still be used with all sort of class, and I prefer it this way.

    ,但我不知道它是否是使用一个函数功能的好方法吗?它仍然很好,很扎实?这是我第一次尝试使用Func键,这就是为什么我问我自己!

    BUT, I'm not sure if it is the good way to use a Func? Is it still nice and SOLID? This is my first try to use a Func, that's why I'm asking myself!

    几个月前,我用的第一个解决方案,与经典界面...

    A couple of months ago I used the first solution, with classic interface...

    推荐答案

    我重新措辞我的答案,因为从评论,我意识到我还没有非常明确的。

    I'm re-phrasing my answer, because from the comments I realized I haven't been very clear.

    这取决于意图你的代码,对谁都有责任给一个名字到类(客户端应该知道,并指定如何命名类VS类本身应该有一个名称)。我改变了@ Scorpi0的例子一点,让富实际上做的东西的名称(它迎接它)而不是只返回了。

    It depends on the intent of your code and on who has the responsibility to give a name to your classes (the client should know and specify how to name the classes vs the classes should inherently have a Name). i'm changing @Scorpi0's example a little, so that Foo actually does something with the name (it greets it) instead of just returning it.

    interface INamable { string Name { get; } }
    
    class AThingWithAName : INamable 
    {
        public string Name {get {return "thing";}}
    }
    
    class AnotherThingWithAName : INamable 
    {
        public string Name {get {return "different thing";}}
    }
    
    class Foo<T> where T : INamable
    {
        public string Greet(T item) {return "hi " + item;}
    }
    

    下面有东西,无论美孚的名称。富都知道,只要他们有一个名称(这是由合同保证他们实现INamable接口)如何迎接的事情。
    在这里要保证美孚仅适用于事物的名称和尝试迎接什么都应该是由编译器捕获类型错误。

    Here Things have a Name regardless of Foo. Foo knows how to Greet Things as long as they have a Name (which is guaranteed by contract by them implementing the INamable interface). Here you want to guarantee that Foo only works on things with a Name and attempts to greet anything else should be a type error caught by the compiler.

    另外请注意,你在封装每个类的具体实施姓名。名称可以依赖于它的类的私有状态。

    Also, note that you're encapsulating the concrete implementation of Name in each class. Name could depend on its class's private state.

    class AThing {}
    class AnotherUnrelatedThing {}
    
    class Foo<T>
    {
        public string Greet(T item, Func<T, string> namingFunction) 
        {
            return "hi " + namingFunction(item);
        }
    }
    



    在这里强调的是富。事情并不一定有一个名称。我想建立一个类Foo,可以迎接任何事情。它是如何做到的?嗯,这是主叫方的责任,对任何类型的,可以给一个名称的类型的函数来传递。
    在这种情况下,不仅我们没有要求那件T知道自己的名义保证,但我们的方式构建富,它可以迎接任何类型的,只要我们知道如何给它一个名称。比如这个作品:

    Here the emphasis is on Foo. Things don't necessarily have a Name. I want to build a class Foo that can greet anything. How does it do that? Well, it's the caller's responsibility, for any Type, to pass in a function that can give a name to that type. In this case, not only we're not requesting a guarantee that T knows its own Name, but we're building Foo in a way that it can Greet any type, as long as WE know how to give it a name. For instance this works:

    var foo = new Foo<int>();
    var res=foo.Greet(2, n=>n.ToString());
    

    在交换灵活性,我们放弃了封装。现在名称不再东西是类的责任落实,我们(来电)告诉美孚如何给一个名字我们每次与使用它的类。

    In exchange for that flexibility, we're giving up encapsulation. Now Name is no longer something that is the class's responsibility to implement, we (the caller) are telling Foo how to give a name to each class we use it with.

    所以,这取决于你想表达的,如果你有一个有一个名字,无论富的对象的层次结构,您可以选择一种或另一种方式是什么。

    So, depending on what you want to express and if you have a hierarchy of objects that have a name regardless of Foo, you may choose one or the other way.

    这篇关于使用Func键&LT;&GT;通过接口?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

    查看全文
    相关文章
    登录 关闭
    扫码关注1秒登录
    发送“验证码”获取 | 15天全站免登陆