问题在标题中,为什么:
return double.IsNaN(0.6d) && double.IsNaN(x);
Run Code Online (Sandbox Code Playgroud)
代替
return (0.6d).IsNaN && x.IsNaN;
Run Code Online (Sandbox Code Playgroud)
我问,因为在实现具有与NaN相同含义的特殊值的自定义结构时,我倾向于选择第二种结构.
此外,属性的性能通常更好,因为它避免复制堆栈上的结构以调用IsNaN静态方法(并且因为我的属性不是虚拟的,所以没有自动装箱的风险).当然,对于内置类型来说这不是一个真正的问题,因为JIT可以很容易地优化它.
我现在最好的猜测是,因为你不能在double类中同时拥有属性和静态方法,所以他们更喜欢java启发的语法.(事实上你可以同时定义一个get_IsNaN属性getter,另一个定义一个IsNaN静态方法,但它会混淆任何支持属性语法的.Net语言)
Pop*_*lin 14
静态方法是线程安全的,基元上的方法通常需要是线程安全的,以支持平台中的线程(意味着至少安全地从内部竞争条件开始),实例方法采用托管指向结构的指针,这意味着结构/原语可能是另一方面,静态方法采用结构/原语的副本,因此在线程竞争条件下是安全的.
如果结构是线程安全的,那么只有在进行原子操作时才应该将方法设为实例方法,否则应该选择静态方法.
(作为另一种选择,可以使用使用锁定的实例方法,但它们比复制更昂贵)
编辑:@VirtualBlackFox我已经准备好并举例说明结构上的实例方法即使在不可变结构上也不是线程安全的:
using System;
using System.Threading;
namespace CA64213434234
{
class Program
{
static void Main(string[] args)
{
ManualResetEvent ev = new ManualResetEvent(false);
Foo bar = new Foo(0);
Action a = () => bar.Display(ev);
IAsyncResult ar = a.BeginInvoke(null, null);
ev.WaitOne();
bar = new Foo(5);
ar.AsyncWaitHandle.WaitOne();
}
}
public struct Foo
{
private readonly int val;
public Foo(int value)
{
val = value;
}
public void Display(ManualResetEvent ev)
{
Console.WriteLine(val);
ev.Set();
Thread.Sleep(2000);
Console.WriteLine(val);
}
}
}
Run Code Online (Sandbox Code Playgroud)
显示Instance方法打印:0 5
即使结构是不可变的.对于线程安全方法,使用静态方法.
有趣的问题; 不知道答案 - 但如果它真的让你烦恼,你可以声明一个扩展方法,但它仍然会使用堆栈等.
static bool IsNaN(this double value)
{
return double.IsNaN(value);
}
static void Main()
{
double x = 123.4;
bool isNan = x.IsNaN();
}
Run Code Online (Sandbox Code Playgroud)
如果C#具有扩展属性会更好(对于语法),但是上面是关于你现在可以得到的最接近的,但是它应该"内联"得很好.
更新; 想一想,静态和实例之间还有另一个区别; C#总是用" callvirt
"而不是" call
" 来调用实例方法,即使其类型被密封为非可空的.那么将它静态化可能会带来性能上的好处吗?幸运的是,扩展方法仍然算作静态,因此您可以保留此行为.