Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/130.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# 为什么API应该返回';无效';?_C#_C++_Api - Fatal编程技术网

C# 为什么API应该返回';无效';?

C# 为什么API应该返回';无效';?,c#,c++,api,C#,C++,Api,在编写API或可重用对象时,所有返回“void”的方法调用都不应该只返回“this”(*this在C++中)有什么技术原因吗 例如,使用string类,我们可以执行以下操作: string input= ...; string.Join(input.TrimStart().TrimEnd().Split("|"), "-"); 但我们不能这样做: string.Join(input.TrimStart().TrimEnd().Split("|").Reverse(), "-"); …因为Ar

在编写API或可重用对象时,所有返回“void”的方法调用都不应该只返回“this”(*this在C++中)有什么技术原因吗

例如,使用string类,我们可以执行以下操作:

string input= ...;
string.Join(input.TrimStart().TrimEnd().Split("|"), "-");
但我们不能这样做:

string.Join(input.TrimStart().TrimEnd().Split("|").Reverse(), "-");
…因为Array.Reverse()返回void

还有许多其他示例,其中一个API有大量的void返回操作,因此代码最终看起来像:

api.Method1();
api.Method2();
api.Method3();
…但完全有可能写出:

api.Method1().Method2().Method3()
…如果API设计者允许的话

遵循这条路线有技术原因吗?或者它只是一种样式,用来表示易变性/新对象

(x-ref)


结语

我接受了Luviere的回答,因为我认为这最能代表意图/设计,但似乎有一些流行的API示例偏离了这一点:

C++中的代码> CUT< P>如果你有<代码> Retryse(/Cord>)返回一个“代码>字符串,那么对于API的用户来说,它是否返回一个新的字符串或相同的字符串,在适当的位置上是不明显的。

string my_string = "hello";
string your_string = my_string.reverse(); // is my_string reversed or not?

这就是为什么,例如,在Python中,返回
None
;它将就地排序与返回void state的。

方法区别开来,后者更清楚地表明它们有副作用。返回修改结果的那些应该没有副作用,包括修改原始输入。使方法返回为void意味着它更改其输入或API的其他内部状态

遵循这条路线有技术原因吗


< C++设计指南之一是“不要为你不使用的功能付费”;返回
会有一些(轻微的)性能损失,因为许多人(例如我)不愿意使用此功能。

除了设计原因之外,返回此功能也会有轻微的性能成本(速度和空间)。

许多其他人提到的技术原则(强调函数具有副作用的事实)称为


虽然这一原则有其利弊,例如,(主观上)更清晰的意图与更简洁的API,但最重要的部分是一致性。

我认为一个原因可能是简单性。非常简单,一个API通常应该尽可能小。它应该清楚它的各个方面,以及它的用途

如果我看到一个返回void的函数,我知道返回类型并不重要。不管该函数做什么,它都不会返回任何可供我使用的内容

如果一个函数返回非空的东西,我必须停下来想一想为什么。这个对象可能会返回什么?为什么会返回?我是否可以假设这个总是返回,或者它有时是空的?或者是一个完全不同的对象?等等

在第三方API中,我更希望这种问题永远不会出现


如果函数不需要返回任何内容,它就不应该返回任何内容。

如果您希望从F#调用API,请执行返回
无效
,除非您确信此特定方法调用几乎每次使用时都会与另一个方法调用链接

如果您不想让API在F#中易于使用,可以停止阅读这里的内容

在某些方面,F#比C#更严格——它希望您明确地知道调用方法是为了获取值,还是纯粹为了它的副作用。因此,当该方法同时返回值时,调用方法的副作用会变得笨拙,因为为了避免错误,必须显式忽略返回的值d编译器错误。这使得从F#开始使用“流畅的接口”有点尴尬,F#有自己优越的语法将一系列调用链接在一起

例如,假设我们有一个带有
Log
方法的日志系统,该方法返回
this
,以允许某种方法链接:

let add x y =
    Logger.Log(String.Format("Adding {0} and {1}", x, y)) // #1
    x + y                                                 // #2
在F#中,因为第#1行是一个返回值的方法调用,我们没有对该值执行任何操作,
add
函数被视为获取两个值并返回该记录器实例。然而,第#2行不仅返回值,它还出现在F#认为是“返回”的值之后语句,有效地生成两个“return”语句。这将导致编译器错误,我们需要显式忽略
Log
方法的返回值以避免此错误,以便我们的
add
方法只有一个return语句

let add x y =
    Logger.Log(String.Format("Adding {0} and {1}", x, y)) |> ignore
    x + y
正如您可能猜到的,在到处散布大量的
ignore
语句时,进行大量主要与副作用有关的“Fluent-API”调用变得有些令人沮丧


当然,你可以两全其美,通过提供一个流畅的API和一个F模块来使用你的代码来取悦C#和F#开发者。但是如果你不打算这样做,并且你打算让你的API供公众使用,请在从每个方法返回
这个
之前三思

您描述的模式也称为方法链接()。方法链接,或fluent接口(尽管我相信纯粹主义者声称后者需要更多的东西!).Ahhh-它有一个名字!它看起来很可读,在JQuerySee和@bbum对客观经验的回答中很流行-C@Mark我不知道“FLUENT”的名字,所以我最初的搜索并没有引起这个问题。在C++中,还有其他的方式来表达这个const成员函数,例如……@ jBrWiknon问题的s?COPE比C++更广,它也有一个C标签。我所说的是一个语言不可知API实践。Stuto.Pop.()()是一个API的例子,它返回一个值,但也会改变对象。这是坏的设计(应该是:使用PEEK)。