直接等同会是这个样子:
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)));
}
在这里,你可以有多种变换名称相同,但第二个和第三个缺点上面提到的仍然适用。
您有一本字典作为本贴子的标签。所以字典看起来像这样:var matrices = transforms.GroupBy(x => x.a,y => y.b) .ToDictionary(x => x.Key,y => y.ToList()); – jdweng
@jdweng谢谢。但是如果我还有一个字典作为输入参数“变换”呢?例如:Dictionary,其中decimal []是矩阵系数的数组? –
单个数组如何映射到(a,b)? – jdweng