Programming/C Sharp: Difference between revisions
Brodriguez (talk | contribs) (Create page) |
Brodriguez (talk | contribs) (Add some notes) |
||
(12 intermediate revisions by the same user not shown) | |||
Line 2: | Line 2: | ||
It's used often in large, enterprise/business scale projects, due to having solid scaffolding for enforcing consistency through the project, which allows many people to work on a given project with less maintenance overhead. This is accomplished via things like required strong typing and good support for the [[interface class]] structure. | It's used often in large, enterprise/business scale projects, due to having solid scaffolding for enforcing consistency through the project, which allows many people to work on a given project with less maintenance overhead. This is accomplished via things like required strong typing and good support for the [[interface class]] structure. | ||
== Other == | |||
* Classes are always passes by reference. | |||
* Structs and value types (when not part of a class) are always passed by value. | |||
== Comments == | == Comments == | ||
Line 9: | Line 15: | ||
=== Block Comments === | === Block Comments === | ||
Because there is minimal difference in C# between inline and block comments, these are really only useful when declared above a class or function declaration line. | |||
This is because C# knows to treat this as documentation and adds special logic around it. For example, hovering over a class instantiation will display the block comment data for that class. | |||
/// This is a block comment. | /// This is a block comment. | ||
/// Comment line 2. | /// Comment line 2. | ||
/// Another block comment line. | /// Another block comment line. | ||
=== Block/Region Declaration === | |||
Regions are used for organizational purposes, and allow for code folding at the click of a button. To be useful, both the start and end must be declared. | |||
#region MyRegionName | |||
| |||
... | |||
| |||
#endregion MyRegionName | |||
== Variables == | |||
Variables are strongly typed in C#. That means that you must declare the type (bool, int, string, etc) as well as the variable name. | |||
=== Variable Definition === | |||
bool a_bool = true; | |||
bool b_bool = false; | |||
string my_var_1 = "This is "; | |||
string my_var_2 = "a string."; | |||
=== Variable Usage === | |||
Console.WriteLine("Printing variable values."); | |||
Console.WriteLine(a_bool); | |||
Console.WriteLine(b_bool); | |||
Console.WriteLine(my_var_1 + my_var_2); | |||
=== Variable Casting === | |||
Variables will be treated as the originally indicated type until a cast statement is used. | |||
For example, to convert a boolean to an int, use: | |||
bool a_bool = true; | |||
int converted_bool = Convert.ToInt32(a_bool); | |||
== If Statements == | |||
=== Basic If === | |||
if (x == y) | |||
{ | |||
// Logic if true. | |||
} | |||
=== Full If === | |||
if (x == y) | |||
{ | |||
// Logic if true. | |||
} else if ( x && (y || z) ) | |||
{ | |||
// Logic for "else if" true. | |||
} else | |||
{ | |||
// Logic for false. | |||
} | |||
=== Switch/Case Statements === | |||
switch (my_var) | |||
{ | |||
case "1": | |||
// Logic for case value of "1". | |||
break; | |||
case "a": | |||
// Logic for case value of "a". | |||
break; | |||
case "test": | |||
// Logic for case value of "test". | |||
break; | |||
default: | |||
// Logic for no match. | |||
break; | |||
} | |||
== Functions == | |||
Functions in C# are syntactically handled similarly to C, with a few modifications. The format is: | |||
<accessibility> <return_type> <function_name>(<args>) | |||
{ | |||
// Function logic here. | |||
} | |||
For example: | |||
public void MyFunc(int my_int, string my_string) | |||
{ | |||
// Function logic here. | |||
} | |||
=== Accessibility === | |||
Accessibility levels indicate what can and cannot access the given variable or function. The most types are as follows: | |||
{{ note | See [https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/keywords/accessibility-levels this link] to see the all levels in the Microsoft docs. }} | |||
* <code>public</code> - Anything can access it. | |||
* <code>protected</code> - This class and all inheriting children can access it. | |||
* <code>private</code> - Only this class can access it. Not even inheriting children have access. | |||
=== Return Type === | |||
The return type is exactly that. Aka, the type of the variable that the function returns on function exit. If a variable does not return anything, then the type of <code>void</code> type. | |||
== Basic Data structures == | |||
=== Arrays === | |||
Arrays are one of the most common data structures. See [[Arrays]] for more info. | |||
In C#, all indexes for a given array must hold the same data type. | |||
==== Declaring Arrays ==== | |||
Declare an array by specifying the type, followed by brackets, followed by the array name. | |||
string[] my_array; | |||
Then we can initialize the array by declaring the number of indexes. For example, to declare 4 indexes, use: | |||
my_array = new string[4]; | |||
If you want to initialize with pre-populated values, you can take it a step further with something like: | |||
my_array = new string[4] { "Index 0", "Index 1", "Some String Value", "Final Index" }; | |||
Finally, note that you can combine declaration and initialization into one line. | |||
==== Accessing Array Values ==== | |||
The syntax to access an array is as follows: | |||
// Update index 1. | |||
my_array[1] = "Test Index 1"; | |||
// Read index 1. | |||
Console.WriteLine(my_array[1]); | |||
To access all array indexes in order, use a standard for loop. | |||
for (int index = 0; index < my_array.Length; index++) | |||
{ | |||
Console.WriteLine(my_array[index]); | |||
} | |||
=== Dictionaries === | |||
Dictionaries can be incredibly powerful. See [[Dictionaries]] for more info. | |||
==== Declaring Dictionaries ==== | |||
Similarly to C# arrays, once the data type is declared in a dictionary, it cannot be changed. However, note that "keys" and "values" in a dictionary can each hold a different, unique data type. | |||
For example, to declare a dictionary of string keys and int values, use: | |||
Dictionary<string, int> my_dict = new Dictionary<string, int>(); | |||
==== Accessing Dictionary Values ==== | |||
To set new key-value pairs, use: | |||
my_dict.Add(<key>, <value>); | |||
To read an existing key-value pair, use: | |||
my_dict[<key>] | |||
To update an existing key-value pair, use: | |||
my_dict[<key>] = <updated_value>; | |||
To remove an existing key-value pair, use: | |||
my_dict.Remove(<key>); | |||
==== Example ==== | |||
Here's an example of a dictionary for a hypothetical business trying to track count of items sold. | |||
// Create our dict. | |||
Dictionary<string, int> product_sold = new Dictionary<string, int>(); | |||
| |||
// Add initial values. | |||
product_sold.Add("Ice Cream", 50); | |||
product_sold.Add("Burgers", 56); | |||
product_sold.Add("Pizza", 102); | |||
| |||
// Sold another pizza. Update value. | |||
product_sold["Pizza"] += 1; | |||
=== Structs === | |||
Structs are essentially a means to group sets of variables together. They are handled very similarly to C structs. | |||
Unlike C# arrays or dicts, structs are able to combine as many variable types as desired. | |||
==== Struct Declaration ==== | |||
First, declare the struct type itself.<br> | |||
If familiar with classes, this will look a lot like declaring a simplified class that has only class variables and nothing else. | |||
struct MyStructObject | |||
{ | |||
public bool test_bool; | |||
public int test_int; | |||
public string test_string; | |||
} | |||
Once the struct type is declared, we can create instances of it to use. | |||
MyStructObject a_struct = new MyStructObject(); | |||
==== Accessing Struct Items ==== | |||
Structs are basically containers for holding the associated variables within. Thus, we can easily access the contained variables with syntax that should look fairly familiar. | |||
// Set or update struct values. | |||
a_struct.test_bool = true; | |||
a_struct.test_int = 5; | |||
a_struct.test_string = "My test string"; | |||
| |||
// Print struct values. | |||
Console.WriteLine(a_struct.test_bool); | |||
Console.WriteLine(a_struct.test_int); | |||
Console.WriteLine(a_struct.test_string); | |||
== Classes == | |||
A class can be thought of as a struct that can have functions built into it. | |||
Classes are generally defined in new, separate files. A good rule of thumb is to only include multiple classes in one file if they are nested, inner subclasses within the first class. | |||
{{ note | In C#, class variables and methods are often called with <code>this.<value></code>, to help differentiate between local and class level values. However, this is optional and will not always be followed. }} | |||
=== Class Variables === | |||
To declare class level variables, declare the variable name and type in the class, but don't assign to it. | |||
For organization, it's recommended to do this at the very top of the class, and enclose it within a region. | |||
class MyClass | |||
{ | |||
#region Variables | |||
| |||
bool test_bool; | |||
int test_int; | |||
string test_string; | |||
| |||
#endregion Variables | |||
| |||
... | |||
} | |||
=== Constructor === | |||
A constructor is essentially the logic that's ran on class instantiation. | |||
To declare a constructor, declare a method with the same name as the class and <code>public</code> accessibility. | |||
If your class needs to be able to handle multiple possible sets of passed arguments, then create one constructor for each. | |||
For example, this is a constructor for a class that takes 0 arguments. | |||
class MyClass | |||
{ | |||
... | |||
| |||
public MyClass() | |||
{ | |||
// Constructor logic here. | |||
} | |||
| |||
... | |||
} | |||
=== Properties === | |||
Properties are a "safer" way to read (get) and update (set) class variables. | |||
Effectively, properties are functions that handle a single variable, and allow for custom logic to clean/validate your variable before saving it to the class or returning it for use outside of the class. | |||
Minimum property syntax (to both set and get) is as follows: | |||
class MyClass | |||
{ | |||
#region Variables | |||
| |||
string test_string; | |||
| |||
#endregion Variables | |||
| |||
... | |||
| |||
public string TestString | |||
{ | |||
get { return this.test_string; } | |||
set { this.test_string = value; } | |||
} | |||
| |||
... | |||
} | |||
If we want to expand this to show how it can be useful, we can validate our value first. | |||
class MyClass | |||
{ | |||
#region Variables | |||
| |||
string test_string; | |||
| |||
#endregion Variables | |||
| |||
... | |||
| |||
public string TestString | |||
{ | |||
get | |||
{ | |||
// First check if our string is a known bad value. | |||
if (this.test_string == "I'm an invalid value, ohno!") | |||
{ | |||
// Invalid value detected! Return something else as a fallback. | |||
return "Default string value." | |||
} else | |||
{ | |||
// If we got here, then the string is valid. Return that. | |||
return this.test_string; | |||
} | |||
} | |||
set | |||
{ | |||
// Check if our provided value is valid before setting. | |||
// In this case, we simply make sure it's 3 characters or greater. | |||
if (this.test_string.Length > 2) | |||
{ | |||
this.test_string = value; | |||
} | |||
} | |||
} | |||
| |||
... | |||
} | |||
=== Class Functions === | |||
Class functions are declared and handled the same way as any other C# function. See functions section. |
Latest revision as of 19:54, 22 April 2023
C# is a higher level version of C. It was designed by Microsoft, and for the longest time, was generally only supported on Windows.
It's used often in large, enterprise/business scale projects, due to having solid scaffolding for enforcing consistency through the project, which allows many people to work on a given project with less maintenance overhead. This is accomplished via things like required strong typing and good support for the interface class structure.
Other
- Classes are always passes by reference.
- Structs and value types (when not part of a class) are always passed by value.
Comments
Inline Comments
// This is an inline comment.
Block Comments
Because there is minimal difference in C# between inline and block comments, these are really only useful when declared above a class or function declaration line.
This is because C# knows to treat this as documentation and adds special logic around it. For example, hovering over a class instantiation will display the block comment data for that class.
/// This is a block comment. /// Comment line 2. /// Another block comment line.
Block/Region Declaration
Regions are used for organizational purposes, and allow for code folding at the click of a button. To be useful, both the start and end must be declared.
#region MyRegionName ... #endregion MyRegionName
Variables
Variables are strongly typed in C#. That means that you must declare the type (bool, int, string, etc) as well as the variable name.
Variable Definition
bool a_bool = true; bool b_bool = false; string my_var_1 = "This is "; string my_var_2 = "a string.";
Variable Usage
Console.WriteLine("Printing variable values."); Console.WriteLine(a_bool); Console.WriteLine(b_bool); Console.WriteLine(my_var_1 + my_var_2);
Variable Casting
Variables will be treated as the originally indicated type until a cast statement is used.
For example, to convert a boolean to an int, use:
bool a_bool = true; int converted_bool = Convert.ToInt32(a_bool);
If Statements
Basic If
if (x == y) { // Logic if true. }
Full If
if (x == y) { // Logic if true. } else if ( x && (y || z) ) { // Logic for "else if" true. } else { // Logic for false. }
Switch/Case Statements
switch (my_var) { case "1": // Logic for case value of "1". break; case "a": // Logic for case value of "a". break; case "test": // Logic for case value of "test". break; default: // Logic for no match. break; }
Functions
Functions in C# are syntactically handled similarly to C, with a few modifications. The format is:
<accessibility> <return_type> <function_name>(<args>) { // Function logic here. }
For example:
public void MyFunc(int my_int, string my_string) { // Function logic here. }
Accessibility
Accessibility levels indicate what can and cannot access the given variable or function. The most types are as follows:
public
- Anything can access it.protected
- This class and all inheriting children can access it.private
- Only this class can access it. Not even inheriting children have access.
Return Type
The return type is exactly that. Aka, the type of the variable that the function returns on function exit. If a variable does not return anything, then the type of void
type.
Basic Data structures
Arrays
Arrays are one of the most common data structures. See Arrays for more info.
In C#, all indexes for a given array must hold the same data type.
Declaring Arrays
Declare an array by specifying the type, followed by brackets, followed by the array name.
string[] my_array;
Then we can initialize the array by declaring the number of indexes. For example, to declare 4 indexes, use:
my_array = new string[4];
If you want to initialize with pre-populated values, you can take it a step further with something like:
my_array = new string[4] { "Index 0", "Index 1", "Some String Value", "Final Index" };
Finally, note that you can combine declaration and initialization into one line.
Accessing Array Values
The syntax to access an array is as follows:
// Update index 1. my_array[1] = "Test Index 1"; // Read index 1. Console.WriteLine(my_array[1]);
To access all array indexes in order, use a standard for loop.
for (int index = 0; index < my_array.Length; index++) { Console.WriteLine(my_array[index]); }
Dictionaries
Dictionaries can be incredibly powerful. See Dictionaries for more info.
Declaring Dictionaries
Similarly to C# arrays, once the data type is declared in a dictionary, it cannot be changed. However, note that "keys" and "values" in a dictionary can each hold a different, unique data type.
For example, to declare a dictionary of string keys and int values, use:
Dictionary<string, int> my_dict = new Dictionary<string, int>();
Accessing Dictionary Values
To set new key-value pairs, use:
my_dict.Add(<key>, <value>);
To read an existing key-value pair, use:
my_dict[<key>]
To update an existing key-value pair, use:
my_dict[<key>] = <updated_value>;
To remove an existing key-value pair, use:
my_dict.Remove(<key>);
Example
Here's an example of a dictionary for a hypothetical business trying to track count of items sold.
// Create our dict. Dictionary<string, int> product_sold = new Dictionary<string, int>(); // Add initial values. product_sold.Add("Ice Cream", 50); product_sold.Add("Burgers", 56); product_sold.Add("Pizza", 102); // Sold another pizza. Update value. product_sold["Pizza"] += 1;
Structs
Structs are essentially a means to group sets of variables together. They are handled very similarly to C structs.
Unlike C# arrays or dicts, structs are able to combine as many variable types as desired.
Struct Declaration
First, declare the struct type itself.
If familiar with classes, this will look a lot like declaring a simplified class that has only class variables and nothing else.
struct MyStructObject { public bool test_bool; public int test_int; public string test_string; }
Once the struct type is declared, we can create instances of it to use.
MyStructObject a_struct = new MyStructObject();
Accessing Struct Items
Structs are basically containers for holding the associated variables within. Thus, we can easily access the contained variables with syntax that should look fairly familiar.
// Set or update struct values. a_struct.test_bool = true; a_struct.test_int = 5; a_struct.test_string = "My test string"; // Print struct values. Console.WriteLine(a_struct.test_bool); Console.WriteLine(a_struct.test_int); Console.WriteLine(a_struct.test_string);
Classes
A class can be thought of as a struct that can have functions built into it.
Classes are generally defined in new, separate files. A good rule of thumb is to only include multiple classes in one file if they are nested, inner subclasses within the first class.
this.<value>
, to help differentiate between local and class level values. However, this is optional and will not always be followed. Class Variables
To declare class level variables, declare the variable name and type in the class, but don't assign to it.
For organization, it's recommended to do this at the very top of the class, and enclose it within a region.
class MyClass { #region Variables bool test_bool; int test_int; string test_string; #endregion Variables ... }
Constructor
A constructor is essentially the logic that's ran on class instantiation.
To declare a constructor, declare a method with the same name as the class and public
accessibility.
If your class needs to be able to handle multiple possible sets of passed arguments, then create one constructor for each.
For example, this is a constructor for a class that takes 0 arguments.
class MyClass { ... public MyClass() { // Constructor logic here. } ... }
Properties
Properties are a "safer" way to read (get) and update (set) class variables.
Effectively, properties are functions that handle a single variable, and allow for custom logic to clean/validate your variable before saving it to the class or returning it for use outside of the class.
Minimum property syntax (to both set and get) is as follows:
class MyClass { #region Variables string test_string; #endregion Variables ... public string TestString { get { return this.test_string; } set { this.test_string = value; } } ... }
If we want to expand this to show how it can be useful, we can validate our value first.
class MyClass { #region Variables string test_string; #endregion Variables ... public string TestString { get { // First check if our string is a known bad value. if (this.test_string == "I'm an invalid value, ohno!") { // Invalid value detected! Return something else as a fallback. return "Default string value." } else { // If we got here, then the string is valid. Return that. return this.test_string; } } set { // Check if our provided value is valid before setting. // In this case, we simply make sure it's 3 characters or greater. if (this.test_string.Length > 2) { this.test_string = value; } } } ... }
Class Functions
Class functions are declared and handled the same way as any other C# function. See functions section.