I have not looked at Jamie's code, and I assume it is good, but I thought I'd add a comment to address your question about the nature of attribute definitions and attribute references.
the AutoCAD database contains Symbol Tables which define certain objects.... Without broadening this conversation too much, we're just talking about the Block Table, in this case. The block table contains the
definition of a block, that is, what objects autocad is to replicate each time the block is inserted into the model, or paper space. This is where the concept of an AttributeDefinition comes in. When you are defining a block to autocad, which in .NET is creating a BlockTableRecord, you would add objects of type AttributeDefinition. In the AttributeDefinition, you can set properties, such as a default value, and a prompt to display in the user dialog for attribute editing, Height, Width, Constant, Invisible.... etc.
But, once a block definition has been inserted into a drawing, in Model or Paper space, it becomes a BlockReference, and if you iterate through all of the Sub-Entities of the BlockReference then the (attribute) objects you will find there will be type AttributeReference.
perhaps if you take away all the autocad stuff and just think in terms of programming, you could look at a block definition in a similar way to a class definition, and maybe compare the attribute to a property defined in the class. when you are writing the code at design time, you are creating the definition of what that class is and what each instance will contain, but at runtime you may create multiple instances of the class, which will in turn create multiple instances of the properties. These class instances created at runtime are like the BlockReference and the property instances that go with them are like AttributeReference.
Hope that helps a little...
Dave O.