Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/329.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C#:返回';这';用于方法嵌套?_C#_Methods_Return Value_Fluent Interface - Fatal编程技术网

C#:返回';这';用于方法嵌套?

C#:返回';这';用于方法嵌套?,c#,methods,return-value,fluent-interface,C#,Methods,Return Value,Fluent Interface,我有一个类,我必须多次调用一个或两个方法。这些方法当前返回void。我在想,让它返回this,这样方法就可以嵌套了,这样会更好吗?或者这被认为是非常糟糕的?或者如果不好,如果它返回相同类型的新对象会更好吗?或者你怎么想?例如,我创建了加法器类的三个版本: // Regular class Adder { public Adder() { Number = 0; } public int Number { get; private set; } public void

我有一个类,我必须多次调用一个或两个方法。这些方法当前返回
void
。我在想,让它返回
this
,这样方法就可以嵌套了,这样会更好吗?或者这被认为是非常糟糕的?或者如果不好,如果它返回相同类型的新对象会更好吗?或者你怎么想?例如,我创建了加法器类的三个版本:

// Regular
class Adder
{
    public Adder() { Number = 0; }

    public int Number { get; private set; }

    public void Add(int i) { Number += i; }
    public void Remove(int i) { Number -= i; }
}

// Returning this
class Adder
{
    public Adder() { Number = 0; }

    public int Number { get; private set; }

    public Adder Add(int i) { Number += i; return this; }
    public Adder Remove(int i) { Number -= i; return this; }
}

// Returning new
class Adder
{
    public Adder() : this(0) { }
    private Adder(int i) { Number = i; }

    public int Number { get; private set; }

    public Adder Add(int i) { return new Adder(Number + i); }
    public Adder Remove(int i) { return new Adder(Number - i); }
}
第一个可以这样使用:

    var a = new Adder();
    a.Add(4);
    a.Remove(1);
    a.Add(7);
    a.Remove(3);
    var a = new Adder()
        .Add(4)
        .Remove(1)
        .Add(7)
        .Remove(3);
其他两个可以这样使用:

    var a = new Adder();
    a.Add(4);
    a.Remove(1);
    a.Add(7);
    a.Remove(3);
    var a = new Adder()
        .Add(4)
        .Remove(1)
        .Add(7)
        .Remove(3);
其中唯一的区别是
a
在第一种情况下是
新加法器()
,而在后一种情况下是最后一种方法的结果

第一次我发现很快就变成。。。一遍又一遍地写,真烦人。所以我想使用另一个版本

第三种方法与许多其他方法类似,如许多字符串方法和IEnumerable扩展方法。我想这有其积极的一面,你可以做一些事情,比如
vara=newadder();var b=a.加上(5)然后有一个是0,一个是5。但同时,一直创建新对象不是有点贵吗?第一个物体什么时候会死?第一个方法何时返回某种类型的?还是


不管怎样,我喜欢返回
this
的那个,我想我会使用它,但我很想知道其他人对这个案例的看法。什么是最佳实践。

考虑一下这个问题:如果你在5年后回到这个代码,这对你有意义吗?如果是这样的话,我想你可以继续


但是,对于这个特定的例子,重载
+
-
操作符似乎可以使事情更清楚,并完成同样的事情。

这种“返回此”样式有时被称为a,是一种常见的做法。

我喜欢“流畅的语法”,并会采用第二种。毕竟,对于那些对流利语法感到不舒服的人来说,你仍然可以把它作为第一个

另一个让加法器这样的接口更易于使用的想法是:

public Adder Add(params int[] i) { /* ... */ }
public Adder Remove(params int[] i) { /* ... */ }

Adder adder = new Adder()
  .Add(1, 2, 3)
  .Remove(3, 4);
我总是尝试制作简短易读的界面,但许多人喜欢编写尽可能复杂的代码

  • 对于您的特定情况,重载算术运算符可能是最好的解决方案

  • 返回
    这个
    (流畅的界面)是创建表达式的常见做法-单元测试和模拟框架经常使用它。Fluent Hibernate是另一个例子

  • 返回新实例也可能是一个不错的选择。它允许您将类设置为不可变的—通常这是一件好事,在多线程的情况下非常方便。但是,如果不变性对您没有用处,请考虑对象创建开销


  • 如果你叫它加法器,我会把这个还给你。然而,加法器类包含答案有点奇怪

    你可以考虑让它像MyNoT之类的东西,并创建一个Ad()方法。< /P> 理想情况下(IMHO),这不会更改实例中存储的数字,而是使用新值创建一个新实例,并返回:

    class MyNumber
    {
        ...
    
        MyNumber Add( int i )
        {
            return new MyNumber( this.Value + i );
        }
    }
    

    我认为对于简单的接口,“fluent”接口非常有用,特别是因为它的实现非常简单。fluent界面的价值在于它消除了许多妨碍理解的无关的绒毛。开发这样的接口可能需要很多时间,特别是当接口开始涉及时。您应该担心接口的使用如何“读取”;在我看来,这种接口最引人注目的用途是它如何传达程序员的意图,而不是它保存的字符数量


    为了回答您的具体问题,我喜欢“返回此”样式。我对fluent界面的典型使用是定义一组选项。也就是说,我创建了一个类的实例,然后在实例上使用fluent方法来定义对象所需的行为。如果我有一个yes/no选项(比如日志记录),我会尝试不使用“setLogging(bool state)”方法,而是使用两种方法“WithLogging”和“WithoutLogging”。这需要做更多的工作,但最终结果的清晰性非常有用。

    链接是一件很好的事情,在某些框架中是核心(例如Linq扩展和jQuery都大量使用它)

    创建新对象还是
    返回此
    取决于初始对象的行为:

    var a = new Adder();
    
    var b = a.Add(4)
             .Remove(1)
             .Add(7)
             .Remove(3);
    
    //now - should a==b ?
    
    jQuery中的链接将更改您的原始对象-它已返回此值。 这是预期的行为-否则基本上会克隆UI元素

    Linq中的链接将使您的原始收藏保持不变。这也是预期的行为-每个链式函数都是一个过滤器或转换,原始集合通常是不可变的


    哪种模式更适合您所做的工作?

    第二种和第三种解决方案的主要区别在于,通过返回一个新实例而不是此实例,您可以“捕获”处于特定状态的对象并从该状态继续

    var a=新加法器() .添加(4)

    var b=a.移除(1)

    变量c=a.Add(7) .移除(3)

    在这种情况下,b和c都将在a中捕获的状态作为起点。 我在阅读有关在中构建测试域对象的模式时遇到了这个习惯用法


    关于您关于实例生命周期的问题:我认为只要调用Remove或Add返回,它们就可以进行垃圾收集

    你是三等舱的,你说的做不了。你可以从数字中加或减,并将其作为一个单独的整数传递到新的加法器(…)中。当然,在这种情况下,最好是直接使用整数。但这正是我能想到的