可以在C#中缩短数学参考吗?

在VB.NET中,我可以通过导入System.Math并直接引用其方法来使我的数学代码更加清晰:

Imports System.Math [...] Return New Vector3(Sin(az) * Cos(el), Cos(az) * Cos(el), Sin(el)) 

但是我不认为C#可以使用类来隐式访问它们的方法,所以我必须做类似的事情:

 using System; [...] return new Vector3(Math.Sin(az) * Math.Cos(el), Math.Cos(az) * Math.Cos(el), Math.Sin(el)); 

但那很难看; 它需要自己的滚动条! 有没有办法在C#中编写一些看起来像我的VB.NET代码的东西? 我可以为Sin和Cos编写局部包装器方法,但这不会降低性能(因为函数调用的开销)? 而且,这需要为我正在使用的每个类中使用的每个Math函数编写包装函数; 这也不是那么令人满意。

您可以使用using指令为System.Math提供别名:

 using M = System.Math; return new Vector3(M.Sin(az) * M.Cos(el), M.Cos(az) * M.Cos(el), M.Sin(el)); 

这是我得到的最好的。

我可以为Sin和Cos编写局部包装器方法,但这不会降低性能(因为函数调用的开销)?

你可以,并且在那时你可以使用generics和其他细节使它更方便,但你仍然会引用这样的库,除非所有的数学都发生在这个代码作为方法出现的同一个类中。

“从开销中获得性能”这一问题的答案是“额外的堆栈帧,这对于标准应用来说非常明显。” 如果你处于紧张的循环中,那么是的,这将是一个问题。

从C#6.0开始,您可以通过添加using static声明来缩短数学引用:

 using static System.Math; 

这允许您使用Math类型的静态成员,而不使用类型名称限定它:

 public void Foo() { var bar = Sin(8); } 

由于目前根本无法在全球范围内应用使用声明,因此无法“全局”执行此操作。

对于那些不使用C#6的人

但是不会降低性能(因为函数调用的开销)?

我不担心。 编写代码以便首先读取 。 我们可以用几种不同的方式编写方法。 第一个,就是添加空格:

 return new Vector3( Math.Sin(az) * Math.Cos(el), Math.Cos(az) * Math.Cos(el), Math.Sin(el) ); 

您也可以将它放在辅助方法中。

jcolebrand的答案也很好,但它需要添加一个using m = System.Math; 到处。

但那很难看; 它需要自己的滚动条!

是的,在Stack Overflow上,宽度很短。 你必须把它放在多行上:

 return new Vector3(Math.Sin(az) * Math.Cos(el), Math.Cos(az) * Math.Cos(el), Math.Sin(el)); 

就个人而言,我认为无论如何都更具可读性,因为现在三个不同的值更清楚地区分了。 空白行是一个比逗号,IMO更清晰的分隔符。 如果你有几个足够相似的参数可以让它们一起丢失,那么为了清晰起见,请使用多行。

是的,如果你能写出Sin(az)等,它会在某种程度上变得很好 – 但C#中没有任何内容可以让你这样做,所以我会坚持重新格式化代码以便于阅读。

你可以加

 using M = System.Math; 

然后就做

 return new Vector3(M.Sin(az) * M.Cos(el), M.Cos(az) * M.Cos(el), M.Sin(el)); 

但是……我没有看到真正的价值

事实上,我认为应该存储每个变量,并用更好的名称来表示它们是什么。 看着这个,我看不出正在做什么。

 var sinAz = Math.Sin(az); //Could these be named better? Perhaps with words in the correct domain var cosAz = Math.Cos(az); var sinEl = Math.Sin(el); var cosEl = Math.Cos(el); return new Vector3(sinAz * cosEl, cosAz * cosEl, sinEl); 

或者更好的是,Vector3实际使用的三个参数是什么?

 var parm1 = Math.Sin(Az) * Math.Cos(El); //What should parm1, parm2, parm3 be called? var parm2 = Math.Cos(Az) * Math.Cos(El); var parm3 = Math.Sin(Az); return new Vector3(parm1, parm2, parm3); 

这将极大地提高可读性,因为下一个人将更好地理解公式是什么。

您可以创建一个将调用包装为扩展方法的类:

 public static class MathExtensions { public static double Sin(this double value) { return Math.Sin(value); } public static double Cos(this double value) { return Math.Cos(value); } } return new Vector3(az.Sin() * el.Cos(), az.Cos() * el.Cos(), el.Sin()); 

编译器应该内联这些调用,以便性能不会真正有所不同。

您也可以使用扩展方法,但结果看起来会更不自然(可能会有额外的函数调用,也可能会被内联):

 static double Sin(this double value) { return Math.Sin(value);} 

并使用:

 return new Vector3(az.Sin() * el.Cos(),.... 

您无法在C#中为方法定义别名,只能在类中定义。