Space Engineers

Space Engineers

235 ratings
Programmable Block - Programming 101 for Space Engineers
By Textor
This is an overview of C# programming, trimmed down to the parts relevant to Space Engineers.
   
Award
Favorite
Favorited
Unfavorite
Introduction
This guide will go through C# in the context of its use in Space Engineers. It is meant for beginners, so there may be concepts here that are not used as often in professional C# code, since those are more advanced topics.

This guide also assumes you have read my first guide prior to this. If you haven't, please do so.

As in my prior guide, bold words in the text are found in the glossary at the end of the guide.
Variables
Variables are the bread and butter of programming. They let you store information in your program to be referenced or changed later on. Variables in C# are typed variables. This means that each variable has a specific data type assigned to it. The following types of variables (not objects) are available in Space Engineers:

NOTE: This only shows types that are implemented in-game. If they don't work in-game, I'm not listing them here. I have also tested the limits, and they are accurate.

int - a 32 bit integer number. This stores whole numbers (no decimal places!) between –2,147,483,648 and 2,147,483,647. (this gives you a range of 4.2 BILLION. You probably shouldn't need that much.) An int is declared as such:
int i = 42; int j = -246938494;

short - The int type's little brother. It is a 16 bit integer. It stores whole numbers, only the range is much smaller: -32,768 to 32,767.
short s = 1; short t = -12941;

long - The int type's big brother. It is a 64 bit integer. It ranges from –9,223,372,036,854,775,808 to 9,223,372,036,854,775,807. So, very large. You most likely won't need to use a long, but I'm keeping it here to be thorough.
long l = -1232142145535498495356; long m = 10;

uint - This is an unsigned 32-bit integer. It goes from 0 to 4,294,967,295.
uint u = 1; uint v = 257568258;

ulong - This is an unsigned 64-bit integer. It goes from 0 to 18,446,744,073,709,551,615
ulong u = 1; ulong v = 255585755784815857;

ushort - This is an unsigned 16 bit integer. It goes from 0 to 65,535.
ushort u = 1; ushort v = 10234;

float - a FLOATing point number (float? Floating point? Get it? Good.) Basically, a data type that has a decimal. Floats have a range of -3.4x10^38 to 3.4x10^38. For those unused to scientific notation: 3,400,000,000,000,000,000,000,000,000,000,000,000,000 or 3.4 Undecillion. That's a lot. It also has a precision of 7 decimal places. That means it can be: 1.1234567 but won't care past that (1.12345678 would be truncated to 1.1234567.) Floats must be defined by having an f or an F at the end of the number (it doesn't matter which case):
float f = 1.0f; float g = 2.445562F;

double - The float's cool older brother. A double can contain 1.7x10^308. (I will not write this out. I will also not do research for the name of that insane number. It's tons, you'll never need it all unless you are a masochist.) A double is also precise to 15 decimal places. It can be defined in a couple of ways:
double d = 1.0; double e = 1D; double f = 1d; double g = 1.0E+2;

What's with the E+2? Scientific notation. Yes, you can declare scientific notation on a double. Probably won't need to, though.

bool - Boolean, which is binary variable. It is either true or false. No grey areas, here. Except for this one, but that's not the boolean's fault. (Sorry, this joke was funnier when I could control the color of the text. Imagine that bit is grey. There, see? Funny! Yes, let's move on...)
bool thisIsTrue = true; bool thisIsFalse = false;

char - This is the (very) little brother of the string. It contains a single character. A character is a letter, number, or symbol. When declaring a character, you must contain that character in single quotes (aka, the apostrophe)(').
char c = 'c'; char d = '!';

string - Text. Lots and lots of text. Technically a string is an array of characters, but it'll be easier to consider it to be its own thing. This entire post can be contained in a string. The URL at the top of the browser is a string. Your username is a string. Your password is a string. War and Peace is a really, really huge string. A string can hold 2,147,483,648 characters. Most people won't be holding two billion characters in a string. Also, I don't think the names in Space Engineers are capable of being able to display something 2 billion characters long, so there's that. Strings' values must be contained in double quotes ("). Do not use two apostrophes ('') or the system will smack you on the nose and say "NO!"
sting s = "A string can hold 2,147,483,648 characters. Most people won't be holding two billion characters in a string."; string t = "Here's another string. Further examples seem unnecessary.";

var - Ok, this is a funny one. You may have seen people declaring all of their variables as var in code examples: this is because it is a context-sensitive type. What does this mean? If you declare a variable as a var, it takes the type of the value you assign it to when it is declared. In programmer-speak, all the other types discussed are explicitly typed. Var is implicitly typed. So:
var i = 1; /*this is an int.*/ var f = 1.0f; /*this is a float.*/ var d = 1.0; /*this is a double*/ var s = "Hi there!" /*This is a string.*/ var u = 2147483648; /*This is an unsigned integer*/ var c = 'c'; /*this is a char*/

enum - Enumeration! I'd explain this, but as of 1.063.004, this crashes to desktop. Do not use.
Operators
Operators, shockingly, allow you to perform operations on data. You will be using some operators a lot more than others. Make sure you know how operators work, since this is just as important as variables-- you probably want to do stuff with all that data you're storing, right? This is not an exhaustive list of operators in C#. This is a list of operators you will most likely be using while working in Space Engineers.

[] - The square brackets are used in a lot of places. Usually this is in reference to arrays. They can also be used in other advanced operations, but that is not a lesson we are teaching today.
int[] i = new int[100];
creates an array of 100 integers.
string s = "Hi, there!"; char c = s[2];
Using [], we can access the "index" of the string. In this example, variable "c" contains a comma. Don't forget that computers start counting at zero, not one.

() - Used for casting one variable type to another. This will be explained at length later, in the Casting subsection.

+ - Adds things. Just like you learned in school! Also, concatenates strings.
int i = 1; int j = 2; int k = i+j; /*k = 3!*/ int l = i+3; /*l = 4*/ string s = "Hello"; string t = ", Galaxy!"; string u = s+t+" I'm Textor!";/*"Hello, Galaxy! I'm Textor!"*/

- - Subtracts, just like on the tin!
int i = 1; int j = 2; int k = i-j;/*k = -1!*/ int l = i - 5 /*l = -4*/

* - multiplies. Also used for other, way more advanced things, so let's stick to multiplication.
int i = 2; int j = 3; int k = i*j; /*k = 6*/ int l = i * 5; /*l = 10*/

/ - Divides. NOTE: Two integers being divided becomes an integer! That means if you do 1/3 you'll get 0. If you use a float, it'll give you 0.3333333. Note that you will need to cast the divisor into a float in order to get a float answer, not just have the variable storing the answer be a float.
int i = 2; int j = 4; int k = j/i; /*k = 2*/ int l = i/2; /*l = 1*/ int m = i/j; /*m = 0*/ float n = i/(float)j; /*n = 0.5f*/

% - This is not percent. This is remainder. You know that thing you had in long division? When the numbers didn't quite add up? Yeah, that's this thing. This doesn't return 0.3333333 when you divide 1/3, it returns 1.
int i = 3; int j = 10; int k = j%i; /*k = 1*/

= - Assignment operator. It assigns things to other things. You probably figured this one out, already. I'm not even going to give you an example. If you need one, see every other block of code in this guide.

++<variable> - increment (increase) <variable> by 1 BEFORE using the variable.
int i = 0; int j = ++i; /*j = 1*/

<variable>++ - increment <variable> by 1 AFTER using the variable.
int i = 0; int j = i++; /*j = 0, i = 1*/

-- - The opposite of the above. Works the same, only it decrements (decreases) the variable by 1. --<variable> and <variable>-- are both present and operate the same as the ++ equivalents.

+= - This is an interesting one. Add a value to the variable. It's a combination of the + and = operators (as you probably can see from the fact that they are together.
int i = 1; i += 1; /* i = 2*/

-= - Same as above, only subtracts.

*= - Same as above, only multiplies.

/= - Same as above, only divides.

%= - Same as above, only generates a remainder.
Logic
Logic is very important to programming. It is the decision making part of the program. Is that thing more than the other thing? Do this stuff! Otherwise, Do something else!

if - If is one of the most common logical operations you'll perform. Just read it out like a sentence when you see it: if(1 < 2) THEN do stuff. It must use curly braces ({) to block out the code that executes when the condition evaluates as TRUE.
if(1 < 2) /* this is true.*/ { /*The code will execute!*/ } if(false) /*This is obviously false, and will always be false.*/ { /*This code will never execute.*/ }

else - Else is If's brother. Else cannot be used without If. Else is used when If evaluates as false. Read the entire thing as a sentence: IF (1 < 2) THEN do stuff, ELSE (otherwise) do other stuff.
if(1<2) { /*This code will execute.*/ } else { /*This code will not execute*/ } if( 1 > 2) { /*This code will not execute.*/ } else { /*This code will execute.*/ }

! - logical negation. (AKA, NOT.) So, think of it like this: If you see ! in a line, read it as NOT. "He does !love her." "This statement is !True." Used to invert the comparison (true = false, false = true).
if(!false) { /*this will always execute.*/ } bool real = true; if(!real) { /*real is true, so this will not execute.*/ }

&& - Logical AND operator. Compares two conditions. Returns true if both conditions are true. Read it as "AND" when you see it. "Mary && Joe went to the store."
if(true && true) { /*Will execute.*/ } if(true && false) { /*Will not execute.*/ } if((1 < 2) && (3 > 5)) { /*Will not execute.*/ } if((1<2) && (5>3)) { /*Will execute.*/ }

|| - logical OR operator. Compares two conditions. If EITHER is true, entire statement returns true. Read it as OR when you see it. "Soup || salad?"
if(true || false) { /*Will execute.*/ } if(false || false) { /*Will not execute.*/ } if((1 < 2) || (3 > 5)) { /*Will execute. 1 IS less than 2, so it is true. 3 is NOT more than 5, so it is false. So: true || false == true.*/ }


== - Equality comparison operator. Read it as "IS EQUAL TO" in a sentence: "USA == United States of America?"
if(1==1) { /*Will execute*/ } if("Hi" == "Hi") { /*Will execute.*/ } if("Hi" == "hi") { /*Strings are case sensitive. Will not execute.*/ } if(1 == 2) { /*Will not execute.*/ }


!= - Inequality comparison operator. Compares two values to see if they aren't equal. If 1 != 2, then it returns true. If 1 != 1, it returns false. Read it as "IS NOT EQUAL TO" in a sentence: "Dog != cat!"
if(1 != 2) { /*Will execute.*/ } if("Hi" != "Bye") { /*Will execute*/ } if(1 != 1) { /*Will not execute.*/ }

< - Less than. Used to evaluate if something is less than something else.
if(1 < 2) { /*this will execute.*/ } if(2 < 1) { /*this will not execute.*/ } if(1<1) { /*this will not execute*/ }

> - More than. See above.

<= - Less than OR equal to. If the value is equal to the comparison, it also returns true.
if(1 <= 2) { /* Will execute. */ } if(2 <= 1) { /* Will not execute*/ } if(1 <= 1) { /*Will execute*/ }

>= - More than OR equal to. Same as above.

? - The Riddler Was Here! Actually, it's a conditional operator. It checks if something is true or false, then returns a value depending on which case it was.
bool b = true; string s = "This is true."; string t = "This is false."; string u = b ? s : t; /*u = "This is true."*/

?? - ?'s more confused brother? Actually, no, it checks to see if a value is null. If it is, it returns the other value. If it isn't, it returns the value you were checking.
string s = null; string t = "S is null!"; string u = s ?? t; /*u = "S is null!"*/

switch - This may not work at the moment. I saw a bug report saying it isn't working, but I won't have an opportunity to test this until later. I find switches are awesome, and if it isn't working I'll definitely want the devs to add this to the game, since it will make logic infinitely easier to do. So, in the spirit of the awesomeness of switch statements, here is how a switch works: A switch evaluates a statement, and then looks at a "case" keyword to determine what to do with it. So, if you want to check an integer to see what numbers it has:
int i = 10; switch(i) { case 1: /*do stuff*/ break; case 5: /*do more stuff*/ break; case 10: /*do other stuff. Since i = 10, this is the one that executes*/ break; default: /*If all other cases fail, then do this thing.*/ break; }
This also works for strings ("case "Hi": do stuff; It would work if the string was "Hi". Remember that strings are case-sensitive. It only works for an exact match-- a single character difference fails the case.) and anything else you can think of, really. If it can be evaluated, a switch can evaluate it. This is really only useful if you have more than two possibilities. If you are just going to have a true/false evaluation, stick with if/else.

To basically summarize why a switch is awesome, let's rewrite the above code example using if/else:
if(i == 1){/*do stuff*/} else if(i == 5){/*do stuff*/} else if(i == 10){/*do stuff*/} else {/*do stuff if nothing else worked*/}
Casting
Ok, so I've referred to casting before. Casting is extremely important in a strongly-typed programming language (which C# is.) Basically, the system won't let you just do whatever you want with a variable. If you want to manipulate something, you have to make sure that it is the right type. Now, we could do it the hard way-- make a new method for every single possible instance we can see something being used:
public int DivideTwoInts(int i, int j) { return i/j; } public float DivideTwoFloats(float f, float g) { return f/g; } public double DivideTwoDoubles(double d, double e) { return d/e; } public float DivideTwoIntAndReturnAFloat(int i, int j) { float k = j*1.0f; return i/k; }

Ok, so that's a bit tedious, isn't it? So I want to divide two numbers, and return it into a format that can be used for anything. That's where casting comes in:
public double DivideTwoNumbers(var i, var j) { return i/(double)j; } int i = 4; int j = 2; int k = (int)DivideTwoNumbers(i,j);

So what did I do there? I made a single method (DivideTwoNumbers) and asked it to take two var variables (remember, var is context-sensitive- it automatically types the variable as to what is assigned to it), then divide one into the other, while converting the second number explicitly into a double (casting the variable as a double, basically). Then the result, which is returned as a double (so in this case, it would come back as 2.0) is cast into an int (now it becomes 2. Semantics, really, but the computer cares about the .0 being there and would return an error saying, "hey, you know this isn't an int you are saving to an int, right?")

Note: The example I used is definitely not an optimal solution, but this is about casting and not how to overload a method, which comes later, when I talk about methods. Fancy that.

The best way to summarize casting: Casting is the act of telling the system that yes, I really did mean to do that, and no, you don't need to tell me that these two variables aren't the same type, thank you.

You do have to make sure that what you are casting is compatible, however. Not everything is castable to something else. I can't cast a IMyBeacon to an int-- they are inherently incompatible, since IMyBeacon is a class and is far too complex to be boiled down to an integer. If you make a mistake and try to do something like int i = (int)IMyBeaconVariable; the compiler will helpfully say, "Hey, you know this isn't going to work, right?" in its own, cold way. You also can't cast a string to a character-- a string, if you recall, is an array of characters. You need to just access a single character in the string rather than try to convert the entire thing into a single character.

One of the best things in C# is the fact that they make casting pretty easy: there are a lot of methods out there to do casting, besides doing the () thing. So, if I want to convert an integer to a string, I use the very helpful (and near-universal) method .ToString():
int i = 0; string s = i.ToString(); /*This converts i to a string that contains '0'*/

You can also convert strings into numbers by using the helpful Convert class:
string s = "1"; double d = Convert.ToDecimal(s); /*converts to a double*/ int i = Convert.ToInt32(s); /*converts to an integer*/ short sht = Convert.ToInt16(s); /*converts to a short*/ long l = Convert.ToInt64(s); /*converts to a long*/ float f = Convert.ToSingle(s); /*converts to a float*/

You've probably also noticed that I've only talked about casting variables so far. What about casting objects? Well, we can do that a few ways. This is important, because you'll be doing it a lot in Space Engineers programming:
List<IMyBeacon> blocks = new List<IMyBeacon>(); GridTerminalSystem.GetBlocksOfType<IMyBeacon>(blocks); IMyBeacon = blocks[0] as IMyBeacon;

We can also change that last line to:
IMyBeacon = (IMyBeacon)blocks[0];

So let's examine this code a bit more closely:

List<IMyBeacon> blocks = new List<IMyBeacon>();
This looks intimidating, but it is actually really easy to read. We haven't gone into classes yet (they are a topic in themselves), but a class is declared as either a copy of an existing object or a new one (which requires us to tell the system that we want a new one, and put in the constructor.)

So, let's break it down:
List<IMyBeacon> blocks
List is a class. The <IMyBeacon> tells the system to use the List class template to make a list of IMyBeacon objects. So we have an IMyBeacon list object, named blocks.

= new List<IMyBeacon>();
Ok, so we are saying, "This is a NEW instance of a list. The list is type IMyBeacon. We will use the default constructor." (The constructor is the () thing at the end. It'll be explained in more detail when we get to classes, but basically, that () tells the system which constructor you want to use.)

So, that's basically what the whole "casting" thing is like.
Classes
Ok, the big one: these are like variables, only a lot more flexible and contain a lot more information. They are likely the thing you'll be using the most. In fact, in C#, the void Main() method is contained in a class. This is all because of C# being a 100% object oriented programming language. OOP (object-oriented programming) is not a topic I'm going to go into here, but suffice it to say, it likes to treat as many things as "objects" as it can. In other lessons, I'll probably get into the minutia of OOP and its benefits/drawbacks.

Class Definition
To define a class, you must do it outside the Main() method. You cannot define a class within Main(). To make a new class, you simply need to do this:
public class MyNewClass { public MyNewClass() { } }

Well, that was easy. But that doesn't seem to do much. So, let's go through this skeleton and see what we learn:
private class MyNewClass
public is a keyword in C# that tells the system if the class can be accessed outside of its namespace. It's something you don't need to worry about, really.
class is a keyword in C# that tells the system that you are making a new class, obviously. Notice that unlike a method declaration (we'll get into that later), this doesn't have a type other than class.

public MyNewClass() { }
You remember how I mentioned constructors earlier? Well, this is a constructor. When creating a new class instance, you have to call a constructor. This is something called the "default" constructor. You can overload constructors, as well, just like methods. Let's take a look at overloading a constructor:
public class MyNewClass() { string name; int integer; public MyNewClass() { this.name = "Default Name"; this.integer = 0; } public MyNewClass(int i, string s) { this.name = s; this.integer = i; } }

Ok, so let's look at the code, now. We now have two new variables: name and integer. You'll also notice that the constructor is doing things, now:
public MyNewClass() { this.name = "Default Name"; this.integer = 0; }
So, when you make a new MyNewClass object, you can do this:
MyNewClass mnc = new MyNewClass();
What will happen? Well, the default constructor (the one with no parameters) will automatically assign the value "Default Name" to the "name" variable, and 0 to the "integer" variable. What about the other constructor? How do we use that?
MyNewClass mnc = new MyNewClass(1, "Textor");
You'll notice that this has two parameters in it. This is called an overload. It allows you to have the exact same name for something, but use different inputs to make it do different things. In this case, we are saying that we want to pass the number 1 and the string "Textor" into the class. What will happen? The class will use the constructor we made that uses those parameters. If you look at the code:
public MyNewClass(int i, string s) { this.name = s; this.integer = i; }
We can see what the constructor is doing: assign the name "Textor" to the name variable, and assign the value 1 to the integer variable.

Ok, let's expand our class a bit more:
public class MyNewClass { string name; int integer; public MyNewClass() { this.name = "Default Name"; this.integer = 0; } public MyNewClass(int i, string s) { this.name = s; this.integer = i; } public string Name { get { return this.name; } } public int Integer { get { return this.integer; } set { this.integer = value; } } }
Ok, so we see the constructors, nothing new there... and we get to two new things: public string Name and public int Integer. These are properties of the class. Best practices say that you should never expose your variables directly to the outside of the class-- you should use a property to access them. This allows you extreme control over the variable, manipulating what things outside the class can see and what they can do with the variable. You'll notice the get and set keywords, here. Get allows you to retrieve the variable's value from the class. Using the return keyword, we pass the value of the variable to the outside of the class. The set keyword allows us to assign a value to a variable inside the class. The value keyword basically says, "this is the right-hand operator in the assignment" (Integer (left-hand operator)= 10 (right hand operator, aka "value")) In this case, we have integer receiving the value from outside the class. Let's take a look at how these interact when you are using it in code:
string s = mnc.Name; mnc.Integer = 10; int i = mnc.Integer;
What will happen here? Let's step through this:
string s = mnc.Name;
Create a new string s and assign it the value Name from class mnc. So assuming we initialized the class using the second constructor, s will be "Textor"
mnc.Integer = 10; int i = mnc.Integer;
Ok, so this says to assign the value 10 to the Integer property, then assign the value in Integer to the variable i. What is the result? i = 10, now.

So what does this mean for us? Well, Name is a read-only propery. You can't set the value, only see what it is. Integer is a property that can be read and written to. You'll notice this a lot in Space Engineers programming: for instance, let's say we have a IMyPiston block. The piston has a property called MaxLength which is read-only. That means I can find out what the MaxLength is set to, but I can't assign a value to it. It does have methods that increment the maxlength, but we can't assign a specific value to the property. Well, let's add a method that changes the name variable in our class:
/*all code is same from prior class definition.*/ public void ChangeName(string n) { if(n.Length < 10) { this.name = n; } }
So what does this one do? Well, it says, "give me a string to try to change the name to. If it is less than 10 characters long, set the name variable to that new name, otherwise don't do anything." This is why people might do methods to change variable's properties rather than letting them directly access it through the property itself-- it gives you a lot of control over what happens. You can also overload it (something you can't do with a property) to take different inputs and handle them differently. Technically, in this example, we can use the Name property to do the exact same thing:
public string Name { get { return this.name; } set { if(value.ToString().Length < 10) { this.name = value; } } }
Methods
Ok, now we get to methods. A method is a repeatable block of code. Are you planning to do something a lot? Stick it in a method! It makes it easier to read the code, and you don't have to type as much stuff.

A method needs to be defined within a class. If you recall, I mentioned that the Main() method was technically in a class. In Space Engineers, the class that is wrapping Main() isn't visible, but it is technically there. Because of this, you may create methods outside the Main() method.

Let's look at creating a method:
public void MyNewMethod() { }
And that's it. That is an entire method. It doesn't do anything, so it's kinda boring, but it is technically a method. Let's break it down:
public - this says that the method is accessible to all classes. Not strictly necessary to have here.
void - the void type means "I don't return a value." You can't declare a void variable, but you can declare a void method.
MyNewMethod() - this tells the system what the method expects the programmer to pass into it. Since () is empty, it means you aren't expecting anything to be passed into it.

Let's do something slightly more complex:

public int AddTwoNumbers(int i, int j) { return i + j; }
Ok, so this is pretty self explanatory. We'll break it down again to the pieces that are new:
int - this says that the method returns an integer. The method itself isn't actually an integer, it just passes one along when it is finished.
(int i, int j) - this is the parameter list. This tells the system that when you call AddTwoNumbers() you are requiring that the programmer put in two integer variables, i and j. Because you only have the one method named AddTwoNumbers, and that method has two parameters, these parameters are mandatory. You can make them not mandatory by creating overloaded methods, explained in a bit.
return - The return keyword says, "pass this value out of the method." In this case, it is taking the parameters i and j and adding them together. The result of i+j is returned. So if you pass in 1 and 2, it will return 3.


So, let's overload this thing:
public int AddTwoNumbers(int i, int j) { /*Nothing changed from above.*/ } public float AddTwoNumbers(float i, float j) { return i+j; }

So now, we have two AddTwoNumber methods. The system can tell which one you want to use based on the parameters you are passing into it:
int i = AddTwoNumbers(1,2); /*i = 3*/ float f = AddTwoNumbers(1.0f,2.1f); /*f = 3.1*/
So in this, we see that AddTwoNumbers is used with two different parameter sets, and all we had to do to tell the system which one to use is to use the proper variable assignments. What would happen if we did this?
int i = AddTwoNumbers(1.0f,2.1f);
It would return a warning-- you are not explicitly casting the AddTwoNumbers (float version) into an integer. If you really wanted to do that (why? you have the int overload version...) you can just put (int) in front of AddTwoNumbers().

How about this?
int i = AddTwoNumbers(1, 2.1f);
It would return an error-- there are no overloads that match this. Why? Here's what it is looking for:
AddTwoNumbers(int, int)
OR
AddTwoNumbers(float, float)

You gave it: AddTwoNumbers(int,float). If you wanted to do this, make another overload to handle it. What about more parameters? Maybe I want to pass in another variable? Well, just add a new overload:
public int AddTwoNumbers(int i, int j, bool ifirst) { if(ifirst) { return i+j; } else { return j+i; } }
Now you have a new overload: AddTwoNumbers(int, int, bool). This example is rather stupid, though, because it has no real effect on what the method does (adding a number to another number will always be the same. If this was subtraction, it would make a difference, however.)
Glossary
  • typed - A typed variable is something that must have a very strict set of data contained within it. If you have an integer, you can't have decimals. If you have a short, you can't assign 42,000 to it, because it is outside the range of a short. It can be very restrictive, but that restriction also protects you as a programmer-- you have to tell the system quite explicitly when you mean to violate a type (via casting) or it just won't work. If this restriction wasn't in place, a lot of weird things can happen.
  • object - Basically refers to anything that can have a value assigned to it in C#. C# is an object-oriented programming language. A variable is an object. A class is an object. Objects can be manipulated and the idea behind OOP is how objects interact.
  • Unsigned - There is no negative value. -1 is a "signed" integer. 1 is technically a "signed' integer (+1) but we omit the + in front of it. Unsigned means that it is always zero or positive. If I cast a negative number into an unsigned variable, it will convert to positive. It would probably be easier to multiply that variable by -1, though.
  • scientific notation - You probably learned this in chemistry (or will learn it in chemistry). The quick rundown is this: A number is a "Ones" place number with a decimal with any additional numbers behind it (3.14). You then multiply that by 10 to the power of whatever you want it to become. So if I want to make 3.14 3,140, I want to note it in scientific notation as : 3.14 x10^3 (3.14 x1000). This moves the decimal place 3 times: (3140.0). Negative exponents on the 10 make it smaller: 3.14x10-3 moves the decimal 3 spaces to the left. That means it becomes: 0.00314. In computers, this will be denoted not as 3.14x10^10, but 3.14E+10 (3.14 x 10 to the positive exponent of 10). You can also do 3.14E-10 (3.14 x 10 to the negative exponent of 10).
  • precision - How far down in decimals you can go. If I have a precision of 2, I can write 1000.00 or 1000.09. If I write 1000.001 it will be cut off to 1000.00 because it is only precise to 2 digits. Having a precision of 7 means you can write out 1.0000001 with no problem. Note that this only effects numbers after the decimal place. Precision isn't about the left-hand side of the decimal-- it is about the right-hand side.
  • context-sensitive - The system will look around and figure out what something does based on what the things around it are doing. var i = 1, in context says that you are making i an integer because you are assigning an integer to the variable i.
  • explicitly-typed - You deliberately define a variable to be a specific type. int i is explicitly defining i as an integer type.
  • implicitly-typed - You let context define the variable type. var i = 1 implicitly (not deliberately) defines i as an integer type.
  • array - a variable that is an array contains multiple values of the type defined in the array. int[] i = new int[3] would create an array of size 3. It can contain 3 integers: i[0] =1; i[1] = 2;i[2] = 3; All are contained within i, but must be accessed using an index (the number in the square brackets).
  • concatenate - Really fancy word to say, "Add it to the back of this thing." "Hi" + " there" concatenates the string to "Hi there". Not too hard, really.
41 Comments
JoMakaFloe 28 Dec, 2019 @ 5:35am 
everyone, Just a quick heads up on this guide; it was last updated in January 2015 and they have changed a lot in programming since then
Babbayega 6 Aug, 2019 @ 5:38pm 
quick question (hopefully) I am learning the code by examples of others and piecing together my drill rig operations. But i would like to display on a LCD the values of each of the variables, and also on an LCD the 'what i am doing now' information. the program has sections where each of the six stages of the rig operation happens. so I have places to put code to display the info.

Ideas? this make sense? Yes, i am reading through the guides for clues too. :)
☼king wu 19 Jul, 2018 @ 11:00am 
Anybody know how to make a mouse control a turret without actually "controling" it like if i wanted to control two and or more turrets at the same time? i need to know what the inputs are and the outputs and how to in a way put them together so once i run the block or whatever i can view from the cockpit and with the mouse i control two turrets.
Altonoj 26 Nov, 2017 @ 1:14pm 
Hi Textor, I hope you are monitoring the Guide now. I am getting an error message that Void cannot be used from C# to use Typeof(Void) to get the void type abject.
Lethal Shadow 8 Sep, 2017 @ 4:30am 
Awesome. But about classes. I have error when trying to create class:

// start of code
class Sensor
{
IMySensorBlock sensor;
public Sensor( string name )
{
sensor = GridTerminalSystem.GetBlockWithName( name ) as IMySensorBlock ;
}
// end of code

Compiler dont know what is GridTerminalSystem.GetBlockWithName.

// start of code
IMySensorBlock getSensor( string name )
{
return GridTerminalSystem.GetBlockWithName( name ) as IMySensorBlock ;
}
// end of code

Function compiled without errors, class method cant be compiled. Why?
Sgt Major Johnson 20 Aug, 2017 @ 3:08pm 
the only programming ive ever done is with websites
this kills me
Bubi 20 Jul, 2017 @ 9:51pm 
Have a beer , its on me.

Thank you for doing this <3
V4D4RS F1ST 4 Jun, 2017 @ 12:23am 
True. this has been around well over a year and is not specifically for SE. Great info though.
.MemeMan 28 May, 2017 @ 11:51am 
This guide was ripped from the Space Engineers official C# guide, wtf, didn't even credit them.
geniusface1234 7 Apr, 2017 @ 7:12am 
*click* noice