So, it seems you need to learn C# in a hurry, but you already know Java. You've come to the right place.
The Syntax
It's the same.
Seriously.
C# was designed from the ground up to be an easier-to-use Java. Go into that file cabinet in your brain of Java knowledge, make some photocopies, and put it in the new C# filing cabinet. This tutorial will focus on pointing out the minor differences, but unless it's stated here, you can start out assuming it works the same way in C# as it does in Java.
For example, here is Hello, World in Java:
public class HelloWorld { public static void main(String[] args) { // a nice greeting System.out.println("Hello, World!"); // now count to 10... for (int i = 0; i < 10; ++i) { System.out.println(i + " Mississippi"); } } }
And here it is in C#:
public class Program { public static void Main(string[] args) { // a nice greeting System.Console.WriteLine("Hello, World!"); // now count to 10... for (int i = 0; i < 10; ++i) { System.Console.WriteLine(i + " Mississippi"); } } }
Yup, there are some differences, but a lot of it is just convention rather than a language difference.
First Things First
Download Visual Studio. It's free. Fiddly project setup is never done by hand and if you try to do this without Visual Studio you're in for a world of hurt. Download it. It's big, yes. But you'll be glad you did.
About .NET
But before we get into the minor differences, it helps to know a little bit about what .NET is and how C# fits in to that.
.NET was created in the original ".com era" and was a pure marketing term to play on that buzz, but has absolutely nothing to do with the internet. It's hard to define since really, all it is is a giant umbrella term for a collection of Microsoft technologies related to their developer tools, but the scope of the term ".NET" these days has largely limited to just their managed code ecosystem.
The beauty of .NET is that when code written in a .NET language (such as C# or VB.NET) is compiled, it all compiles down to a common format independent of the language, and then can be compiled to the CPU and executed. This also means you can use components written in another language in your program.
There is a lot more technical details and if you ask 20 different software developers to define .NET you will get 20 different definitions. But the most important thing right now is learning C#...
C# Project File Structure
With Java, you basically could have a pile of .java files and then you could run a big command line command with javac and you'd get a .class file. If you were fancy, you'd use a compilation tool that would take care of invoking the Java compiler such as Ant, Maven, or Gradle. But these were independent technologies that simply invoked the Java compiler. With C#, there is a similar system, but they are already baked into the official Microsoft ecosystem. You could in theory run a manual csc (C# compile) commands from the command line, but no one really does that. Instead, there is a Solution file and a series of C# Project files (with file extensions of .sln and .csproj respectively).
Solution (.sln) files - This is basically just a list of related .csproj files.
Project (.csproj) files - This is the smallest individual compilation unit. A csproj file will get compiled into a .exe or .dll file. Additionally, they can have dependencies on other project files (which don't necessarily have to be C#). I'm hesitant to use the phrase "they're like Java packages". But they are somewhat similar.
msbuild (which comes with most modern Windows machines) can be pointed to a solution or project file and will know what to do. Most command line options can be encoded into the .csproj file itself (much like a make/ant file).
Code (.cs) files - Code belongs to a .csproj file. Code files can have any name. The name does not matter. Unlike Java where the filename must match the class contained within. This is not the case in C#. Although it's generally a good idea. Organizing files into subdirectories has absolutely no bearing on how the code is compiled. Namespaces (which are like package names) can be whatever you want regardless of where the file is located.
Execution of your program begins in a method called Main in a class called Program.
Style Conventions
The following are just conventions. You can violate any of these if you're feeling stubborn, but if you ever plan on working with other people who have to read your code, I wouldn't recommend it.
- Classes are always capitalized, just like Java
- Methods are always capitalized, unlike Java
- Interfaces are always prefixed with an uppercase I
- Opening curly braces go on the next line
- Variables use camelCase, just like Java. Not road_kill_case like C++.
- However, unlike Java, Enum members are PascalCase, not upper ROAD_KILL_CASE.
Terminology Differences
There are quite a number of language keywords that are identical across C# and Java with the exception of their name.
- package scoped classes and methods (i.e. the ones that you didn't declare as either private, public, or protected) have a keyword in C# called internal. These fields/classes are only visible to other code within the same csproj file.
- final is weird because it had multiple uses in Java. You could declare a class as final and that would mean you couldn't extend it. Alternatively you could set a field or variable as final which means you can't modify the value. For C#, a class that cannot be inherited from uses the sealed keyword. A field that you cannot modify uses the readonly keyword.
And if you're the sort of developer that just made everything mutable/extensible and only used public/private, then none of this really matters anyway, I guess.
Defining a Class
Defining a class in Java required you to distinguish which class you extended from and which interfaces you are implementing. In C#, you simply put a colon after the class name and list them all in a comma-delimited list. After all, all Interfaces start with an "I" by convention, so the extra syntax to distinguish which is which isn't really important.
public sealed class MyThing : AbstractMyThing, IThing { private readonly int value; public MyThing(int value) { this.value = value; } }
static
The word "Static" generally refers to the concept that a thing belongs to a single global instance whereas non-static things belong to individual instantiated instances. This is true in both C# and Java. However, the static keyword works entirely differently when applied to a class.
In Java, if you have an inner nested class that was static, that meant that the class definition belonged to the wrapping class, not an instance of the wrapping class. Having a non-static nested class is kind of weird and very rarely occurs aside from a developer typos. Therefore all inner nested classes in C# are automatically "static" in the Java sense, without the static keyword supplied. However, when you apply the static keyword to a class in C#, that simply means that all fields and methods in the class are to be declared static, e.g. it's a utility method never meant for instantiation.
// The following Java code has no equivalent in C#... public class Foo { public class Bar { ... } } ... Foo foo = new Foo(); Bar bar = new foo.Bar(); // there is no sane reason you'd want to do this.
This is far more common...
// Java public class Foo { public static class Bar { ... } } // C# public class Foo { public class Bar { ... } } // Code for both C# and Java to instantiate: Foo foo = new Foo(); Bar bar = new Foo.Bar();
However, the static keyword, when applied to fields and methods, means the exact same thing in C# as it does in Java.
Type Differences
There is quite a bit of overlap with the built-in primitive types, but as far as the built in class library goes, there's usually some sort of equivalent, but it may not be immediately clear. However, most of them are a quick Google+StackOverflow search away. But here are the major differences:
boolean is now simply bool. Think of all the time you'll save.
String is now string. Lowercase. You use it like a primitive most of the time, so C# aliases "string" to "String". You could, in theory, just use an uppercase "String" for your strings, but that is non-standard and will annoy other C# developers. Like a primitive type, you can use == without fear that it will do an reference comparison.
Object is now object.
The Java List interface is a C# IList because it is an interface.
ArrayList is simply just List in C#.
HashMaps are now Dictionary's. And Map is now IDictionary.
Additionally, there are a lot more numeric types in C# than there are in Java and each numeric type generally has a corresponding unsigned type that begins with a u.
- byte: -128 to 127
- ubyte: 0 to 255
- uint: 0 to 232 - 1
- ulong: 0 to 264 - 1
Generics
Generics are much less fiddly in C#. Partially because they are both a compile-time and run-time concept. There is no diamond syntax (e.g. new ArrayList<>();) in C# which may sound horrific, but it's really not that bad. As a bonus, primitives are valid types for generics. So you can have a List
Invoking methods that require generics as parameters are done between the method name and the parenthesis as opposed to between the dot and the method name. Basically constructors and methods in C# use the same convention whereas Java used different syntax for generics for the constructor and methods.
// returns a list with strict member type of Foo. List<Foo> listOfFoos = listOfVariousThings.OfType<Foo>();
Properties
In C# you don't need boiler-plate getter and setter methods. There is syntax to make this concept a bit more lightweight to both define and use. They are called properties.
Here is a Java class with a field called value...
public class Foo { private int value; public Foo(int value) { this.value = value; } public int getValue() { return value; } // package-scoped setter void setValue(int value) { this.value = value; } } ... Foo foo = new Foo(42); foo.setValue(-1); int newValue = foo.getValue();
Here is equivalent code in C#...
class Foo { public int Value { get; internal set; } // project-scoped setter public Foo(int value) { this.Value = value; } } ... Foo foo = new Foo(42); foo.Value = -1; int newValue = foo.Value;
With properties, you can even bypass the constructor arguments altogether and use the following syntax to set properties...
class Foo { public int Value { get; internal set; } } Foo foo = new Foo() { Value = 42 };
"But wait! The beauty of a Java getter/setter is that you can define special code to run when you get or set the field, such as clearing a cache."
You can do that too in C#. By default, get; and set; will act like a field. But you can give these actual implementations that do more interesting things. In fact, you can just create a getter without a setter that just returns a value from code rather than getting it from a field.
public class Foo { private int value; public int Value { get { return this.value; } set { // the word "value" here that you're setting to the field // "this.value" is actually a C# keyword available in // all setters. this.value = value; } } public bool IsEven { get { return this.value % 2 == 0; } } }
In Conclusion
That covers most of the major differences. At least enough to get you started and without getting into the details of any particular framework. If you have suggestions for additions or think something should be clarified, feel free to reach out to @NerdParadise on twitter.