Beware of SPList.Items.Add()
What could possibly be wrong with this statement?
SPListItem myItem = myList.Items.Add();
This is what’s wrong with it – this is the innards of SPList.Items:
public virtual SPListItemCollection Items { get { SPQuery query = new SPQuery(); query.ViewAttributes = "Scope=\"Recursive\""; return this.GetItems(query); } }
That’s right, the entire collection, every single item, item is returned and then Add() is applied to the final SPListItemCollection instance, which results in an internal SPListItem constructor call:
public SPListItem Add(string folderUrl, SPFileSystemObjectType underlyingObjectType, string leafName) { return new SPListItem(this, folderUrl, underlyingObjectType, leafName); }
internal SPListItem(SPListItemCollection items, string folderUrl, SPFileSystemObjectType underlyingObjectType, string leafName) { this.m_ItemGuid = Guid.Empty; this.m_fsoType = SPFileSystemObjectType.Invalid; if (underlyingObjectType != SPFileSystemObjectType.File) { while (underlyingObjectType != SPFileSystemObjectType.Folder) { throw new ArgumentOutOfRangeException("underlyingObjectType"); } } this.m_Items = items; this.m_uiItemsUpdateVersion = items.UpdateVersion; this.m_iIndex = -1; this.m_strNewFolderName = folderUrl; this.m_fsoType = underlyingObjectType; this.m_strNewBaseName = leafName; this.m_bNewItem = true; }
So what should be used instead? Rob Garrett suggests creating a new empty SPListItemCollection and adding to it, below is his method converted to an Extension method (and renamed to be more easily found):
public static SPListItem AddItemOptimized(this SPList list) { const string EmptyQuery = "0"; SPQuery q = new SPQuery {Query = EmptyQuery}; return list.GetItems(q).Add(); }
(and no, neither Rob nor I have instrumented the difference between these two methods, but Reflector doesn’t lie…)