通用方法与非通用方法 - 是否有性能上的优势?

4

我正在使用C#创建我的第一个网站。

我注意到在智能感知中出现了一些扩展方法的重复。经过进一步调查,发现这两个扩展方法是:

public static void ThrowNullOrEmpty<T>(this IEnumerable<T> obj, string param)
{
}

public static void ThrowNullOrEmpty(this string obj, string param)
{
}

看起来字符串也可以是 IEnumerable<char>

从编译的基础上,我可以移除字符串变量,但我是否需要注意任何性能问题或其他问题?

更新:

刚刚进行了100万次迭代测试。

public bool IsNullOrEmpty1(string @this)
{
    return String.IsNullOrEmpty(@this);
}

vs

public bool IsNullOrEmpty2<T>(IEnumerable<T> @this)
{
    return @this == null || !@this.Any();
}

我的开发机上,IsNullOrEmpty1 的时间为12毫秒,而 IsNullOrEmpty2 为125-250毫秒,因此慢了10-20倍。

在真实世界中,我每月执行了30m次迭代,这相当于每分钟1388个(12小时工作日)。两者的结果都不到1毫秒。

因此,删除 IsNullOrEmpty1 不是最佳方法,但也不会对网站造成致命影响。


据我所知,这是一种语法糖,编译器会为您的泛型生成一个新类型。在运行时,您不应该注意到任何区别。 - BenCr
3
测量非常简单,但如果没有问题,为什么要费心呢? - spender
2个回答

3

这可能取决于这些方法的实现 - 字符串版本可以优化性能,而 IEnumerable<T> 版本需要更通用。调用通用方法没有额外开销,在编译时已经解析为正确的通用参数。

字符串版本可以像这样实现,它几乎没有额外开销(基本上只需要进行两次比较):

if (String.IsNullOrEmpty(value))  

另一方面,IEnumerable<T> 可能需要实现类似以下的内容:
if (value == null || !value.Any())

这里的关键在于调用Any方法,它会调用GetEnumerator方法并返回一个枚举器。(为简单起见,我们将忽略框架在某些类型上可能使用的内部性能优化)。这意味着实现实际上创建了一个新对象,稍后需要进行垃圾回收 - 这两个过程都需要比执行string版本中提到的两个比较需要更多的时钟周期。
实际上,除非这些方法被频繁调用,否则我怀疑没有任何显著的性能差异。
顺便说一句,这个方法可以工作的原因是string是一个IEnumerable<char>

0

string 是一个密封类,因此我们可以直接调用 string 类中的方法,而无需访问虚函数指针。 理论上,这比传递一个 IEnumerable<char> 更快。但在实践中,这取决于您在方法中调用 string 方法的次数。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接