1. This forum is obsolete and read-only. Feel free to contact us at support.keenswh.com

[Guide] Programmable Block - C# 101 For Space Engineers

Discussion in 'Programming Guides and Tools' started by Textor, Jan 2, 2015.

Thread Status:
This last post in this thread was made more than 31 days old.
  1. Textor

    Textor Junior Engineer

    Messages:
    775
    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 (not the titles) are found in the glossary at the end of the post.

    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:
    Code:
    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.
    Code:
    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.
    Code:
    long l = -1232142145535498495356;
    long m = 10;
    
    uint - This is an unsigned 32-bit integer. It goes from 0 to
    4,294,967,295.
    Code:
    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
    Code:
    ulong u = 1;
    ulong v = 255585755784815857;
    
    ushort - This is an unsigned 16 bit integer. It goes from 0 to
    65,535.
    Code:
    [/COLOR]
    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):
    Code:
    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:
    Code:
    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.
    Code:
    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)(').
    Code:
    char c = 'c';
    char d = '!';
    
    string - Text. Lots and lots of text. <em style="line-height: 18px;">Technically</em> 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. <em style="line-height: 18px;">War and Peace</em> 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 <em style="line-height: 18px;">that</em>. 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!"
    Code:
    sting s = "[COLOR= #2a2a2a]A string can hold 2,147,483,648  characters. Most people won't be holding two billion characters in a string.[/COLOR][COLOR= #2a2a2a]";
    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:
    Code:
    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.
    Code:
    int[] i = new int[100];
    
    creates an array of 100 integers.
    Code:
    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.
    Code:
    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!
    Code:
    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.
    Code:
    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.
    Code:
    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.
    Code:
    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.

    ++&lt;variable> - increment (increase) &lt;variable> by 1 BEFORE using the variable.
    Code:
    int i = 0;
    int j = ++i; /*j = 1*/
    
    &lt;variable>++ - increment &lt;variable> by 1 AFTER using the variable.
    Code:
    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. --&lt;variable> and &lt;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.
    Code:
    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.
     
    Last edited by a moderator: Jan 2, 2015
    • Like Like x 2
  2. Textor

    Textor Junior Engineer

    Messages:
    775
    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 &lt; 2) THEN do stuff. It must use curly braces ({) to block out the code that executes when the condition evaluates as TRUE.
    Code:
    if(1 &lt; 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 &lt; 2) THEN do stuff, ELSE (otherwise) do other stuff.
    Code:
    if(1&lt;2)
    {
    /*This code will execute.*/
    }
    else
    {
    /*This code will not execute*/
    }
    
    if( 1 > 2)
    {
    /*This code will not execute.*/
    }
    else
    {
    /*This code will execute.*/
    }
    [/SIZE][COLOR= #2a2a2a]
    [/COLOR]
    ! - 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).
    Code:
    if(!false)
    {
        /*this will always execute.*/
    }
    
    bool real = true;
    if(!real)
    {
    /*real is true, so this will not execute.*/
    }
    
    &amp;&amp; - Logical AND operator. Compares two conditions. Returns true if both conditions are true. Read it as "AND" when you see it. "Mary &amp;&amp; Joe went to the store."
    Code:
    if(true &amp;&amp; true)
    {
    /*Will execute.*/
    }
    if(true &amp;&amp; false)
    {
    /*Will not execute.*/
    }
    if((1 &lt; 2) &amp;&amp; (3 > 5))
    {
    /*Will not execute.*/
    }
    if((1&lt;2) &amp;&amp; (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?"
    Code:
    if(true || false)
    {
    /*Will execute.*/
    }
    if(false || false)
    {
    /*Will not execute.*/
    }
    if((1 &lt; 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?"
    Code:
    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!"
    Code:
    if(1 != 2)
    {
    /*Will execute.*/
    }
    if("Hi" != "Bye")
    {
    /*Will execute*/
    }
    if(1 != 1)
    {
    /*Will not execute.*/
    }
    
    &lt; - Less than. Used to evaluate if something is less than something else.
    Code:
    if(1 &lt; 2)
    {
    /*this will execute.*/
    }
    if(2 &lt; 1)
    {
    /*this will not execute.*/
    }
    if(1&lt;1)
    {
    /*this will not execute*/
    }
    
    > - More than. See above.

    &lt;= - Less than OR equal to. If the value is equal to the comparison, it also returns true.
    Code:
    if(1 &lt;= 2)
    {
    /* Will execute. */
    }
    if(2 &lt;= 1)
    {
    /* Will not execute*/
    }
    if(1 &lt;= 1)
    {
    /*Will execute*/
    }
    
    >= - More than OR equal to. Same as above.
     
    Last edited by a moderator: Jan 2, 2015
    • Like Like x 2
  3. Textor

    Textor Junior Engineer

    Messages:
    775
    ? - 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.
    Code:
    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.
    Code:
    string s = null;
    string t = "S is null!";
    string u = s ?? t; /*u = "S is null!"*/
    
    switch -
    <em style="color: #2a2a2a; font-family: &#39;Segoe UI&#39;, &#39;Lucida Grande&#39;, Verdana, Arial, Helvetica, sans-serif; line-height: 18px;">This may not work at the moment.</em> 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:
    Code:
    [/COLOR]
    [COLOR= #2a2a2a]int i = 10;[/COLOR]
    [COLOR= #2a2a2a]switch(i)[/COLOR]
    [COLOR= #2a2a2a]{[/COLOR]
    [COLOR= #2a2a2a]    case 1: /*do stuff*/[/COLOR]
    [COLOR= #2a2a2a]               break;[/COLOR]
    [COLOR= #2a2a2a]    case 5: /*do more stuff*/[/COLOR]
    [COLOR= #2a2a2a]               break;[/COLOR]
    [COLOR= #2a2a2a]    case 10: /*do other stuff. Since i = 10, this is the one that executes*/[/COLOR]
    [COLOR= #2a2a2a]                 break;[/COLOR]
    [COLOR= #2a2a2a]    default: /*If all other cases fail, then do this thing.*/[/COLOR]
    [COLOR= #2a2a2a]                 break;[/COLOR]
    [COLOR= #2a2a2a]}[/COLOR]
    [COLOR= #2a2a2a]

    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 <em style="color: #2a2a2a; font-family: &#39;Segoe UI&#39;, &#39;Lucida Grande&#39;, Verdana, Arial, Helvetica, sans-serif; line-height: 18px;">more than two possibilities</em>. 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:
    Code:
    [/COLOR]
    [COLOR= #2a2a2a]if(i == 1){/*do stuff*/}[/COLOR]
    [COLOR= #2a2a2a]else if(i == 5){/*do stuff*/}[/COLOR]
    [COLOR= #2a2a2a]else if(i == 10){/*do stuff*/}[/COLOR]
    [COLOR= #2a2a2a]else {/*do stuff if nothing else worked*/}[/COLOR]
    [COLOR= #2a2a2a]
    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:
    Code:
    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:
    Code:
    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():
    Code:
    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:
    Code:
    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:
    Code:
    List&lt;IMyTerminalBlock> blocks = new List&lt;IMyTerminalBlock>();
    GridTerminalSystem.GetBlocksOfType&lt;IMyBeacon>(blocks);
    
    IMyBeacon = blocks[0] as IMyBeacon;
    
    We can also change that last line to:
    Code:
    IMyBeacon = (IMyBeacon)blocks[0];
    
    So let's examine this code a bit more closely:

    Code:
    List&lt;IMyTerminalBlock> blocks = new List&lt;IMyTerminalBlock>();
    
    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:
    Code:
    List&lt;IMyTerminalBlock> blocks
    
    List is a class. The &lt;IMyTerminalBlock> tells the system to use the List class template to make a list of IMyTerminalBlock objects. So we have an IMyTerminalBlock list object, named blocks.

    Code:
    = new List&lt;IMyTerminalBlock>();
    
    Ok, so we are saying, "This is a NEW instance of a list. The list is type IMyTerminalBlock. 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:
    Code:
    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:
    Code:
    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.

    Code:
    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:
    Code:
    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:
    Code:
    public MyNewClass()
    {
        this.name = "Default Name";
        this.integer = 0;
    [COLOR= #2a2a2a]}
    [/COLOR][COLOR= #2a2a2a]
    So, when you make a new MyNewClass object, you can do this:
    Code:
    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?
    Code:
    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:
    Code:
    public MyNewClass(int i, string s)
    {
    [/COLOR][COLOR= #2a2a2a]    this.name = s;
    [/COLOR][COLOR= #2a2a2a]    this.integer = i;[/COLOR][COLOR= #2a2a2a]
    }
    
    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:
    Code:
    public class MyNewClass
    {
    [/COLOR][COLOR= #2a2a2a]    string name;
    [/COLOR][COLOR= #2a2a2a]    int integer;[/COLOR][COLOR= #2a2a2a]
    [/COLOR][COLOR= #2a2a2a]    public MyNewClass()
    [/COLOR][COLOR= #2a2a2a]    {
    [/COLOR][COLOR= #2a2a2a]    [/COLOR][COLOR= #2a2a2a]    this.name = "Default Name";
    [/COLOR][COLOR= #2a2a2a]    [/COLOR][COLOR= #2a2a2a]    this.integer = 0;[/COLOR][COLOR= #2a2a2a]
    [/COLOR][COLOR= #2a2a2a]    }
    [/COLOR][COLOR= #2a2a2a]    public MyNewClass(int i, string s)
    [/COLOR][COLOR= #2a2a2a]    {
    [/COLOR][COLOR= #2a2a2a]    [/COLOR][COLOR= #2a2a2a]    this.name = s;
    [/COLOR][COLOR= #2a2a2a]    [/COLOR][COLOR= #2a2a2a]    this.integer = i;[/COLOR][COLOR= #2a2a2a]
    [/COLOR][COLOR= #2a2a2a]    }
    [/COLOR][COLOR= #2a2a2a]    public string Name
    [/COLOR][COLOR= #2a2a2a]    {
    [/COLOR][COLOR= #2a2a2a]    [/COLOR][COLOR= #2a2a2a]    get
    [/COLOR][COLOR= #2a2a2a]    [/COLOR][COLOR= #2a2a2a]    {
    [/COLOR][COLOR= #2a2a2a]    [/COLOR][COLOR= #2a2a2a]    [/COLOR][COLOR= #2a2a2a]    return this.name;[/COLOR][COLOR= #2a2a2a]
    [/COLOR][COLOR= #2a2a2a]    [/COLOR][COLOR= #2a2a2a]    }[/COLOR][COLOR= #2a2a2a]
    [/COLOR][COLOR= #2a2a2a]    }
    [/COLOR][COLOR= #2a2a2a]    public int Integer
    [/COLOR][COLOR= #2a2a2a]    {
    [/COLOR][COLOR= #2a2a2a]    [/COLOR][COLOR= #2a2a2a]    get
    [/COLOR][COLOR= #2a2a2a]    [/COLOR][COLOR= #2a2a2a]    {
    [/COLOR][COLOR= #2a2a2a]    [/COLOR][COLOR= #2a2a2a]    [/COLOR][COLOR= #2a2a2a]    return this.integer;[/COLOR][COLOR= #2a2a2a]
    [/COLOR][COLOR= #2a2a2a]    [/COLOR][COLOR= #2a2a2a]    }
    [/COLOR][COLOR= #2a2a2a]    [/COLOR][COLOR= #2a2a2a]    set
    [/COLOR][COLOR= #2a2a2a]    [/COLOR][COLOR= #2a2a2a]    {
    [/COLOR][COLOR= #2a2a2a]    [/COLOR][COLOR= #2a2a2a]    [/COLOR][COLOR= #2a2a2a]    this.integer = value;[/COLOR][COLOR= #2a2a2a]
    [/COLOR][COLOR= #2a2a2a]    [/COLOR][COLOR= #2a2a2a]    }[/COLOR][COLOR= #2a2a2a]
    [/COLOR][COLOR= #2a2a2a]    }[/COLOR][COLOR= #2a2a2a]
    }
    
    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[/COLOR] 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:
    Code:
    string s = mnc.Name;
    mnc.Integer = 10;
    int i = mnc.Integer;
    
    What will happen here? Let's step through this:
    Code:
    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"
    Code:
    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:
    Code:
    /*all code is same from prior class definition.*/
    public void ChangeName(string n)
    {
    [COLOR= #2a2a2a]    if(n.Length &lt; 10)
    [/COLOR][COLOR= #2a2a2a]    {
    [/COLOR][COLOR= #2a2a2a]    [/COLOR][COLOR= #2a2a2a]    this.name = n;[/COLOR][COLOR= #2a2a2a]
    [/COLOR][COLOR= #2a2a2a]    }[/COLOR][COLOR= #2a2a2a]
    }
    
    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:
    Code:
    public string Name
    {
    [/COLOR][COLOR= #2a2a2a]    get
    [/COLOR][COLOR= #2a2a2a]    {
    [/COLOR][COLOR= #2a2a2a]    [/COLOR][COLOR= #2a2a2a]    return this.name;[/COLOR][COLOR= #2a2a2a]
    [/COLOR][COLOR= #2a2a2a]    }
    [/COLOR][COLOR= #2a2a2a]    set
    [/COLOR][COLOR= #2a2a2a]    {
    [/COLOR][COLOR= #2a2a2a]    [/COLOR][COLOR= #2a2a2a]    if(value.ToString().Length &lt; 10)
    [/COLOR][COLOR= #2a2a2a]    [/COLOR][COLOR= #2a2a2a]    {
    [/COLOR][COLOR= #2a2a2a]    [/COLOR][COLOR= #2a2a2a]    [/COLOR][COLOR= #2a2a2a]    this.name = value;[/COLOR][COLOR= #2a2a2a]
    [/COLOR][COLOR= #2a2a2a]    [/COLOR][COLOR= #2a2a2a]    }[/COLOR][COLOR= #2a2a2a]
    [/COLOR][COLOR= #2a2a2a]    }[/COLOR][COLOR= #2a2a2a]
    }
    
    Methods[/COLOR]
    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:
    Code:
    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:

    Code:
    public int AddTwoNumbers(int i, int j)
    {
    [/SIZE][COLOR= #2a2a2a]    return i + j;[/COLOR][COLOR= #2a2a2a]
    }
    
    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[/COLOR] 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:
    Code:
    public int AddTwoNumbers(int i, int j)
    {
    /*Nothing changed from above.*/
    }
    
    public float AddTwoNumbers(float i, float j)
    {
    [/COLOR][COLOR= #2a2a2a]    return i+j;[/COLOR][COLOR= #2a2a2a]
    }
    
    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:
    Code:
    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?
    Code:
    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?
    Code:
    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:
    Code:
    public int AddTwoNumbers(int i, int j, bool ifirst)
    {
    [/COLOR][COLOR= #2a2a2a]    if(ifirst)
    [/COLOR][COLOR= #2a2a2a]    {
    [/COLOR][COLOR= #2a2a2a]    [/COLOR][COLOR= #2a2a2a]    return i+j;[/COLOR][COLOR= #2a2a2a]
    [/COLOR][COLOR= #2a2a2a]    }
    [/COLOR][COLOR= #2a2a2a]    else
    [/COLOR][COLOR= #2a2a2a]    {
    [/COLOR][COLOR= #2a2a2a]    [/COLOR][COLOR= #2a2a2a]    return j+i;[/COLOR][COLOR= #2a2a2a]
    [/COLOR][COLOR= #2a2a2a]    }[/COLOR][COLOR= #2a2a2a]
    }
    
    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.
     
    Last edited by a moderator: Jan 3, 2015
  4. Nuros

    Nuros Trainee Engineer

    Messages:
    8
    Great Work, keep it up!! :D
    I have a question and hope you can help me.
    I learned Programmin in school but it´s a long time and i forgot the most.
    I wrote a script, create a list and saved all conectors in this list.
    List&lt;IMyTerminalBlock> Connectors =new List&lt;IMyTerminalBlock>();
    GridTerminalSystem.GetBlocksOfType&lt;IMyShipConnector> (Connectors);

    how can i search one connector by name only in my list?
    i always get errors.
    and is it possible to get a group assigned on my ship and store only the blocks of my group in this list?
    a tryed a little bit with BlockGroups command but i can´t get it working :/
     
  5. Locko1997

    Locko1997 Trainee Engineer

    Messages:
    17
    If im not wrong, you just need to add:

    Code:
    GridTerminalSystem.GetBlockWithName&lt;"Name goes here"> as Connectors
    
     
  6. AutoMcD

    AutoMcD Senior Engineer

    Messages:
    2,369
    vote sticky
     
  7. Morte

    Morte Trainee Engineer

    Messages:
    29
    Very nicely typed up and I like the little bits of humour here and there. Makes it a very nice read.

    Hope you make more of these =]
     
  8. Textor

    Textor Junior Engineer

    Messages:
    775
    Ok, guide for 101 is finished. 102 will be developed in the next couple of days.
     
  9. TheGallow

    TheGallow Trainee Engineer

    Messages:
    1
    Very nice work!

    As a programmer myself, I can say it looks very solid.

    Here is a minor contribution that might save some lines. You an write this:
    Code:
    [FONT= &#39][COLOR= #000088]public[/COLOR][COLOR= #000088]int[/COLOR][COLOR= #660066]Integer[/COLOR]
    [/FONT][FONT= &#39][COLOR= #000000]    [/COLOR][COLOR= #666600]{[/COLOR]
    [/FONT][FONT= &#39][COLOR= #000000]    [/COLOR][/FONT][FONT= &#39][COLOR= #000000]    [/COLOR][COLOR= #000088]get[/COLOR]
    [/FONT][FONT= &#39][COLOR= #000000]    [/COLOR][/FONT][FONT= &#39][COLOR= #000000]    [/COLOR][COLOR= #666600]{[/COLOR]
    [/FONT][FONT= &#39][COLOR= #000000]    [/COLOR][/FONT][FONT= &#39][COLOR= #000000]    [/COLOR][/FONT][FONT= &#39][COLOR= #000000]    [/COLOR][COLOR= #000088]return[/COLOR][COLOR= #000088]this[/COLOR][COLOR= #666600].[/COLOR][COLOR= #000000]integer[/COLOR][COLOR= #666600];[/COLOR][/FONT][FONT= &#39]
    [/FONT][FONT= &#39][COLOR= #000000]    [/COLOR][/FONT][FONT= &#39][COLOR= #000000]    [/COLOR][COLOR= #666600]}[/COLOR]
    [/FONT][FONT= &#39][COLOR= #000000]    [/COLOR][/FONT][FONT= &#39][COLOR= #000000]    [/COLOR][COLOR= #000088]set[/COLOR]
    [/FONT][FONT= &#39][COLOR= #000000]    [/COLOR][/FONT][FONT= &#39][COLOR= #000000]    [/COLOR][COLOR= #666600]{[/COLOR]
    [/FONT][FONT= &#39][COLOR= #000000]    [/COLOR][/FONT][FONT= &#39][COLOR= #000000]    [/COLOR][/FONT][FONT= &#39][COLOR= #000000]    [/COLOR][COLOR= #000088]this[/COLOR][COLOR= #666600].[/COLOR][COLOR= #000000]integer [/COLOR][COLOR= #666600]=[/COLOR][COLOR= #000000] value[/COLOR][COLOR= #666600];[/COLOR][/FONT][FONT= &#39]
    [/FONT][FONT= &#39][COLOR= #000000]    [/COLOR][/FONT][FONT= &#39][COLOR= #000000]    [/COLOR][COLOR= #666600]}[/COLOR][/FONT][FONT= &#39]
    [/FONT][FONT= &#39][COLOR= #000000]    [/COLOR][COLOR= #666600]}[/COLOR][/FONT]
    as this:
    Code:
    [FONT= &#39][COLOR= #000088]public[/COLOR][COLOR= #000088]int[/COLOR][COLOR= #660066]Integer [/COLOR][/FONT][FONT= &#39][COLOR= #666600]{ [/COLOR][/FONT][FONT= &#39][COLOR= #000088]get; set;[/COLOR][/FONT][FONT= &#39][COLOR= #000000] [/COLOR][COLOR= #666600]}[/COLOR][/FONT]
    It does the same thing, just in a much shorter notation.

    Since Keen has made it clear that too complex scripts will be thrown an error and that means it's likely character or line based, anything that saves space can be useful.
     
  10. Kuu Lightwing

    Kuu Lightwing Senior Engineer

    Messages:
    1,503
    Thank you, thank you, thank you! *hugs*
     
  11. Vilsol

    Vilsol Trainee Engineer

    Messages:
    4
    Last edited by a moderator: Jan 3, 2015
  12. Kuu Lightwing

    Kuu Lightwing Senior Engineer

    Messages:
    1,503
    By the way, this

    Code:
    List&lt;IMyBeacon> blocks =newList&lt;IMyBeacon>();
    GridTerminalSystem.GetBlocksOfType&lt;IMyBeacon>(blocks);
    
    doesn't seem to work. Looks like GetBlocksOfType and similar methods want List &lt;IMyTerminalBlock> as an argument.
     
  13. Textor

    Textor Junior Engineer

    Messages:
    775
    \

    Correct. The GetBlocksOfType&lt;T>() takes a IMyTerminalBlock interface as a parameter.

    When I do my proper guide to the API, I'll have all of this info in there. I'll adjust the code in the example, just in case it causes anyone confusion.
     
    Last edited by a moderator: Jan 3, 2015
  14. Digi

    Digi Senior Engineer

    Messages:
    2,393
    @Deathpaw

    Every variable that you create inside { and } stays there, you can't access it outside of that.

    So, for your code, you need to make them before the conditions so you can access them afterwards...
    But for simplicity sake you can just use in-line conditions:
    Code:
    string DoorSate = (DoorLock.Open ? "Open" : "Closed");
    string DoorPower = (DoorLock.IsWorking ? "On" : "Off");
    PS: Also, don't you mean DoorState instead of DoorSate ? :p
     
    Last edited by a moderator: Jan 4, 2015
  15. Arcelf

    Arcelf Trainee Engineer

    Messages:
    82
    Helpfull guide welldone!

    I am sure you will be getting to it but, how do we access the fields of a block, i'm not totally up on my C#!

    I want my program to know when a player is in range of a sensor. I know the sensor block has a field for DetectPlayers which is boolean true/false. I just need to know how to access that in code.

    I would of thought it would be something like: -

    Code:
    IMyTerminalBlock sensor = GridTerminalSystem.GetBlockWithName("sensor");
    if (sensor.DetectPlayers == true)
    {
    //Do stuff here
    }
    
    but that throughs back a few errors. Any Ideas?
     
    Last edited by a moderator: Jan 7, 2015
  16. Digi

    Digi Senior Engineer

    Messages:
    2,393
    @Arcelf
    Well, IMySensorBlock has DetectPlayers, but IMyTerminalBlock does not.
    Code:
    IMySensorBlock sensor = GridTerminalSystem.GetBlockWithName("sensor") as IMySensorBlock;
    
    if(sensor.DetectPlayers == true)
    {
        // Do stuff here with indentation :P
    }
    
    Also in case you didn't know, DetectPlayers field only tells you if the "Detect Players" checkbox is set for it, not that it actually detects them right now :p

    The field for sensor detecting something (any of the checked things) is IsActive.
     
    Last edited by a moderator: Jan 7, 2015
    • Informative Informative x 1
  17. 101m4n

    101m4n Apprentice Engineer

    Messages:
    130
    This is nice, great for beginners, but what those of us who can already write code really need, is a list of accessible variables!

    I have been looking for a while now, and can't seem to find any documentation as to what is and is not accessible.

    Anyone have any leads?
     
  18. Arcelf

    Arcelf Trainee Engineer

    Messages:
    82
    @101m4n

    Yes look at these links

    https://www.spaceengineerswiki.com/Programmable_Block

    https://steamcommunity.com/sharedfiles/filedetails/?id=360966557
     
  19. Arcelf

    Arcelf Trainee Engineer

    Messages:
    82
    @Digi

    Thanks I just worked out that I was referenceing the wrong class level, but still can't work out how to access the sensor class that contains the field its self. I'll try your code :)
    Can you tell me where you have read that the boolean field is only for saying whether the box is checked?
     
    Last edited by a moderator: Jan 7, 2015
  20. Arcelf

    Arcelf Trainee Engineer

    Messages:
    82
    @Digi

    Ok, im sorry i doubted you, just tested it, and it is indeed a field for the check box!

    Thanks man you have been very helpfull :)

    Can't wait till they add sensor state!
     
  21. 101m4n

    101m4n Apprentice Engineer

    Messages:
    130
    Awesome! Thanks
    Couldn't find anything myself, must not have been looking hard enough.
     
    Last edited by a moderator: Jan 7, 2015
  22. Arcelf

    Arcelf Trainee Engineer

    Messages:
    82
    @Digi and everyone who needs to know

    I've got it!

    Code:
    IMySensorBlock sensor = GridTerminalSystem.GetBlockWithName("sensor") as IMySensorBlock;
    if (sensor.IsActive == true)
    {
        //Do stuff here    
    }
    
    the .IsActive gets the current state of the sensor, works like a charm :) and I would think thats for every other block that has an active/inactive state.

    Thanks for the help Digi I would have been stuck without your input!
     
  23. Arcelf

    Arcelf Trainee Engineer

    Messages:
    82
    @101m4n

    No problem ;) It takes a village :) what a great community we have here
     
  24. Textor

    Textor Junior Engineer

    Messages:
    775
    You can actually write the if statement as:

    Code:
    if(sensor.IsActive)
    
    since it is a bool-- so it doesn't need an explicit comparison. If you wanted to check if it is false, you can also write it like:

    Code:
    if(!sensor.IsActive)
    
    instead of an explicit if(sensor.IsActive == false).

    I will note, however, that if you find your code is easier for you to understand using explicit comparisons, then it is completely valid to do it that way.
     
  25. Arcelf

    Arcelf Trainee Engineer

    Messages:
    82
    @Textor

    Good point, I did know this but was just leaving it in to be clearer! I'll use that from now on, looks like this environment really is true to C# syntax!
     
  26. Alpha_Squad

    Alpha_Squad Trainee Engineer

    Messages:
    13
    Code:
    publicintInteger
        {
            get
            {
                returnthis.integer;
            }
            set
            {
                this.integer = value;
            }
        }
    
    In terms of the code above, the compiler keeps on wanting me to put ";" after the words "get" and "set" for some reason. Not sure if it will screw up the rest of my code, but it seems to be a problem nonetheless.
     
  27. Textor

    Textor Junior Engineer

    Messages:
    775
    Hm, not sure why it would do that, the code is properly formatted and valid C# code. Just in case I made a mistake, I just verified it in Visual Studio, which finds no issue. Maybe it is a bug with the C# handler in Space Engineers?
     
  28. gimmilfactory

    gimmilfactory Junior Engineer

    Messages:
    523
    I have read this and all other posts by you 20 times, Textor. Coming from someone with a different programming background (I know a decent amount f bash and html, and css);I still don't understand this stuff. I just need a simple program and this is just out of my grasp I guess..ffs...-_-
     
  29. Phoera

    Phoera Senior Engineer

    Messages:
    1,713
    there is much examples on workshop and here.
    Is not enough?

    which example are you needed?
     
  30. Cuber

    Cuber Apprentice Engineer

    Messages:
    262
    You'd be better off looking checking out C# fundamentals:
    https://channel9.msdn.com/Series/C-Fundamentals-for-Absolute-Beginners
     
    Last edited by a moderator: Jan 12, 2015
Thread Status:
This last post in this thread was made more than 31 days old.