Saturday, July 19, 2008

The minimum C# to learn to program Revit?

I received a good question the other day from someone who was interested in learning to program Revit. They had done some C programming years ago, and was somewhat overwhelmed by the size of the "Introduction to C#" kind of books (which do tend to be 3+ inches thick).

So I was trying to explain what the core concepts of C# (or any .NET language, for that matter) that they would need in order to get to the point where they would be "dangerous", as they say.

Here are my thoughts:

Object-Oriented Programming (OOP)
Everything in .NET (as well as everything in the Revit API) is built around objects. So you must understand the fundamentals of how to make and use objects.

  • Class definitions
  • Creating new objects
  • Fields and Properties and Methods
  • Object scope/lifecycle
  • The concept of NULL;
  • User Interface (any UI that you do revolves around OOP)

Basic language features
I originally didn't address this... you'll obviously need to learn the basic language features of whatever language you choose. Declarations, IF statements, dealing with Enumerated types, etc...

Enumerators, For loops and Foreach loops
Much of the Revit API revolves around these concepts for looking up elements or other information. Enumerators (or Iterators) is probably the least intuitive of the bunch.

Code Example:

// To go through all of the elements in the model, one way is to do the following:

ElementIterator ei = commandData.Application.ActiveDocument.Elements;

while (ei.MoveNext())
Element e = ei.Current as Element;

// now you do something with Element "e".



Maybe it's just me, but almost every Revit application I'm involved with makes significant use of Arrays/Lists - so you may as well get comfortable with them. Personally, I'm a fan of what are called "Generic" Lists - which are lists of a specific type of object.

Code Example:

// if we had to go through all the elements, and find the elements that were "Pinned"

// Make our list object
List pinnedElements = new List();

// go through all the elements (NOTE: this way is far slower than some other alternatives - but reasonable for beginners)
ElementIterator ei = commandData.Application.ActiveDocument.Elements;

while (ei.MoveNext())
Element e = ei.Current as Element;

if (e.Pinned) pinnedElements.Add( e ); // if it is pinned, add it to the list

// now presumably we do something with all those pinned Elements we found...

Object Casting

I'm not sure if they still call it this in the books - but that's how I learned it. This would be used, for example if you had an "Element" from Revit, but you wanted to determine if it was a "Wall" so that you could get the wall-specific information from it.

There are a few mechanisms which support this kind of goal:

Code Example:

// Let's assume that I have "Element e" from one of our routines above, and we want to determine if it's a Wall, so that we can get the Wall width.

//option 1: direct casting

Wall myWall = (Wall)e; // cast "e" into a Wall.

// The down side of this approach? It throws an exception if "e" is not a wall. Which you could catch, but that's time consuming.

// option 2: testing first using the is

if (e is Wall) myWall = (Wall)e;

// this is OK as an approach... better than option 1 at least.

// option 3: using the AS keyword

Wall myWall = e as Wall;

// the benefit here? it casts it if it is the right type. If it's not? then myWall is NULL (which you'll need to test for).

All the methods described above have pros and cons in terms of writing the code and the performance of the application... So they're not meant to be instructive on either, so much as show you some possibilities.

I hope this will be useful to someone...



Dave Baldacchino said...

Thanks a lot Matt. This will help a lot of us trying to (someday) get started and become dangerous!

Andrew and/or Amy said...

Matt, this is great! I am currently undergoing my third semester of Computer Science, and this is the stuff they are drilling in our heads. I hope to apply this stuff to cool Revit (or just plain BIM) applications once I get through.

jvedio said...

Hi, just wanted to mention that the use of filters is now the recommended method of selecting objects using the api. It's much quicker than iterating over all of the elements in the model.

Matt Mason said...

Good point, jvedio...

Although there are still a decent number of other things to iterate over (other than elements).

I also tend to use iterators a little more than others - anything that's got a "GetEnumerator" method on it can use "foreach" - so that's probably an easier approach as well.

SBL said...

Great stuff! This is very useful. Thanks for sharing.

SBL Development & Applications