Disposing list’s SPSite/SPWeb without ParentWeb

Update 12/10/2008: Don’t use this technique; use the guidance here instead: The New Definitive SPSite/SPWeb Disposal Article

Chris O’Brien’s recent post discusses the need to dispose of SPSite and SPWeb objects, but only if they didn’t come from SPContext. To do this he depends on a list’s ParentWeb property, which currently returns the same instance as the original SPWeb. However, he notes that this strategy depends on the internal implementation of ParentWeb, which (however unlikely) might change.

As a future-proof alternative, I propose capturing the SPWeb as an out parameter if it will need to be disposed:

public void DoSomething() {
  SPWeb webToDispose = null;
  SPList list = getList(out webToDispose);

  // do something with list..
  foreach (SPListItem item in list.Items) {
    processItem(item);
  }

  // ** PROBLEM - how do we now dispose of the SPSite/SPWeb objects we created earlier? **
  // ** SOLUTION - if we didn't use context, webToDispose has reference
  if (webToDispose != null) {
    webToDispose.Dispose();
    webToDispose.Site.Dispose();
  }
}

private SPList getList(out SPWeb webToDispose) {
  webToDispose = null;

  SPContext currentContext = SPContext.Current;
  SPList list = null;

  if (currentContext != null) {
    list = currentContext.Site.AllWebs["MyWeb"].Lists["MyList"];
  }
  else {
    SPSite site = new SPSite("http://solutionizing.net");
    webToDispose = site.OpenWeb("/MyWeb");
    list = webToDispose.Lists["MyList"];
  }

  return list;
}

This code should be functionally equivalent and perhaps a bit easier to read, but without the dependency on ParentWeb. Thoughts?

Also, to add to Chris’s list of required reading, check out Roger Lamb’s excellent SharePoint 2007 and WSS 3.0 Dispose Patterns by Example.

Update 7/23/2008: How ironic…Chris and I have a leak! If you can’t spot it, I explain here.

Finding an SPWebApplication by ID

Not sure if it was me that prompted Neil’s post, but a question that came up earlier today was how to retrieve an SPWebApplication from its ID. Neil suggested trying to retrieve the generic SPPersistedObject by that ID, which eventually led me to SPFarm.GetObject(Guid).

SPFarm farm = SPFarm.Local;
Guid webAppId = new Guid("e81de291-7205-42fe-8228-422c6bbed277");
SPWebApplication webApp = farm.GetObject(webAppId) as SPWebApplication;
Debug.WriteLine(webApp);

Have I overlooked another method, or is this really the only way?

Bonus tip: Use SPAdministrationWebApplication.Local to get the web app for Central Admin.