dotnetnoob
dotnetnoob

Reputation: 11330

Generic method vs non generic method - is there any performance benefit?

I am creating my first website in C#.

I noticed I was getting some duplication of extension methods in intellisense. Onfurther investigation it was these two:

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

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

It seems string can also be IEnumerable<char>.

From a basis of compiling I can remove the string variant, but are there any performance issues or anything else I should be aware of?

UPDATE

Just tested over 1m iterations.

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

vs

public bool IsNullOrEmpty2<T>(IEnumerable<T> @this)
{
    return @this == null || [email protected]();
}

IsNullOrEmpty1 clocked 12 ms on my development machine, IsNullOrEmpty2 (125 - 250ms), so 10 - 20 times slower.

In the real world, I took an extremely high figure of 30m iterations per month, which translates back to 1388 per minute (12 hour day). The result was less than 1ms for both.

So, removing IsNullOrEmpty1 is not the best approach but its not a site killer either.

Upvotes: 4

Views: 685

Answers (2)

driis
driis

Reputation: 164291

It probably depends on the implementation of those methods - the string version could be optimized for performance, while the IEnumerable<T> one needs to be more general. Calling a generic method has no overhead, it is already resolved to the correct generic parameter at compile time.

The string version can be implemented like this, which has very little overhead (it basically needs to make two comparisons):

if (String.IsNullOrEmpty(value))  

The IEnumerable<T> on the other hand probably has to be implemented something like:

if (value == null || !value.Any())

The key here is the Any call which will invoke the GetEnumerator method and return an enumerator. (For simplicity, we will overlook the performance optimizations that the framework might use internally for some types, here). This means that the implementation actually creates a new object, which will later need to be garbage collected - both will require more clock cycles than making the two comparisons mentioned in the string version.

In practice, unless these methods are called very frequently, I doubt there is any significant performance difference.

Btw, the reason why this works, is that string is an IEnumerable<char>.

Upvotes: 3

linquize
linquize

Reputation: 20366

string is a sealed class, so we can call the methods in string class directly without accessing the virtual function pointer. In theory, it is faster than passing an IEnumerable<char>. But in practice, it depends how many times you call the string methods in your method.

Upvotes: 0

Related Questions