我看到一些本地WPF控件的代码类似于以下内容:
static MyControl {
Type typeFromHandle = typeof(MyControl);
// Which is used in various places
SomeProperty.OverrideMetadata(typeFromHandle, ...);
CommandManager.RegisterClassInputBinding(typeFromHandle, ...);
EventManager.RegisterClassHandler(typeFromHandle, ...);
}
以下代码似乎具有相同的性能:
static MyControl {
SomeProperty.OverrideMetadata(typeof(MyControl), ...);
CommandManager.RegisterClassInputBinding(typeof(MyControl), ...);
EventManager.RegisterClassHandler(typeof(MyControl), ...);
}
当JIT编译代码或在运行时,这种方法在性能方面是否有任何好处?
typeof
的缓存将使您的性能得到小幅提升。下页给出了基准:
Typeof expression used: 2.55 ns
Type object cached: 0.64 ns
如果你经常typeof
,或者关心纳秒,那么这可能对你很重要!
简短回答
是的,它更优化,但不,你不应该使用它,因为在几乎每个的情况下,它都是过早的优化。如果有什么不同的话,如果您多次使用typeof(MyControl)
,请将其用作保持代码可读性的一种方法。
长答案
如果您查看C#中typeof(MyControl)
语句生成的IL,您会看到以下内容:
IL_0001: ldtoken [mscorlib]MyControl
IL_0006: call class [mscorlib]System.Type
[mscorlib]System.Type::GetTypeFromHandle(
valuetype [mscorlib]System.RuntimeTypeHandle)
这些说明的作用如下:
- 将
RuntimeTypeHandle
(ldtoken
IL指令)加载到堆栈上(CLR指令,而不是C#/.NET概念的CLR指令) - 从
RuntimeTypeHandle
中获取Type
(对Type.GetTypeFromHandle
的调用)
将其与将Type变量类型与存储在实例中的类型进行比较:
IL_0014: ldloc.2
注意,位置(1、2等)将根据其他变量而变化,但最终,它是引用类型的负载。
比较两者,对已分配变量的调用总是会更快。第一个必须加载类型句柄,然后必须调用一个方法,以便将句柄解析为Type
;第二种方法只是引用一个局部变量。
然而,像大多数其他帖子一样,这肯定会被认为是一种过早优化的情况,所以如果你认为你的代码表现不佳,我建议你不要这样做。
可以提出这样的论点:从代码重用的角度来看,它更好,就好像你必须更改类型,你会在更少的地方更改它;你不会被typeof
声明淹没。
最后,关于WPF,考虑到性能要求(就像任何UI系统一样),这是他们必须做的事情;WPF有大量的托管对象,与Windows窗体相比要多得多,并且必须考虑这些对象的性能,以便能够尽快呈现UI。
结果,你会看到这样的东西:
private static readonly object TrueObject = true;
private static readonly object FalseObject = false;
// Later on.
DoSomething(condition ? TrueObject : FalseObject);
// Where
void DoSomething(object value)
{
// Compare to true/false objects.
if (value == TrueObject)
{
// True case.
}
else if (value == FalseObject)
{
// False case.
}
else
{
// Invalid.
throw new InvalidOperationException();
}
}
原因很简单;大多数WPF公开的属性/方法将对象作为参数,而不是强类型值。当涉及值类型时,可能会涉及大量的装箱/取消装箱。
为了绕过这一点,他们有一个单个实例,当他们确切地知道哪些值将被装箱/取消装箱时,该实例被装箱/解除装箱;有了bool
,这很容易,只有true
和false
。
同样,我不一定推荐这种方法用于几乎任何系统,但对于某些系统,它是有意义的。
在您的情况下,我会简单地将类型分配给一个变量,只是为了可读性,而不是为了性能。如果您有性能问题,请首先查看整个过程,通过测量进行隔离,然后从那里开始。
您不太可能在typeof的性能很重要的地方编写代码,因此您应该选择最清晰和可维护的代码样式。