I work on applications developed in C#/.NET with Visual Studio. Very often ReSharper, in the prototypes of my methods, advises me to replace the type of my input parameters with more generic ones. For instance, List<> with IEnumerable<> if I only use the list with a foreach in the body of my method. I can understand why it looks smarter to write that but I'm quite concerned with the performance. I fear that the performance of my apps will decrease if I listen to ReSharper...
Can someone explain to me precisely (more or less) what's happening behind the scenes (i.e. in the CLR) when I write:
public void myMethod(IEnumerable<string> list)
{
foreach (string s in list)
{
Console.WriteLine(s);
}
}
static void Main()
{
List<string> list = new List<string>(new string[] {"a", "b", "c"});
myMethod(list);
}
and what is the difference with:
public void myMethod(List<string> list)
{
foreach (string s in list)
{
Console.WriteLine(s);
}
}
static void Main()
{
List<string> list = new List<string>(new string[] {"a", "b", "c"});
myMethod(list);
}
In the first version (IEnumerable) it is more generic and actually you say the method accepts any argument that implements this interface.
Second version yo restrict the method to accept sepcific class type and this is not recommended at all. And the performance is mostly the same.
The definition for
List<T>
is:So
List<T>
is derived fromIList
,ICollection
,IList<T>,
andICollection<T>,
in addition toIEnumerable
andIEnumerable<T>.
The
IEnumerable
interface exposes theGetEnumerator
method which returns anIEnumerator
, aMoveNext
method, and aCurrent
property. These mechanisms are what theList<T>
class uses to iterate through the list with foreach and next.It follows that, if
IList, ICollection, IList<T>, and ICollection<T>
are not required to do the job, then it's sensible to useIEnumerable
orIEnumerable<T>
instead, thereby eliminating the additional plumbing.There is no performance penalty for a static-upcast. It's a logical construct in program text.
As other people have said, premature optimization is the root of all evil. Write your code, run it through a hotspot analysis before you worry about performance tuning things.
In general, the increased flexibility will be worth what minor performance difference it would incur.
An interface simply defines the presence and signature of public methods and properties implemented by the class. Since the interface does not "stand on its own", there should be no performance difference for the method itself, and any "casting" penalty - if any - should be almost too small to measure.
You'd have to look at the generated code to be certain, but in this case, I doubt there's much difference. The foreach statement always operates on an IEnumerable or
IEnumerable<T>
. Even if you specifyList<T>
, it will still have to get theIEnumerable<T>
in order to iterate.