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返回,它们就可以进行垃圾收集 你是三等舱的,你说的做不了。你可以从数字中加或减,并将其作为一个单独的整数传递到新的加法器(…)中。当然,在这种情况下,最好是直接使用整数。但这正是我能想到的