创建操作类型为'object'的扩展方法是否会影响性能?
本文关键字:是否 性能 方法 影响 object 类型 操作 创建 扩展 | 更新日期: 2023-09-27 18:10:22
我有一组扩展方法,我经常将它们用于各种UI任务。我通常将它们定义为运行类型object
,即使在它们内部我通常将它们转换为字符串类型。
public static string FormatSomething(this object o)
{
if( o != null )
{
string s = o.ToString();
/// do the work and return something.
}
// return something else or empty string.
}
我使用类型object
而不是string
的主要原因是,当我可以做<%#Eval("Phone").FormatSomething()%>
时,在UI中不必做<%#Eval("Phone").ToString().FormatSomething()%>
。
那么,从性能的角度来看,在object
上创建所有的扩展方法是好的,还是我应该根据扩展方法正在做的事情将它们转换为string
(或相关)类型?
创建操作对象类型的扩展方法是否会影响性能?
是的。如果传入一个值类型,则该值类型将被框起来。这会造成分配盒子和执行复制的性能损失,当然之后还必须对盒子进行垃圾收集。
代替
public static string FormatSomething(this object o)
{
return (o != null) ? o.ToString() : "";
}
我会写
public static string FormatSomething<T>(this T o)
{
return (o != null) ? o.ToString() : "";
}
具有相同的效果,但避免了拳击惩罚。或者更确切地说,它用每次调用拳击惩罚换取第一次调用跳跃成本惩罚。
从性能的角度来看,在对象上创建所有的扩展方法是好的吗?
我们不能回答这个问题。试一试!衡量绩效,将其与期望的绩效进行比较,看看是否达到了目标。如果你做到了,那很好。如果不是,使用分析器,找到最慢的东西,并修复它。
但这两个问题都不是你应该问的问题。应该问的问题是:
是一个良好的编程实践,创建一个扩展方法,扩展一切?
。这几乎从来不是个好主意。在大多数情况下,当人们想要这样做时,他们是在滥用扩展方法机制。通常有一些更具体的类型可以扩展。如果你经常这样做,那么你最终会在每种类型上都有很多扩展方法,编码会变得混乱和容易出错。
例如,假设您希望有一个扩展方法来回答"这个序列是否包含这个值?"你可以这样写:public static bool IsContainedIn<T>(this T item, IEnumerable<T> sequence)
,然后写
if (myInt.IsContainedIn(myIntSequence))
但最好这样说:
public static bool Contains<T>(this IEnumerable<T> sequence, T item)
,然后写
if (myIntSequence.Contains(myInt))
如果你这样做的第一种方式,然后你在IDE中键入,每次你键入"。",你得到提示与IsContainedIn
作为一个选项,因为也许你要写的代码,以确定这个对象是否在一个集合。但99%的情况下,你不会这么做。这样做会增加工具的噪音,并使您更难以找到真正想要的东西。
除了可能对IDE产生一些影响外,我非常怀疑会有任何性能影响。一旦编译,我不期望它会有什么不同。
与在调用FormatSomething之前调用ToString相比,不是真的(您是null)检查可能会花费更多毫秒,但它们也使代码更健壮。
即使你调用方法的对象的编译时类型是字符串,它仍然会产生明显的差异。
在出现性能问题之前不要担心性能。在此之前,要担心可维护性,包括可读性。如果你有一个性能问题,然后使用分析器找到它在哪里。
在运行时与扩展方法相关的开销是什么?(. net)回答了你的问题。扩展方法只是静态方法,因此它们不属于Object类型。智能感知只是让它看起来是这样。