It’s free for Open source projects. ( you can confirm that part)
I don’t think we actually qualify
as we have plans for receiving money and paying core developers. So I’d actually would have to pay out of pocket for it, though I might try the trial again if they let me, and if it is nice enough buy it.
Sure, give it a try. Currently core developers aren’t being paid. So we are eligible for at least a year.
https://www.tutorialspoint.com/csharp/index.htm
Environment
csc programname.cs
Program Structure
using System; // includes the System namespace
namespace App
{
class HelloWorld
{
static void Main(string[] args) // Main = program entry point
{
// Single-line
/* multi-line */
Console.WriteLine("Hello World!");
Console.ReadKey(); // prevents autoclose
}
}
}
Questions!
- What is the
string[] args
thing? - If a file has a namespace instead of a single class, do I name the file after its namespace instead?
Basic Syntax
using System;
namespace RectangleApplication
{
class Rectangle
{
// fields
int length, width;
public void AcceptDetails() //method
{
length = 4;
width = 5;
}
public int GetArea()
{
return length * width;
}
}
class ExecuteRectangle
{
static void Main()
{
Rectangle r = new Rectangle();
r.AcceptDetails();
Console.WriteLine(r.GetArea());
Console.ReadKey();
}
}
}
- Now, do I name the file
rectangle.cs
orprogram.cs
, hmmm?
Ok, so a class is just a template. Perfect. So I need to create an object from it like so:
Class obj = new Class();
And to access a method or a field:
obj.fieldName;
obj.Method();
And a namespace is a collection of classes.
To be continued…
I don’t know C#, but I’m pretty sure args
contains the command line arguments.
Let’s say you wanted to list the contents of directory my_dir
like this:
ls my_dir
or (in windows if i’m not wrong):
dir my_dir
ls
(or dir
) will be run. But how does it know what directory it should read? It will read args
to see what command line arguments it received. It sees “my_dir” and then knows what directory it should list. This applies to other programs that read command line arguments.
Edit: Maybe this answer will explain it better: c# - What is "string[] args" in Main class for? - Stack Overflow
not a expert but
- Elrakrez already explained above
- The name of the file really does not matter, but you should name it after the main class
- You would ideally separate it into 2 files but i think in this case it would be called rectangle.cs
also brackey got a good video tutorials if like those:
I guess that’s a fine enough starting point, though as an expert reading through the Tutorialspoint tutorials I’ve found multiple errors. With that C# tutorial, I was able to find a mistake in just a few minutes. They incorrectly talk about destructors running when things go out of scope, which is entirely wrong. Finalizers (as they are properly called in garbage collected languages), actually only run when the garbage collector notices that the object is unreferenced and should be deleted. Microsoft’s documentation says that: Finalizers - C# Programming Guide - C# | Microsoft Learn And one final point is that the Dispose pattern should basically always be used over finalizers.
I guess if you can work through the entire tutorial, it will be a good starting point, even with the mistakes, which you can then build on.
It’s much better for organization to name files after what classes they contain. For Thrive we are using stylecop which will not let your code pass if you don’t name your files after the classes they contain. This is why you should really use an IDE for C# as it can automatically add new files to the project definitions for it to be compiled.
They are the command line parameters passed to your program. For example git pull master
would receive the pull master
part as args (and possibly the exe name that is running, though I haven’t checked the C# documentation so I don’t know, at least in C++ the first argument is always the running executable name, then followed by the command line parameters).
No, because namespaces are supposed to span multiple files. So if you have a folder called Utilities
with multiple files in it, all of them should define their classes in the Utilities
namespace. Once again this is a good naming practice to organize large programs.
Files should not usually contain multiple classes. Though, I make exceptions to this rule for closely related classes like having a small interface and the implementation in the same file. But in this case you should have Rectangle.cs
and Program.cs
separately. And the class containing Main
should be named Program
.
Data Types
Three branches: Value, Reference and Pointer types.
Values types are assigned a value directly.
type | Type | Size (in bit) | Signed? | Number of decimals | Range | Default Value |
---|---|---|---|---|---|---|
bool | Boolean | 8 | – | – | true or false | false |
char | Unicode character | 16 | – | – | [U+0000, U+FFFF] | ‘\0’ |
byte | Integer | 8 | ✗ | – | [0, 255] | 0 |
sbyte | Integer | 8 | ✓ | – | [-128, 127] | 0 |
ushort | Integer | 16 | ✗ | – | [0, 65.5k] | 0 |
short | Integer | 16 | ✓ | – | [-32.7k, 32.7k] | 0 |
uint | Integer | 32 | ✗ | – | [0, 4.29B] | 0 |
int | Integer | 32 | ✓ | – | [-2.1B, 2.1B] | 0 |
ulong | Integer | 64 | ✗ | – | [0, 18.4qi] | 0 |
long | Integer | 64 | ✓ | – | [-9.2qi, 9.2qi] | 0L |
float | Floating point | 32 | ✓ | 6-9 | [1.5 \times 10-45, 3.4 \times 1038] | 0.0F |
double | Floating point | 64 | ✓ | 15-17 | [5.0 \times 10-324, 1.7 \times 10308] | 0.0D |
decimal | Floating point | 128 | ✓ | 28-29 | [1.0 \times 10-28, 7.9 \times 1028] | 0.0M |
sizeof()
method, which outputs the answer in bytes.Console.WriteLine(sizeof(byte)); // outputs 1
object obj;
obj = 100;
dynamic dyn = 15;
String type can be assigned string values.
String str "Hello";
@"World";
Type Conversion
Two ways: Implicit and Explicit.
Implicit conversion converts a smaller type to a greater one. Rules:
- OK Integer ----> Floating point
- NOT OK Integer <------ Floating point
- NOT OK float/double -------> decimal (binary, not binary eh)
- NOT OK signed Integer --------> unsigned Integer
- Can’t convert to the same size (byte can’t convert to sbyte)
- Can only convert if within the right range
ToType()
. However, to convert to float
, one needs to use the ToSingle()
method. For integers (except bytes), just use ToInt<size in bit>
for the corresponding signed integer type or ToUInt<size>
if unsigned.int a = 20;
a.ToString();
Variables
Eh, variables just store a value within a memory location.
int a, b; OK
int a, b = 5, 10; NOT OK
You can also accept user input using the ReadLine()
method.
int a = Convert.ToInt32(Console.ReadLine());
No, C# actually has real pointers, like C++, to raw memory. Because they are unsafe and you can crash your program with them, you can only use them inside unsafe
blocks.
Not much to add but I appreciate your dedication by making a real table
how do you even do that?
|Column A|Column B|Column C|
|---|---|---|
|a|b|c|
Constants
Constants are like variables except you can define their value only once. So technically, not variables.
Constants and variables…
— Elizabeth Comstock, Bioshock Infinite
To define a constant:
const <type> name = value;
Like:
const double pi = 3.1416;
Operators
Eh, operators.
Arithmetic Operators
+, -. *, /, … ah I already know them!
Relational Operators
==, !=. >, <, >=, etc.
Logical Operators
Operator | Description |
---|---|
&& | AND |
` | |
!(condition) | NOT |
Bitwise Operators
Operator | Name | Description |
---|---|---|
& | AND | Copies a bit from both operands. |
` | ` | OR |
^ | XOR | Copies a bit exclusively from either operands. |
~ | Complement Operator | Reverses bits (0 becomes 1 and vice versa). Good for converting negative numbers. |
<< | Left Shift | Pushes bits to the left by a number of bits. |
>> | Right Shift | Pushes bits to the right by a number of bits. |
Decision Making
if, if else, else if. if else can be replaced by ternary operator like so:
string str = (a >= b) ? "Good." : "Bad.";
Console.Write(str);
else if
, you would realize that it looks like a parallel circuit in electronics.Switch decision making
int num = value;
switch(num)
{
case 1:
code;
break;
case 2:
code;
break;
case 3:
code;
break;
default:
code;
break;
}
switch statement can also have multiple cases go to the same outcome like this:
int num = value;
switch(num)
{
case 1:
case 99:
code;
break;
case 2:
case 98:
code;
break;
case 3:
case 97:
code;
break;
case 0:
default:
code;
break;
}
I don’t think so. Though, we might use them in the future for packing a bunch of flag bits in a single int, which was used when the game was in C++, but so far there hasn’t been a need to do that in the C# version.
They are useful to manipulate data within individual bytes. Let’s say you wanted toggle the bit at position b
in my_byte
, you’d do my_byte ^ 1 << b
. If b
is 2 and my_byte
is 0b10101010
, you’d get 0b10101110
in this operation (1 << 2 is 0b00000100
).
As hhyyrylainen mentioned, it can be used to store or read flags in a header of some file format.
A program reading a file could do something like this (this is in C, going to probably look the same, but I’m just saying it just to be safe in case the code would look different):
// Do stuff if bit 6 is set.
if (flags & 1 << 6) // or (flags & 0b01000000)
{
do_stuff()
}
Loops
While Loops
while (a < b)
{
code;
}
For Loops
for (i = 0; i < 6; i++)
{
code;
}
do…while Loops
do
{
code;
} while (a < b);
break Statement
break;
statement allows one to terminate a loop, generally when reaching a particular condition (if statement within a loop).continue Statement
continue;
statement skips the current iteration and goes to the next one.When you don’t know how many times you are looping, or the condition is a boolean variable, they are the only loop type that makes sense.
I built the calculator.
calculator
program.cs
using System;
namespace Calculator
{
class Program
{
static void Main(string[] args)
{
double num1, num2;
num1 = 0.0;
num2 = 0.0;
while(true)
{
Console.WriteLine("This is a calculator. Type 'list' to see all possible operations.");
string choice = Console.ReadLine();
switch(choice)
{
case "1":
Console.WriteLine("You have chosen 'Addition'.\nPlease enter the first number if necessary...");
/*The user has to enter the numbers first, then the code will take care of the operation.
If the user has not cleared the previous result, they won't have to enter the first number.*/
Arithmetics addition = new Arithmetics();
num1 = (num1 == 0.0) ? Convert.ToDouble(Console.ReadLine()) : num1; // if num1 has been cleared, enter the number. Otherwise, keep the same value.
Console.WriteLine("Now, please enter the second number...");
num2 = Convert.ToDouble(Console.ReadLine());
addition.Addition(num1, num2);
Console.WriteLine("The result is {0}", addition.result);
num1 = addition.result;
continue;
case "2":
Console.WriteLine("You have chosen 'Subtraction'.\nPlease enter the first number if necessary...");
Arithmetics subtraction = new Arithmetics();
num1 = (num1 == 0.0) ? Convert.ToDouble(Console.ReadLine()) : num1;
Console.WriteLine("Now, please enter the second number...");
num2 = Convert.ToDouble(Console.ReadLine());
subtraction.Subtraction(num1, num2);
Console.WriteLine("The result is {0}", subtraction.result);
num1 = subtraction.result;
continue;
case "3":
Console.WriteLine("You have chosen 'Multiplication'.\nPlease enter the first number if necessary...");
Arithmetics multiplication = new Arithmetics();
num1 = (num1 == 0.0) ? Convert.ToDouble(Console.ReadLine()) : num1;
Console.WriteLine("Now, please enter the second number...");
num2 = Convert.ToDouble(Console.ReadLine());
multiplication.Multiplication(num1, num2);
Console.WriteLine("The result is {0}", multiplication.result);
num1 = multiplication.result;
continue;
case "4":
Console.WriteLine("You have chosen 'Division'.\nPlease enter the first number if necessary...");
Arithmetics division = new Arithmetics();
num1 = (num1 == 0.0) ? Convert.ToDouble(Console.ReadLine()) : num1;
Console.WriteLine("Now, please enter the second number...");
num2 = Convert.ToDouble(Console.ReadLine());
division.Division(num1, num2);
Console.WriteLine("The result is {0}", division.result);
num1 = division.result;
continue;
case "5":
Console.WriteLine("You have chosen 'Modulus'.\nPlease enter the first number if necessary...");
Arithmetics modulus = new Arithmetics();
num1 = (num1 == 0.0) ? Convert.ToDouble(Console.ReadLine()) : num1;
Console.WriteLine("Now, please enter the second number...");
num2 = Convert.ToDouble(Console.ReadLine());
modulus.Modulus(num1, num2);
Console.WriteLine("The result is {0}", modulus.result);
num1 = modulus.result;
continue;
case "list":
Console.WriteLine(" 1-Addition \n 2-Subtraction \n 3-Multiplication \n 4-Division \n 5-Modulus: Find the remainder of a division. \n clear-Clear the previous result. \n exit-Exit the program.");
continue;
case "clear":
num1 = 0.0;
Console.WriteLine("The result has been cleared.");
continue;
case "exit":
Console.WriteLine("Please press <Enter> to exit...");
Console.ReadKey();
break;
default:
Console.WriteLine("Wrong input. Please enter a valid input.");
continue;
}
break;
}
}
}
}
arithmetics.cs
using System;
namespace Calculator
{
class Arithmetics
{
public double result;
public double Addition(double number1, double number2)
{
result = number1 + number2;
return result;
}
public double Subtraction(double number1, double number2)
{
result = number1 - number2;
return result;
}
public double Multiplication(double number1, double number2)
{
result = number1 * number2;
return result;
}
public double Division(double number1, double number2)
{
result = number1 / number2;
return result;
}
public double Modulus(double number1, double number2)
{
result = number1 % number2;
return result;
}
}
}
Big brain
However, here’s an interesting message.
Microsoft (R) Visual C# Compiler version 4.8.4084.0
for C# 5
Copyright (C) Microsoft Corporation. All rights reserved.[justify]This compiler is provided as part of the Microsoft (R) .NET Framework, but only supports language versions up to C# 5, which is no longer the latest version. For compilers that support newer versions of the C# programming language, see Bing
It’s probably just the runtime. AFAIK there is a separate development tools you need to download. The Godot mono instructions go into more detail on how to get those development tools without getting visual studio. If you just get visual studio, it comes with everything. Due to the way the C# language is structured, it’s probably very annoying to use the command line to compile projects, so no one uses it directly.
Encapsulation
There are access specifiers for class data :
- public
- private (default)
- protected
- internal
- protected internal
private: Hides a member from other classes, making it accessible only within the same class.
protected: Restrains a member to be accessible only by the same class and its child.
internal: Extends the scope of a member to other classes within the same “application”.
Does it mean within the same namespace?
protected internal: Restricts the scope of a member to the same class and its children only provided that they are within the same “assembly”.
Methods
To define a method:
<access> <return_type> name(parameters)
{
code;
}
If there is nothing to return, just use void
.
public int GetArea(length, width)
{
return length * width;
}
r.GetArea(2, 7);
int a = 5;
int b = 6;
n.GetArea(a, b);
ref
keyword.public void swap(ref int x, ref int y) {...}
int a = 340;
int b = 566;
n.swap(ref a, ref b);
out
and it actually returns the parameter outside the method. So if you define the parameter x
as equal to 5 inside the method, you can modify another variable outside the class.public void getValue(out int x)
{
y = 5;
x = y;
}
...
int a;
n.getValue(out a);
/* a is now equal to 5 */
To be continued…