From AS3 to C#, Part 14: Built-in Types and Variables
The language’s built-in types should be trivial, but they’re not. There are a lot of little details overlooked by many programmers. Today’s article continues the series by looking at subtleties found in seemingly-obvious language features like strings and integers. Read on to learn some tricks!
Table of Contents
- From AS3 to C#, Part 1: Class Basics
- From AS3 to C#, Part 2: Extending Classes and Implementing Interfaces
- From AS3 to C#, Part 3: AS3 Class Parity
- From AS3 to C#, Part 4: Abstract Classes and Functions
- From AS3 to C#, Part 5: Static Classes, Destructors, and Constructor Tricks
- From AS3 to C#, Part 6: Extension Methods and Virtual Functions
- From AS3 to C#, Part 7: Special Functions
- From AS3 to C#, Part 8: More Special Functions
- From AS3 to C#, Part 9: Even More Special Functions
- From AS3 to C#, Part 10: Alternatives to Classes
- From AS3 to C#, Part 11: Generic Classes, Interfaces, Methods, and Delegates
- From AS3 to C#, Part 12: Generics Wrapup and Annotations
- From AS3 to C#, Part 13: Where Everything Goes
- From AS3 to C#, Part 14: Built-in Types and Variables
- From AS3 to C#, Part 15: Loops, Casts, and Operators
- From AS3 to C#, Part 16: Lambdas and Delegates
- From AS3 to C#, Part 17: Conditionals, Exceptions, and Iterators
- From AS3 to C#, Part 18: Resource Allocation and Cleanup
- From AS3 to C#, Part 19: SQL-Style Queries With LINQ
- From AS3 to C#, Part 20: Preprocessor Directives
- From AS3 to C#, Part 21: Unsafe Code
- From AS3 to C#, Part 22: Multi-Threading and Miscellany
- From AS3 to C#, Part 23: Conclusion
Let’s start with the basics of variables, which has one twist in C#. Here’s how they look in AS3 when given a type (highly recommended):
var x:int; // default value var x:int = 33; // assigned value
Or without a type (if you must):
var x; // undefined var x = 33; // assigned value
In C#, you put the type first:
int x; // default value int x = 33; // assigned value
Or you can use var
if the compiler can figure out the type. This means you have to assign a value when you declare the variable.
var x = 33;
Using var
just means that the compiler gives the variable a type, not that it has the untyped (*
) type like in AS3. This means the type can’t change:
var x = 33; x = "hello"; // compiler error
Really, var
is just a convenience. You should choose to use it based on stylistic preferences only. Similarly, dynamic
foregoes compile-time type checking in favor of run-time type checking like you’d get with AS3’s untyped (*
) type:
dynamic x = 33; x = "hello"; // OK
With that out of the way, let’s start talking about types by discussing the integers. In AS3, we had only two: int
(32-bit signed) and uint
(32-bit unsigned). In C#, we have many more!
Bits | Signed | Unsigned |
---|---|---|
8 | sbyte |
byte |
16 | short |
ushort |
32 | int |
uint |
64 | long |
ulong |
All these types give us a lot of flexibility to optimize for memory consumption. The 64-bit variants also give us the ability to store numbers larger than AS3’s 32-bit uint
would allow without dangerously treading into Number
territory and potentially suffering errors due to the lack of precision.
If you want to use an int
literal in AS3, you have two options:
10 // decimal 0xABCD or 0xabcd // hexadecimal
In C# there are five options, mostly to cover the unsigned and long variants:
10 // decimal, first of int then uint then long then ulong 0xABCD or 0xabcd // hexadecimal, first of int then uint then long then ulong 10u or 10U // decimal, smallest of uint then ulong 10l or 10L // decimal, long then ulong 10UL or 10Ul or 10uL or 10ul or 10LU or 10Lu or 10lU or 10lu // ulong
Now for floating-point values. AS3 has only one—Number
—and it stores a 64-bit value. The literal values are very straightforward:
10.2
C# has two floating-point types: float
for 32-bit values and double
for 64-bit values. You can use the same literal values or explicitly specify type you want:
10.2 // double 10.2f or 10.2F // float 10.2d or 10.2D // double
Now for booleans. In AS3, you use the Boolean
type with the true
and false
literals. In C#, you use the bool
type with the true
and false
literals. Other than the type’s name, everything is the same.
Decimals are a whole new type to C# that AS3 doesn’t have. They are like float
and double
, but use 128-bits to store values with higher precision in a smaller range. This makes it useful for financial calculations where the poor precision of float
and double
is unacceptable. You can use these with the decimal
type and the m
suffix for literals:
10.2m or 10.2M // decimal
Characters are also a new type for AS3 programmers. A char
is like a one-character string without any overhead. It’s just stored as a single 16-bit integer. The literals for it include a lot of special cases:
'A' // single, simple character '\uABCD' // Unicode value '\xABCD' // hexadecimal value '\'' // single quote '\"' // double quote '\\' // backslash '\0' // nul '\a' // alert '\b' // backspace '\f' // form feed '\n' // newline '\r' // carriage return '\t' // horizontal tab '\v' // vertical tab
Strings are not new to AS3 programmers. The String
type and double quotes literals is a mainstay of almost every app:
"hello" // simple string "two \n lines" // string with a special character
C#, likewise, has the string
type and the double quotes literal. However, it also has quite a few more kinds of literals. Most of these are to handle all the special characters seen above in the char
examples.
"hello" // string "two \n lines" // string with a special character @"two \n lines" // string where special characters are ignored @"say ""hi"", John" // use quotes and ignore special characters // multi-line string @"multi line string"
Lastly, there are a few special cases. In AS3, Object
is the base type for everything but undefined
. You can create a plain object that holds arbitrary key-value pairs using the curly brace syntax:
// plain Object with keys "first", "last" // and values "Jackson", "Dunstan" { first:"Jackson", last:"Dunstan" }
C# has a similar type: object
. It’s the base type for everything and has a similar kind of literal:
// plain Object with keys "first", "last" // and values "Jackson", "Dunstan" new { first = "Jackson", last = "Dunstan" }
Next is the void
type, which has the same name in both languages. It serves the same function in both languages, too. It’s only used to indicate that a function doesn’t have a return value. That means you can’t have a variable, parameter, field, or anything else with the void
type.
All of the C# types can be made “nullable”. This means that they can have the value null
assigned to them. It works like this:
int x = null; // compiler error int? x = null; // x is "nullable" so this is OK x = 33; // x can be used like any other integer
AS3 has no concept of “nullable types”, so you’d need to resort to the *
type instead and give up all type safety.
Lastly, it should be mentioned that all of these types—even void and nullable types
—are actually just synonyms for types in C#’s System
namespace:
Keyword | Class |
---|---|
byte |
System.Byte |
sbyte |
System.SByte |
short |
System.Int16 |
ushort |
System.Uint16 |
int |
System.Int32 |
uint |
System.UInt32 |
long |
System.Int64 |
ulong |
System.Uint64 |
decimal |
System.Decimal |
float |
System.Single |
double |
System.Double |
bool |
System.Boolean |
char |
System.Char |
string |
System.String |
object |
System.Object |
void |
System.Void |
T? |
System.Nullable<T> |
The following side-by-side code snippets summarize all of these types and variable syntax:
//////// // C# // //////// // Explicitly-typed variable int x = 3; // Implicitly-typed variable var x = 3; // Variable that can change its type dynamic x = 3; x = "hello"; // 8-bit signed integer sbyte x; // 8-bit unsigned integer byte x; // 16-bit signed integer short x; // 16-bit unsigned integer ushort x; // 32-bit signed integer int x = 3; // decimal int x = 0x3; // hexadecimal // 32-bit unsigned integer uint x = 3U; // explicitly unsigned // 64-bit signed integer long x = 3L; // explicitly long // 64-bit unsigned integer ulong x = 3ULU; // explicitly long and unsigned // 32-bit float float x = 3.3f; // explicitly float // 64-bit float double x = 3.3; // implicitly double double x = 3.3d; // explicitly double // 128-bit decimal decimal x = 3.3m; // 16-bit character char x = 'A'; // single, simple character char x = '\uABCD'; // Unicode value char x = '\xABCD'; // hexadecimal value char x = '\''; // single quote char x = '\"'; // double quote char x = '\\'; // backslash char x = '\0'; // nul char x = '\a'; // alert char x = '\b'; // backspace char x = '\f'; // form feed char x = '\n'; // newline char x = '\r'; // carriage return char x = '\t'; // horizontal tab char x = '\v'; // vertical tab // String string x = "hello"; // simple string var x:String = "two \n lines"; // string with a special character var x:String = @"two \n lines"; // string where special characters are ignored var x:String = @"say ""hi"", John"; // use quotes and ignore special characters var x:String = @"multi line string"; // multi-line string // Anonymous object object x = new { first = "Jackson", last = "Dunstan" }; // Nullable type int? x = null; x = 3;
///////// // AS3 // ///////// // Explicitly-typed variable var x:int = 3; // Implicitly-typed variable // {unavailable in AS3} // Variable that can change its type var x = 3; x = "hello"; // or... var x:* = 3; x = "hello"; // 8-bit signed integer // {unavailable in AS3} // 8-bit unsigned integer // {unavailable in AS3} // 16-bit signed integer // {unavailable in AS3} // 16-bit unsigned integer // {unavailable in AS3} // 32-bit signed integer var x:int = 3; // decimal var x:int = 0x3; // hexadecimal // 32-bit unsigned integer var x:uint = 3; // explicitly unsigned - unavailable in AS3 // 64-bit signed integer // {unavailable in AS3} // 64-bit unsigned integer // {unavailable in AS3} // 32-bit float // {unavailable in AS3} // 64-bit float // {unavailable in AS3} // 128-bit decimal // {unavailable in AS3} // 16-bit character // {unavailable in AS3} // String var x:String = "hello"; // simple string var x:String = "two \n lines"; // string with a special character // string where special characters are ignored - unavailable in AS3 // use quotes and ignore special characters - unavailable in AS3 // multi-line string - unavailable in AS3 // Anonymous object var x:* = { first = "Jackson", last = "Dunstan" }; // Nullable type - only untyped (*) available var x:* = null; x = 3;
This wraps up variables and basic types in C#. Next week we’ll continue with more of the kind of code you can put in your functions. Stay tuned!
Spot a bug? Have a question or suggestion? Post a comment!
#1 by taraa on June 12th, 2015
Hello.
How to work with a variable
as3 =
c# (unity) ?? (print (???))
#2 by jackson on June 12th, 2015
You’d write almost exactly the same code with C#:
#3 by taraa on June 14th, 2015
thank you, just ask if the object or Object x.first MonoDevelop knocks error – Type `object ‘does not contain a definition for` first’ and no extension method `first ‘of type` object’ could be found (are you missing a using directive or an assembly reference?)
#4 by jackson on June 14th, 2015
Unlike AS3 where
{}
is an untypedobject
that’s like a key-value map, C# actually creates class like any other behind the scenes. The class doesn’t have a name that you can type in because it’s created by the compiler, but it is still a class. When you use thevar
keyword, as in my example, the type of the variable is whatever type you assign it. Since you’re assigning it a class instance like any other, the compiler knows thatfirst
andlast
are fields of it but, for example,age
is not. If, however, you give the variable anobject
type, then you can only use it like anobject
. Check out the docs forobject
and you definitely won’t seefirst
orlast
.In short, always assign these to a
var
variable.#5 by taraa on June 24th, 2015
it helped, but only if the variable in the function, and if so:
// Type `object’ does not contain a definition for `sa’ and no extension method `sa’ of type `object’ could be found (are you missing a using directive or an assembly reference?)
#6 by jackson on June 24th, 2015
This is a similar issue to the one above where you set the type of the variable to
object
. When youprint
thesa
field, the compiler looks at the type ofparamCollide
and sees that it’s just a plainobject
. You get that error becauseobject
doesn’t have ansa
field.However, there is a workaround for cases like these to retrieve the type. You can cast from
object
to the anonymous class using a helper function:Just make sure that when you cast you’ve listed all of the fields and they have the right types or the cast will fail.
#7 by bennett on September 14th, 2016
print(paramColide(.sa); compiler error. also if paramCollide is still a member field of type object, this still wouldn’t work.
#8 by jackson on September 14th, 2016
You’re right, something happened to the comment on that line. In any case, check out this followup article for more on the subject.