(I am sorry for the delay – have been busy lately).
I'd say it's fairly all right to store and work with Elements directly, in the public managed API anyway. We've made quite an effort to make element objects stable no matter how (and if) the model from which the elements are changes. The same does not apply internally in Revit native code where we need to be more cautious of memory re-allocation, which is why, internally, we generally prefer working with Ids. That general approach mirrors in the public API, for our goal is to have a public API that is as close to our internal API as possible.
So, my general recommendation would be:
- If there is work-sharing involved, stick with unique Ids;
- If work-sharing is not involved (and if you can somehow guarantee that), you can work with either elements directly or with Element Ids (or Unique Id, naturally), whichever way you prefer and are more comfortable with.
There is one point of caution: I've stated that we had made elements quite stable. That is certainly true for most kinds of element, but not for all, unfortunately. There are (I believe) still a few older kinds of elements that do not yet have an “ironclad” wrapper around them. Basically, if an element class does not have the IsValidObject method in their class, those elements would not be safe to hold on to, because in case the actual elements are deleted (or undone, or redone, of if their document got closed), the managed object would not know about it and any operation performed on it would lead to a crash. So, if you store elements make sure it's the kind which has the IsValidObject method, and grow the habit of always testing that method before every use of the element.
As for performance impact, there are, again, a few points I'd like to make:
- There is practically no performance degradation from fetching an element by its Id.
- Naturally, element Ids are smaller to store – they hold only an integer, while most Elements (the managed objects) contain at least two pointers and some flags also.
- Once you have an element (in the API), there will be no slowdown or memory impact. It is because once an element is read and brought in to memory, it stays there until its document is closed or the element is deleted in some work-shared action. However, there are plenty of methods that give you element Ids of elements that have not been completely read from the memory yet. Revit is pretty savvy (some may say lazy) about what part of an element is needed and which can be deferred until later. So, if an API application is given a list of elements and immediately fetches the corresponding elements so it could store them, that application may in fact have negative impact on Revit performance, because Revit would have to completely read those elements and have them in memory.
Oh, and to answer some of the question cwaluqa asked:
- No, it is not possible to obtain Unique Ids from a given Element Id.
- Element instantiation (the API managed object) is not so expensive. However, as I pointed above, it would be expensive if the elements has not been completely read and brought to memory yet. We might have its Id already, but if the element is not completely available yet, we'd need to read it from the file, allocate native memory for it (which may be significant), and then allocate the public API object for it.
Arnošt Löbel