Я бы использовал комбинированный тип, и я скажу вам, почему: потому что вычисление значения должно возвращать значение , а не изменять вид переменных .Мутирование группы переменных не масштабируется, если вам нужно мутировать более чем одной из них.Предположим, вам нужна тысяча таких вещей:
IEnumerable<Ray> rays = GetAThousandRays();
var intersections = from ray in rays
where Intersect(ray, out distance, out normal)
orderby distance ...
Выполнение запроса теперь , неоднократно мутировав те же две переменные .Вы делаете заказ на основе значения, которое мутирует.Это беспорядок.Не делайте запросов, которые изменяют вещи;это очень сбивает с толку.
То, что вы хотите:
var intersections = from ray in rays
let intersection = Intersect(ray)
where intersection.Intersects
orderby intersection.Distance ...
Нет мутации;манипулировать последовательностью значений как значениями , а не как переменными .
Я также был бы склонен, возможно, избавиться от этого логического флага и сделать значение неизменной структурой:
// 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;
}
}