是否更好地使用多个输出值或返回组合值类型?

Joa*_*nge 14 .net c# performance clarity

例如,沿着以下方向:

public bool Intersect (Ray ray, out float distance, out Vector3 normal)
{

}
Run Code Online (Sandbox Code Playgroud)

VS

public IntersectResult Intersect (Ray ray)
{

}

public class IntersectResult
{
    public bool Intersects {get;set;}
    public float Distance {get;set;}
    public Vector3 Normal {get;set;}
}
Run Code Online (Sandbox Code Playgroud)

这对于清晰度,易用性以及最重要的性能而言都更好.

Eri*_*ert 16

我会使用组合类型,我会告诉你原因:因为值的计算应该返回值,而不是改变一堆变量.一旦你需要多个变量突变,变异就不会扩展.假设你想要上千件事:

IEnumerable<Ray> rays = GetAThousandRays();
var intersections = from ray in rays 
                    where Intersect(ray, out distance, out normal)
                    orderby distance ...
Run Code Online (Sandbox Code Playgroud)

现在,执行查询会反复改变相同的两个变量.您根据正在变异的值进行排序.这是一团糟.不要做出改变事物的查询; 这很令人困惑.

你想要的是:

var intersections = from ray in rays 
                    let intersection = Intersect(ray)
                    where intersection.Intersects
                    orderby intersection.Distance ...
Run Code Online (Sandbox Code Playgroud)

没有突变; 将值序列操作为值而不是变量.

我也倾向于摆脱布尔标志,并使值成为不可变的结构:

// returns null if there is no intersection
Intersection? Intersect(Ray ray) { ... }

struct Intersection 
{
    public double Distance { get; private set; }
    public Vector3 Normal { get; private set; }
    public Intersection(double distance, Vector3 normal) : this()
    {
        this.Normal = normal;
        this.Distance = distance;
    }
} 
Run Code Online (Sandbox Code Playgroud)


Bri*_*new 10

我会使用组合类型.

使用对象,您可以附加行为,并返回任意复杂的对象.您可能希望将来重构您的方法,并更改返回值.通过将它们包装在返回对象中并向该对象添加行为,这种重构可以变得非常透明.

使用元组之类的东西很诱人.然而,重构工作一段时间(我的经验在这里讲,刚刚犯了这个错误之后成为头痛再次)


Chr*_*ham 6

最好返回组合类型.至少你的方法签名更清晰,程序员在调用时工作的工作量更少.EG:您不必声明和初始化变量,这会使调用代码变得混乱.


Tej*_*ejs 5

有些人说这是一个偏好问题,但我认为返回一个复杂的对象更好,不仅是为了清晰,而且是为了维护.

如果您需要添加另一位数据作为输出,除了添加额外响应的代码之外,您还必须更改方法签名; 复杂的输出类型不是这样.此外,模拟(用于单元测试)输出参数更难.它似乎打破了"简单"的理念 - 当你只需要一个输入时,你必须经历设置输出参数的麻烦.OOP语言的优势在于制作类型 - 在我看来,这条路线也是如此.

两者之间的性能差异可以忽略不计.