7

在 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 编写本地包装器方法,但这不会降低性能(因为函数调用的开销)?而且,这将需要为我在使用它们的每个类中使用的每个数学函数编写包装函数;这也不是那么理想。

4

7 回答 7

12

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

using M = System.Math;

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

这是我得到的最好的。

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

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

“来自开销的性能”的问题是用“对于标准应用程序来说如此简单的东西的额外堆栈帧”来回答的。如果您处于紧密循环中,那么是的,那将是一个问题。

于 2012-06-19T19:07:59.597 回答
9

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

using static System.Math;

这允许您使用类型的静态成员,而Math无需使用类型名称对其进行限定:

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

没有办法“全局”执行此操作,因为目前根本无法全局应用 using 声明。

对于那些不使用 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;任何地方添加一个。

于 2012-06-19T19:08:19.850 回答
7

你可以加

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);

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

于 2012-06-19T19:09:31.247 回答
7

但这很丑;它需要自己的滚动条!

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

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

我个人认为无论如何这更具可读性,因为现在这三个不同的值更加清晰地区分了。空行是比逗号更清晰的分隔符,IMO。当你有几个足够相似的论点可能会一起丢失时,为了清楚起见,使用多行。

是的,如果您可以只编写等,在某些方面Sin(az)会很好- 但 C# 中没有任何东西可以让您这样做,所以我会坚持重新格式化代码以提高可读性。

于 2012-06-19T19:11:16.073 回答
5

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

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());

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

于 2012-06-19T19:12:39.177 回答
1

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

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

并使用:

return new Vector3(az.Sin() * el.Cos(),....
于 2012-06-19T19:13:54.523 回答
0

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

于 2012-06-19T19:09:39.577 回答