直接等效项如下所示:
public Transform TransformsMultiply(IEnumerable<Transform> transforms)
{
var matrices = transforms.Select(transform =>
transform.Name == "matrix"
? transform.Data
: transformToMatrix(transform));
return new Transform
{
Name = "matrix",
Data = matrices.Aggregate((a, b) =>
multiplyTransformMatrices(a, b));
};
}
当然,您需要定义Transform 类以及transformToMatrix 和multiplyTransformMatrices 方法;
虽然通过Name 属性区分转换类型不是惯用的 C#。如果您为每种转换类型创建一个抽象基 Transform 类型和子类会更好:
public abstract class Transform { /* ... */ }
public class Matrix : Transform
{
public int[,] Data { get; set; }
}
public class OtherTypeOfTransform : Transform
{
/* ... */
}
方法的第一部分如下所示:
var matrices = transforms.Select(transform =>
transform is Matrix
? transform.Data
: transformToMatrix(transform));
但这不是非常面向对象的,因为transformToMatrix 需要知道如何将每种类型的变换转换为矩阵。您应该考虑在基类中添加一个抽象的ToMatrix 方法并在子类中实现它,从而将自身转换为矩阵的责任委托给每个子类。
public abstract class Transform
{
public abstract Matrix ToMatrix();
}
public class Matrix : Transform
{
public int[,] Data { get; set; }
public Matrix ToMatrix() { return this; }
}
public class OtherTypeOfTransform : Transform
{
public Matrix ToMatrix()
{
// Type-specific implementation
}
}
之后,实现将如下所示:
public Matrix TransformsMultiply(IEnumerable<Transform> transforms)
{
return new Matrix
{
Data = transforms
.Select(transform => transform.ToMatrix())
.Aggregate((a, b) => multiplyTransformMatrices(a, b));
};
}
将乘法移到 Matrix 类中会更好:
public Matrix TransformsMultiply(IEnumerable<Transform> transforms)
{
return new Matrix
{
Data = transforms
.Select(transform => transform.ToMatrix())
.Aggregate((a, b) => a.MultiplyBy(b));
};
}
这就是我将 JavaScript 转换为惯用的面向对象的 C# 代码的方式。
编辑
您问我如何使用Dictionary<string, decimal[]> 而不是IEnumerable<Transform> 来实现它,所以这里是:
public KeyValuePair<string, decimal[]> TransformsMultiply(
Dictionary<string, decimal[]> transforms)
{
var matrices = transforms.Select(kvp =>
kvp.Key == "matrix"
? kvp.Value
: transformToMatrix(kvg.Value));
return new KeyValuePair<string, int>(
"matrix",
matrices.Aggregate((a, b) => multiplyTransformMatrices(a, b));
}
Dictionary<TKey, TValue> 是 IEnumerable<KeyValuePair<TKey, TValue>>,因此在此解决方案中,转换由 KeyValuePair<string, decimal[]> 表示。
请注意,字典键是唯一的,因此您只能使用键 "matrix" 进行一次转换。我不确定这是否是你想要的。
这种方案的缺点是:
- 由于字典键的唯一性,每种类型的转换只能有一个实例
- 它掩盖了代码的意图并使其更难阅读(在我看来
- 逻辑上属于变换本身的行为(如何将其转换为矩阵以及如何将一个矩阵与另一个矩阵相乘)现在没有被封装,它在
transformToMatrix 和multiplyTransformMatrices 方法中。李>
如果你真的想要一个通用容器来代替命名类,你可以使用Tuple<T, U>:
public Tuple<string, decimal[]> TransformsMultiply(
IEnumerable<Tuple<string, decimal[]>> transforms)
{
var matrices = transforms.Select(t =>
t.Item1 == "matrix" ? t.Item2 : transformToMatrix(t.Item2));
return new Tuple<string, decimal[]>(
"matrix",
matrices.Aggregate((a, b) => multiplyTransformMatrices(a, b)));
}
在这里你可以有多个同名的变换,但上面提到的第二个和第三个缺点仍然适用。