Though I haven’t actually used the term before, I’ve discussed a number of higher-order functions in the past. Simply put, a higher-order function either accepts a function as a parameter, returns a function, or both. The terminology might be foreign, but the technique is used all over the place:
- Callbacks
- Most LINQ operators
- SPSecurity.RunWithElevatedPrivileges
- Elegant SPSite Elevation
- Thinking Functional: Using
- Anywhere you see
Action<...>orFunc<...>
Another use of higher-order functions is to ensure the existence of a SharePoint resource. For example, I often need to fetch a SharePoint list and create it if doesn’t exist. A standard implementation might look something like this:
public static SPList GetOrCreateList(this SPWeb web, string listName,
string description, SPListTemplate template)
{
SPListCollection webLists = web.Lists;
SPList list = webLists.Cast<SPList>()
.FirstOrDefault(l => l.Title == listName);
if (list == null)
{
Guid newListID = webLists.Add(listName, description, template);
list = webLists[newListID];
}
return list;
}
While there’s nothing wrong with this implementation, per se, it’s not exceedingly flexible. What if we want to use a different overload of SPListCollection.Add? What if we need to elevate privileges to create the list? We could certainly create a dozen variations based on this pattern, but that’s a bunch of duplicate code that we would much rather avoid. Instead, we can use a single higher-order function:
public static SPList GetOrCreateList(this SPWeb web, string listName,
Func<SPWeb, string, SPList> listBuilder)
{
SPList list = web.Lists.Cast<SPList>()
.FirstOrDefault(l => l.Title == listName);
if(list == null && listBuilder != null)
list = listBuilder(web, listName);
return list;
}
And then specify exactly how the list should be created. We could redefine our original method like this:
public static SPList GetOrCreateList(this SPWeb web, string listName,
string description, SPListTemplate template)
{
return GetOrCreateList(web, listName, (builderWeb, builderName) =>
{
var builderLists = builderWeb.Lists;
Guid newListID = builderLists.Add(builderName, description, template);
return builderLists[newListID];
});
}
Or we can just as easily specify a builder that uses elevated privileges and a different Add overload:
public static SPList GetOrCreateTasksList(this SPWeb web)
{
return GetOrCreateList(web, "Tasks", (builderWeb, builderName) =>
{
Guid newListId = web.SelectAsSystem(sysWeb =>
sysWeb.Lists.Add(builderName, null, SPListTemplateType.Tasks));
return builderWeb.Lists[newListId];
});
}
Or my preference is to define a (testable) builder method and just use the higher-order function without a wrapper:
private static SPList CreateGenericList(SPWeb web, string name)
{
var id = web.Lists.Add(name, null, SPListTemplateType.GenericList);
return web.Lists[id];
}
void DoSomething(SPWeb web)
{
SPList list = web.GetOrCreateList("Some List", CreateGenericList);
if (list == null)
throw new SPException("Some List does not exist and could not be created.");
// Do something
}
GetOrCreateGroup
Another use for this pattern is the creation of SharePoint groups, inspired by Adam Buenz’s recent post. His code is correct (though I believe an ordinal comparison is more appropriate than invariant culture), but it can’t easily handle scenarios requiring elevation, AllowUnsafeUpdates, etc. Instead, we can define a higher-order function like this:
public static SPGroup GetOrCreateGroup(this SPWeb web, string groupName,
Func<SPWeb, string, SPGroup> groupBuilder,
Action<SPWeb, SPGroup> associateGroup)
{
SPGroup group = web.SiteGroups.Cast<SPGroup>()
.FirstOrDefault(g =>
string.Equals(g.Name, groupName,
StringComparison.OrdinalIgnoreCase));
if (group == null && groupBuilder != null)
group = groupBuilder(web, groupName);
if (group != null && associateGroup != null)
associateGroup(web, group);
return group;
}
With which the original method is easily rewritten:
public static SPGroup GetGroupOrCreate(SPWeb web, string name,
string description, SPUser owner,
SPUser defaultUser, bool associate)
{
return web.GetOrCreateGroup(name,
(builderWeb, builderName) =>
{
var builderGroups = builderWeb.SiteGroups;
builderGroups.Add(builderName, owner, defaultUser, description);
return builderGroups[name];
},
(assocWeb, assocGroup) =>
{
if (associate && !assocWeb.AssociatedGroups.Contains(assocGroup))
{
web.AssociatedGroups.Add(assocGroup);
web.Update();
}
});
}
Again, the advantage is that we can easily tweak how the group is created and associated independent from the common get-or-create logic.

