Variables & Basic Types
java1-2 drew a hard line: eight built-in primitives, everything else a reference type, no way for a programmer to add to either side. C# keeps the same two-category split — but genuinely lets you choose which side a new type belongs on.
Value Types vs. Reference Types
A value type holds its data directly — assigning or passing it copies the actual data. A reference type holds a reference to data stored elsewhere — assigning or passing it copies the reference, not the underlying data. This is C#'s own version of java1-2's primitive-vs-reference split, but with a genuine structural difference: in Java, only the eight built-in primitives are ever value-like — every programmer-defined type is automatically a reference type, no exceptions. In C#, a programmer can define a brand-new value type of their own.
struct vs. class
struct declares a value type; class declares a reference type — otherwise, the two look almost identical to write. This is the real, structural choice java1-4's own classes never offered: in Java, every custom type is unconditionally a reference type, full stop.
Built-in Types Are Just Structs
Here's the real reveal: int, double, and bool aren't magic keywords divorced from the type system — they're built-in aliases for real structs (System.Int32, System.Double, System.Boolean). Because they're genuinely structs, they can call methods directly, no wrapping required. This is a real, structural contrast with java1-2's own primitives, which aren't objects at all — Java's int can never call a method on itself; it must first be boxed into an Integer.
var Type Inference
var lets the compiler infer a variable's type from its initializer — the type is fixed permanently at compile time, exactly as if it had been spelled out explicitly. This is genuinely still static typing, in the same spirit as C++'s auto, not a loophole into dynamic typing.
Nullable Value Types
A value type genuinely can't be null by default — it's real data sitting directly in the variable, not a reference that could point to nothing. The ? suffix opts a value type into nullability through Nullable<T>, a wrapper struct. This is a separate, earlier feature from Course 2's own nullable reference types chapter, which addresses the opposite problem — reference types, which could always be null by default until that later feature opted them out of it.
| Aspect | Java (java1-2) | C# |
|---|---|---|
| Who can define a value type | nobody — only 8 built-ins | any programmer, via struct |
| Is int a real object? | no — must box to Integer first | yes — int genuinely is System.Int32 |
| Calling a method on a literal | not possible directly | 5.ToString() works directly |
| Can a value type be null | n/a — primitives have no null concept | only if explicitly marked nullable (int?) |
Coding Challenges
Write a struct Point with X and Y int fields, and a class Wallet with a decimal Balance field, create one instance of each, assign each to a second variable, modify the second variable's fields, and print both original and copy to show which one changed and why.
📄 View solutionWrite code that calls a method directly on an int literal (e.g. 42.ToString()) and explain in a comment why this is legal in C# but would not be legal on a raw int in Java without boxing.
📄 View solutionDeclare an int? variable, assign it null, then attempt the same with a plain int. Show the resulting compile error on the plain int and explain the difference in terms of value-type semantics.
📄 View solutionChapter 2 Quick Reference
- struct declares a value type (copied by value); class declares a reference type (copied by reference) — unlike Java, where only 8 built-ins are ever value-like
- C#'s int/double/bool are real structs (System.Int32, etc.) — they can call methods directly, unlike Java's non-object primitives
- var infers a type at compile time — still fully static typing, not dynamic typing
- A plain value type can never be null; int? opts in via the Nullable<T> wrapper struct
- struct is a genuine tradeoff — great for small, immutable, frequently-copied data, costly for large types copied often
- Next chapter: operators and control flow — switch expressions with pattern matching from day one