0

我有这样一个方法:

internal PointGeospatial ConvertToSpherical(double x, double y, double z)

我想知道,确实存在这样一种可能性,可以在 C# 中以某种功能样式处理方法中的所有参数,例如(伪代码):

ConvertToSpherical(double x, double y, double z) ::(x) -> arg->Rad2Deg(x)

这是一个伪代码,但我认为你得到了我想要的东西。当然有制作子方法的方法,比如我会PrepareCoordinates(x, y, z)在哪里foreach准备 3 个变量并发送到ConvertToSpherical(),但这太必要了。

我想要一些很酷的 lamda 风格(函数式语言风格)。我的问题可以在 C# 中使用吗?

4

2 回答 2

0

我对您的问题的理解是,您希望使用Rad2Deg签名和返回类型类似于Func<double, double>.

我没有看到任何特别好的方法。最好的是竖琴:

internal PointGeospatial ConvertToSpherical(double x, double y, double z)
{
  var changedArgs = new[] { x, y, z, }.Select(Rad2Deg).ToArray();

  // rest of method
}

但它不会更改原始变量,因此您仍然可以使用xy并且z稍后会偶然使用。

如果您将方法的签名更改为采用数组(使用params,因此您仍然可以使用相同的调用语法调用它),您可以这样做:

internal PointGeospatial ConvertToSpherical(params double[] x)
{
  for (int i = 0; i < x.Length; ++i)
    x[i] = Rad2Deg(x[i]);

  // rest of method
}

我也可以用箭头做最后一个案例,但它有点难看。你需要这个:

namespace N
{
  delegate void ActionWithRef<T>(ref T obj);

  static class MyExtensions
  {
    public static void ForEachWithRef<T>(this T[] array, ActionWithRef<T> action)
    {
      for (int i = 0; i < array.Length; ++i)
        action(ref array[i]);
    }
  }
}

然后你可以这样做:

// ugly?
// included in this post because it looks a bit like the pseudocode of your question

internal PointGeospatial ConvertToSpherical(params double[] x)
{
  x.ForEachWithRef((ref double t) => t = Rad2Deg(t));

  // rest of method
}

也许有点不那么难看:

namespace N
{
  static class MyExtensions
  {
    public static void MutateAll<T>(this T[] array, Func<T, T> selector)
    {
      for (int i = 0; i < array.Length; ++i)
        array[i] = selector(array[i]);
    }
  }
}

并用于:

internal PointGeospatial ConvertToSpherical(params double[] x)
{
  x.MutateAll(Rad2Deg);

  // rest of method
}

当您只有三个参数时,我不会说我实际上推荐任何这些“解决方案”,但它显示了您可以在 C# 中做什么(和不能做什么)。

在我使用的所有情况下params,如果 的调用者ConvertToSpherical选择以未扩展的形式调用该方法,并且如果他保留了对double[]他传递的实例的引用,那么他会发现当方法返回时他的数组的内容发生了变化。

同样在params示例中,当然不会在编译时检查传递了多少参数(是否为三个)。

这是重复的、非功能性的解决方案:

internal PointGeospatial ConvertToSpherical(double x, double y, double z)
{
  x = Rad2Deg(x);
  y = Rad2Deg(y);
  z = Rad2Deg(z);

  // rest of method
}

;-)

于 2013-10-11T09:40:37.300 回答
0

很抱歉匆忙阅读 Q。这是一个想法,IEnumerables用作向量:

Func<IEnumerable<double>, IEnumerable<double>> convertToSpherical = a => a.Select(Rad2Deg);

var list = new[] {0, Math.PI, Math.PI*2};

var newList = convertToSpherical(list);

foreach (var i in newList)
{
    Console.WriteLine(i);
}

在哪里:

private static double Rad2Deg(double radians)
{
    return radians*180/Math.PI;
}

我发现拥有x, y,z变量是一件痛苦的事,而且无论如何都容易出现复制粘贴错误,所以总是推荐arrays/IEnumerable向量。

于 2013-10-11T09:19:18.313 回答