Hi, I am not sure what is the best way to accomplish what I indend to do. My scenario is that I am working completely integrated in Revit, so no import/export/worksharing issues for the moment. However, I have to keep track of the elements (some types only, not every single element of every single type).
Now if I understand correctly, it is discouraged to rely on Element IDs, since those may not be unique in linked scenarios and may even change within a document. Instead it is recommended to use Unique IDs for this, but the API makes working with these not easy. Moreover, if I want to obtain an Element from an ID, I have to know the document as well. I could now always check all documents if they contain an element or always store a reference to the document alongside with the ID. I could however also work directly with the elements. They know which document they belong to and in case I need something from the element, I do not have to create one from the ID first. However, if I recall correctly, I read some time ago that this may be inefficient. Is that so?
TLDR: To put it in one short question: Is it alright to excessively keep references of elements around? If not: why? And is there a better way?
Solved! Go to Solution.
Solved by arnostlobel. Go to Solution.
Dear Cwaluga,
I would simply keep an eye on the trends set by the Revit API implementation itself.
It is consistently moving away from passing elements as aruments, and using element ids instead.
Therefore, I would agree that what you are doing is best:
I hope this helps.
I also hope Arnošt will correct me if he disagrees in any way or has anything more to add.
Thank you!
Cheers,
Jeremy
Thanks so much for your suggestions, Jeremy. I'll try to avoid keeping the elements alive more than necessary. But there are some points revolving around this, which are not obvious from the documentation.
If I may add two short follow-up questions:
1) Is there any way to obtain a UniqueId from an ElementId without instantiating the element first?
2) How expensive is the element instantiation really? Would a good rule of thumb be that unless you are in a part of your code which needs frequent element access, you are better off with using doc.GetElement whenever needed?
(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:
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:
Oh, and to answer some of the question cwaluqa asked:
Brilliant answer Arnošt! I think I'll have to read this a couple of times to digest what you wrote there. Thanks for this insightful piece of information.
Thank you, Cwaluga, for raising the issue, and Arnošt for the extensive answer.
I edited and published the discussion for posterity:
Cheers,
Jeremy