Revision Difference
From_Lua_to_CSharp#530481
<cat>Code.Misc</cat>
<title>From Lua to C#</title>
⤶
# What is this guide⤶
⤶
This is meant to give an idea of some major differences between Lua and C#.
⤶
This isn't a complete guide to C# and it doesn't cover many of the topics. It's meant to be brief, simple and illustrative. If you want to learn C# in more depth, you can use the [official C# language reference](https://docs.microsoft.com/en-us/dotnet/csharp/).⤶
⤶
<warning>⤶
This page won't teach you how to use C#. In order to effectively use C#, please check out [this page](https://wiki.facepunch.com/sbox/Learning_Resources).
</warning>⤶
⤶
# What is this page⤶
This is meant to give an idea of some major differences between Lua and C#.⤶
⤶
This isn't a complete guide to C# and it doesn't cover many of the topics. ⤶
It's meant to be **brief, simple and illustrative**.⤶
⤶
If you want to learn C# in more depth, please check out [this page](https://wiki.facepunch.com/sbox/Learning_Resources).⤶
# Terminology
## Tables ⤶
C# has no tables. Although they are not exactly a replacement, in most cases you will use *classes* instead.
## Tables⤶
Tables do not exist in C#: although they are not exactly a replacement, in most cases you will use *classes* instead.
## Variables
In C# only variables defined in methods are called so. If it's defined in a class it is called a *field* instead.
In C# only variables defined in methods are called so.
If it's defined in a class it is called a *field* instead.⤶
Example:
```csharp
public class Player
{
private int _health; // field
public void Damage(int amount, int times)
public void Damage( int amount, int times )
{
var totalAmount = amount * times; // variable
}
}
```
## Functions
In C# they are called *methods* instead.
⤶
⤶
# Comments⤶
⤶
```lua⤶
⤶
# Comments⤶
```lua⤶
-- Lua comments start with two minus signs
--[[
Lua multiline comment
example
--]]
```
```csharp
// C# comments start with two slashes, like most other languages
/*
C# multiline comment
example
*/
```
# Global Variables⤶
# Typing System⤶
Lua uses dynamic typing. That means variables do not have a specific type and can be assigned any type of value.⤶
```lua
-- you can define globals anywhere in Lua⤶
globalVar = 100⤶
```⤶
⤶
C# has no global fields. But in most cases you can use static fields instead:⤶
⤶
```csharp⤶
public class MyClass⤶
{⤶
// in C# globals need to be in a class⤶
public static int StaticField = 100;⤶
}⤶
⤶
// you can call the field by using MyClass.StaticField now.⤶
```⤶
⤶
Keep in mind that static fields are often easily abused and should be avoided as they make it harder to manage state correctly. In other words this will make your code more prone to bugs.⤶
⤶
# Type System⤶
Lua is a so called dynamic typed language. That means variables do not have a specific type and can be assigned any type of value.⤶
```lua⤶
-- variables in Lua don't have a static type and can store any data
local a = 100
a = "Hello"
a = function() print( "Hi" ) end
```
C# is a static typed language. That means a variable has a known type that is set during its declaration. Only compatible values can be assigned. For example, you cannot assign a string value to an int variable.
C# uses static typing. That means a variable has a known type that is set during its declaration. Only compatible values can be assigned. For example, you cannot assign a string value to an int variable.
```csharp
int a = 100;
a = "Hello"; // error: can't assign a string to an int
```
There are multiple built in data types in C#. You can view all of them [here](https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/builtin-types/built-in-types)
You can also use the `var` keyword for the type to be inferred. This is considered bad practice to be used constantly and should only be used when defining explicit types.
```csharp
var veh = new Vehicle(); // veh will have the type of Vehicle
```
⤶
# Type conversion⤶
⤶
```lua⤶
⤶
## Type Conversion⤶
```lua⤶
local a = 123
local b = tostring( a ) -- "123"
local c = tonumber( b ) -- 123
```
```csharp
int a = 123;
string b = a.ToString(); // "123"
int c = int.Parse( b ); // 123, will throw an exception if 'b' isn't int-ish
// operator 'as' converts an object reference or returns 'null' on failure
Vehicle vehicle = new Car() as Vehicle; // downcast Car reference to Vehicle
Car car = vehicle as Car; // upcast Vehicle reference to Car
```⤶
⤶
# Numbers⤶
⤶
```lua⤶
local a = 100⤶
a = 5.5⤶
a = -300.1⤶
```⤶
⤶
```csharp⤶
// integer types are sbyte, byte, short, ushort, int, uint, long, ulong⤶
int a = -300;⤶
uint b = 333333;⤶
⤶
// decimal types are float, double, decimal⤶
double d = -500.888;⤶
```
# Strings
⤶
```lua⤶
```lua⤶
local str = "Hello"
local str2 = 'Hello2'
local multilineStr = [[
Hello
Multiline
]]
print( #str ) -- 5, string length
local concated = "I have " .. 3 .. " apples!"
local formatted = string.format( "I have %d apples!", 3 )
```
```csharp
string str = "Hello";
char singleChar = 'a'; // single quotes are for a single character, not a string
string multilineStr = @"⤶
Hello⤶
Multiline⤶
"; // putting '@' before a string literal makes it a verbatim string literal⤶
⤶
Console.WriteLine( str.Length ); // 5, string length⤶
⤶
string concated = "I have " + 3 + " apples!";⤶
⤶
// {0} and {1} here correspond to the order of value arguments⤶
// argument number 0 is '3' and argument number 1 is '2'⤶
string formatted = string.Format( "I have {0} apples and {1} oranges!", 3, 2 );⤶
⤶
// putting '$' before a string allows interpolating values into it using '{value}'⤶
int numApples = 3;⤶
⤶
string interpolated = $"I have {numApples} apples!"; ⤶
⤶
// While there are many ways to concatenate a string, this is the preferred method.⤶
// putting '$' before a string allows interpolating values into it using '{value}'⤶
int appleCount = 3;⤶
string interpolated = $"I have {appleCount} apples!"; ⤶
```
⤶
# Collections⤶
⤶
```lua⤶
local stuff = {⤶
1, 2, 3,⤶
"Oh", "Hi", "Mark",⤶
{ myFunc = function() end }⤶
}⤶
⤶
local arr = { 'a', 'b', 'c' }⤶
⤶
print( arr[1] ) -- will print 'a' since array indices in Lua start from 1⤶
```⤶
⤶
```csharp⤶
int[] numbers = new int[3] { 1, 2, 3 };⤶
List<string> strings = new List<string> { "Oh", "Hi", "Mark" };⤶
Dictionary<string, Action> functions = new Dictionary<string, Action>⤶
{⤶
["myFunc"] = () => { }⤶
};⤶
⤶
string[] arr = new string[3] { "a", "b", "c" };⤶
⤶
Console.WriteLine(arr[1]); // will print "b" since array indices in C# like most languages start from 0⤶
```⤶
# Loops
⤶
```lua⤶
```lua⤶
for i = 1, 10, 2 do
print( i ) -- 1, 3, 5, 7, 9
end
local a = 10
repeat
print( a ) -- 10, 8, 6, 4, 2, 0
a = a - 2
until a < 0
local t = {
a = 5,
b = 10,
c = 15
}
for k, v in pairs( t ) do
print( k .. ' = ' .. v ) -- b = 10, a = 5, c = 15
end
```
```csharp
for ( int i = 1; i < 10; i += 2 )
{
Console.WriteLine( i ); // 1, 3, 5, 7, 9
}
int a = 10;
⤶
do⤶
do⤶
{
Console.WriteLine( a ); // 10, 8, 6, 4, 2, 0
a -= 2;
} while ( a >= 0 );
Dictionary<string, int> t = new Dictionary<string, int>
{
{ "a", 5 },
{ "b", 10 },
{ "c", 15 },
};
foreach (KeyValuePair<string, int> kv in t)
foreach ( KeyValuePair<string, int> kv in t )
{
Console.WriteLine( $"{kv.Key} = {kv.Value}" ); //a = 5, b = 10, c = 15
}⤶
```⤶
⤶
# Member Access⤶
⤶
In Lua anything is accessible from anywhere as long as you have a reference.⤶
⤶
```lua⤶
-- myFile.lua⤶
myTable = {⤶
field = 100⤶
}⤶
```⤶
⤶
```lua⤶
-- otherFile.lua⤶
print( myTable.field ) -- 100⤶
```⤶
⤶
In C# things can be **public**, **private**, **protected** and **internal**.⤶
⤶
```csharp⤶
// MyClass.cs⤶
public class MyClass⤶
{⤶
public static void PublicMethod() { ... }⤶
protected static void ProtectedMethod() { ... }⤶
private static void PrivateMethod() { ... }⤶
}⤶
```⤶
⤶
```csharp⤶
// OtherClass.cs⤶
public class OtherClass : MyClass⤶
{⤶
public static void Test()⤶
{⤶
MyClass.PublicMethod(); // OK⤶
MyClass.ProtectedMethod(); // we inherit from MyClass so OK⤶
MyClass.PrivateMethod(); // error: PrivateMethod is private⤶
}⤶
}
```