C# Primer

gravatar

Scott Currie

Learn all of the C# syntax you need to know to start writing real-world BimlScripts.

published 08.14.15

last updated 10.04.15


Part of lesson C# Primer.

Share

Introduction

For many people who begin to move beyond plain Biml and into full automation with BimlScript, .NET coding can be somewhat intimidating. In this lesson, we will provide the basics of C# syntax that you need to know in order to be successful writing even very advanced BimlScript code nuggets. I will not attempt to give you an end-to-end course that will qualify you as an expert C# application developer. There are plenty of other resources - both paid and free - online and in-person - that do a great job of guiding you through all aspects of C# programming. This lesson is for those who want to learn just enough C# to start automating their Biml.

Why C#?

Before diving into C# syntax, I'd like to address a frequently asked question:

Since BimlScript supports both C# and VB, why is C# the common recommendation?

The modern versions of C# and VB are actually quite similar - so similar that there are automated tools that do a very capable job of automatically converting between them. You won't find any problems that can be solved with one but not the other or that can be solved much more easily with one than the other. The differences that do exist very rarely have any applicability whatsoever to scripting applications such as BimlScript. Consequently, the choice between C# and VB is not so much a technical choice as one of stylistic preference and alignment with the long-term skills of your team. Given that, here are the reasons I personally prefer C# for BimlScript code nuggets (and why I make Biml design decisions with C# first in my mind):

  1. C# uses braces, parentheses, and other punctuation characters rather than keywords (THEN, END, etc.) much more frequently than VB. This makes code much easier to read when code nuggets are interspersed with Biml XML.
  2. There is some evidence that C# has greater adoption than VB and plenty of evidence that it has a stronger, more active community [wikipedia]. This leads to greater ability to hire team members who already know it and greater availability of free online help when you need it.
  3. Most new .NET language and framework features are being driven by the C# language design team. In my opinion, this results in new language features having slightly better implementations in C# as it was the original design target.
  4. In my experience, there is better support among tools and components vendors for C#, which makes it easier for us to build the highest quality developer tools for C# code nuggets.

All that being said, I understand that language choice is informed by a variety of factors that we cannot fully capture here, which is why we support both.

Declaring Variables

The first thing you need to learn how to do in any scripting application is to declare variables that will hold your working data. In C#, variables are declared with their type and name. Type can be any of the C# built-in types or they can be custom types (which we'll learn more about later). For example, I can write the following to declare an integer or a string variable:

int myNumber;
string myText;

Note that after each statement (as with all C# statements) you need to include a semicolon to indicate that the statement is complete. Once we've declared these variables, I can assign values to them, as follows:

int myNumber;
string myText;
myNumber = 0;
myText = "Hello World!";

If I want to save some typing, I can optionally combine the type declaration and initial assignment as follows:

int myNumber = 0;
string myText = "Hello World!";

While better, this is still tedious. Thankfully, C# has a neat feature called implicit typing. Only in cases where I use the initial assignment syntax above, I can actually leave out the type, replacing it with "var". The C# compiler is smart enough to figure out that the variable must be a string based on the fact that I assigned a string initial value to it. Let's use that simpler syntax:

var myNumber = 0;
var myText = "Hello World!";

Remember that even after assigning the variable, you can change the value later. I'll provide a quick example of that, but you'll see much more of it later in this lesson and in future lessons:

var myNumber = 0;
var myText = "Hello World!";
myNumber = 42;

Remember that you do NOT need to include the var keyword or a type name in subsequent assignments. Once the variable is declared, it stays declared and can be used without declaring it again.

Creating Collections

You are going to use collections very extensively in you BimlScript code nuggets. While most of your collections will be created dynamically when you read various metadata sources (database schemas, database tables, flat files, etc.), it is often useful to create your own collections to hold configuration and other data. Declaring a collection variable is just like creating a scalar variable above, but there are a few additional things you should now.

There are a variety of collection types that are offered by the .NET Framework and commonly used libraries. For the vast majority of cases where you are creating your own collections, you will use one of only two different types.

If you know all of the collection items upfront and won't need to add more items later, you should use and array. The syntax to create an array with a collection of initial values is as follows:

var collection1 = new[] { "first", "second", "third", "fourth" };

If you know some collection items upfront but expect you might want to add more items to the collection later, you should use a List. For example:

var collection2 = new List<string>() { "first", "second", "third", "fourth" };

Note that you need to include the type of the elements you intend to store in the list between angle brackets. This is because List is a "generic" type and you are specifying the specific type to use within the angle brackets.

When you are ready to add a new item to the collection, just use the Add method, as follows:

collection2.Add("new item");

Lastly, if you want to create a new collection but don't have any initial items, you can use the same declaration syntax as above but with the initial items omitted. For example:

var collection2 = new List<string>();

Conditional Logic

Setting variables is a great start, but if we want to create actual business logic, we're going to need more. First and foremost is the ability to execute different logic based on some external condition - in other words the if/then/else construct. C# uses very simple syntax for this. To create a conditional logic block, add an if statement which contains the condition expression. After the if statement surround with curly braces the code that should execute when the condition expression is true. It should help to see an example:

if (true) {
    myText = "The condition was true";
}

Of course, you don't need to use just true or false in the conditional, you can write any C# expression that evaluates to a boolean result. Additionally, you can include multiple statements within the conditional code block. For example:

if (myNumber > 10) {
    myText = "The condition was true";
    collection2.Add(myText);
}

Sometimes, you want to do something different when the conditional evaluates to false. For that, we have the else statement. The else statement must be paired with an if statement but does not require a condition, since the condition is implicitly the opposite of the if statement condition:

if (myNumber > 10) {
    myText = "The condition was true";
    collection2.Add(myText);
} else {
    myText = "The condition was false";
    collection2.Add(myText);
}

What if I have more complex logic? Perhaps I'd like to have different text for each of many different integer thresholds. For this, we have the "else if" construct. It permits us to chain together as many conditionals as we like, along with an optional else to cover the case where none of the conditionals matched:

if (myNumber > 40) {
    myText = "The number was greater than 40";
    collection2.Add(myText);
} else if (myNumber > 30) {
    myText = "The number was greater than 30";
    collection2.Add(myText);
} else if (myNumber > 20) {
    myText = "The number was greater than 20";
    collection2.Add(myText);
} else if (myNumber > 10) {
    myText = "The number was greater than 10";
    collection2.Add(myText);
} else {
    myText = "The number was less than or equal to 10";
    collection2.Add(myText);
}

Switches

Occasionally, you will have a bit of logic that checks a variable against a list of static values. You could implement this with a chain of if/elseif/else statements, but some people prefer to use a more compact syntax for this. C# offers the switch/case syntax. It works like so:

switch (myNumber) {
    case 0:
        myText = "zero";
        break;
    case 1:
        myText = "one";
        break;
    case 2:
        myText = "two";
        break;
    case 3:
        myText = "three";
        break;
    case 4:
    case 5:
    case 6:
    case 7:
        myText = "FourToSeven";
        break;
    default:
        myText = "Not a recognized value";
        break;
}

A few things to note:

  1. You start with a switch statement that includes the expression to be checked.
  2. Within the switch is a collection of case statements. Each case must be a literal value. It cannot be a variable.
  3. Each case must end with a break statement (or a return statement/exception throw).
  4. You can stack cases together if they use the same logic, as is shown for 4, 5, 6, and 7.
  5. You can optionally include a default case to handle unlisted values.

Loops

After if/else statements, the next most valuable statements in your C# toolbelt are loops. Loops provide a capability to repeat the same block of code either for each item in a collection or until a specified condition is met. While there are several types of loop structures and patterns available in C#, three will cover the vast majority of coding scenarios you'll ever encounter.

Foreach

If you have a collection and would like to perform some logic for each of its items, C# has a convenient language keyword just for that: foreach. It is very simple to use:

foreach (var item in collection1)
{
    collection2.Add(item);
}

This loop will take each item in collection1, one after the other, assign the item to the variable name "item" and then execute the code within the curly braces with that value. After it finishes one iteration, it will go back to the top and start over with the next item in collection1.

Note that "var item" is a variable declaration just like the ones we discussed earlier. You could specify a type instead of using "var" but using "var" saves us some typing. Also, you can change "item" to be any variable name you like - just be sure to change it inside of the loop as well.

While

Sometimes you want to run a bit of logic repeatedly until some condition is met. That is what a while loop is for. Let's start with an example:

while (myNumber > 0)
{
    collection2.Add("My number is: " + myNumber);
    myNumber = myNumber - 1;
}

This loop will first check if the condition is met (i.e. is myNumber greater than 0). If so, it will execute the code within the curly braces. After it finishes one iteration, it will check the condition again. If it is still true, it will go back to the top and run another iteration. If it isn't true, the loop ends.

Normally within a while loop, one or more of the statements must change variable values so that the condition eventually evaluates to false. Otherwise, the loop would continue forever.

One last fun thought. The foreach loop is actually just a special case of the while loop. Remember our foreach loop from earlier?

foreach (var item in collection1)
{
    collection2.Add(item);
}

Here is the while loop equivalent:

int i = 0;
while (i < collection1.Count)
{
    var item = collection1[i];
    collection2.Add(item);
    i = i + 1;
}

Since iterating over a collection is so common (and for other reasons having to do with minor differences in accessing different types of collections), the foreach keyword was provided in the C# language to save programmer time.

For

Speaking of special cases of the while loop, the for loop provides another type of time saving shortcut. Language designers realized long ago that a very common loop pattern was to create an iterator variable, check the value of that variable against some other variable, do some work, increment the iterator variable, and then repeat. (In fact, the while loop implementation of the foreach loop in the previous section does exactly that.) Since this is so common, the for loop was introduced to make that pattern fast and easy. Here is the same code as the foreach and while loops above, but using for:

for (int i = 0; i < collection1.Count; i++)
{
    var item = collection1[i];
    collection2.Add(item);
}

Notice how the for loop just takes the variable declaration and initialization, the conditional expression, and the increment and separates them with semicolons on the same line. Also note that i++ is just shorthand for i = i + 1.

Comments

Sometimes you will want to make a note in your code for future reference or temporarily disable some lines of code without deleting them. To do this, you can use comments. C# offers two types of comments that you need to know for BimlScript: single line and multi-line.

Single line comments indicated that everything after the comment operator // should be treated as a comment until the end of the line is reached. For example:

var myNumber = 42; // This is my comment text

Multiline comments are a bit more powerful. You begin with a /* operator and end with a */ operator. Everything in between is treated as a comment, even if it spans multiple lines. Note that you are not allowed to nest multiline comments.

var myNumber = 0;
/*var myText = "Hello World!";
This is some random text that wouldn't compile.
var myOtherVariable = 15;*/
myNumber = 42;

Scoping

There is one further consideration that you should be aware of, as it relates directly to the interaction between variable declarations and the conditional/loop structures we examined earlier - and that is scoping.

When you declare a variable in C#, it is defined for the current scope. At the end of that scope, the variable disappears as if it never existed. Scopes are created any time you write an open curly brace { and they end whenever you type the matching closing curly brace }. Consequently, every if/else block and every loop we have shown in this lesson creates a scope. Furthermore, scopes can be nested. If I create an if statement that contains another if statement, variables defined in the outer if statement will be available to the inner if statement, but the outer if statement will not be able to access variables defined in the inner if statement. Let's take a look at an example:

if (myNumber > 0) {
    var scope1 = "Hello World!";
    if (myNumber > 20) {
        var scope2 = "Hello Biml! " + scope1;
        collection2.Add(scope2);
    }
    collection2.Add(scope1);

    // The following would be an error because scope2 is out-of-scope
    // collection2.Add(scope2);
}

if (myNumber > 42) {
    // Here we can safely re-declare scope1 because the previous instance 
    // is out-of-scope and therefore no longer exists
    var scope1 = "Hello Biml!";
    collection2.Add(scope1);
}

You can think of variable scoping as defining the lifetime for a variable. While is scope, the variable it alive. Once you exit the scope in which the variable was defined, it is no longer alive and therefore cannot be used.

Conclusion

Once you have mastered variable declaration/assignment, conditionals, and loops, you already know most of the C# syntax you need to write most of the BimlScript you will ever need. If you would like to improve your skills even further, we strongly recommend spending an afternoon on more in-depth C# training that is available from many paid and free sources online.

PostScript: A Note about Curly Braces

Note that the curly braces are not strictly required. If omitted, the conditional or loop will include the one statement that immediately follows the if statement. While there is considerable disagreement among C# developers about the merits and demerits of omitted braces, you should NEVER omit them when writing BimlScript code nuggets.

Bimlscript code nuggets are compiled to a more complex program under the hood. Sometimes what you think is a single statement actually gets broken up into multiple statements in the underlying program. Consequently, omitting curly braces can result in code not running when you thought it would.

Finished?

Complete the lesson C# Primer:

You are not authorized to comment. A verification email has been sent to your email address. Please verify your account.

Comments

gravatar

Devender

8:10am 08.29.16

How to get rid of syntax error highlights in code window? c# block within <# #> block is showing as error but compiles.

gravatar

Anand Mangipudi

7:02pm 11.13.17

No more red squiggly lines with the new BIML express!!