F# is to C# as C is to Assembler (I regularly use both C# and F# and don't quite agree with this, but it is defensible).
Short answer:
Programming, especially OOP, has a lot of prescriptions: things like coding against interfaces rather than implementations, using abstractions, the law of Demeter, avoiding mutations, prefer composition to inheritance, etc.
Basically, you can think of F# as a language that compiles down to C#, but follows all of the best practices without fuss.
Consider this example of F# code:
type Shape =
| Circle of float
| Square of float
let area s =
match s with
| Circle r -> Math.PI * r * r
| Square sd -> sd * sd
let perimeter s =
match s with
| Circle r -> 2 * Math.PI * r
| Square sd -> sd * 4
Here is the moral equivalent in C#: public abstract class Shape
{
public abstract float Area();
public abstract float Perimeter();
}
public sealed class Circle
{
readonly float r;
public Circle(float r)
{
this.r = r;
}
public override float Perimeter()
{
return Math.PI * 2 * r;
}
public override float Area()
{
return Math.PI * r * r;
}
}
public sealed class Square
{
readonly float side;
public Circle(float side)
{
this.side = side;
}
public override float Perimeter()
{
return 4 * side;
}
public override float Area()
{
return side * side;
}
}
A couple of things to note:* The C# code needs 5 times as many line as the F# code (adding a new shape to F# will require about 3 lines, but the corresponding C# class definition will be at least 15 lines).
* The F# code is idiomatic, but hardly any C# programmer seals classes or defines them as immutable by default, even though it is a good practice.
That said, there are some advantages that C# enjoys. Consider our example code: Even though C# requires more lines of code to define a derivative of Shape, at a certain point it will always be easier to add new classes to C# than the corresponding variant to F# (see "The Expression Problem" - on the other hand, adding new functions that apply to Shape will be easier in F# than adding the corresponding new methods in C#). Also, F# is supposed to be a hardcore statically-typed language, but there are some advanced concepts (e.g. type classes) that are easy to realize in C# yet not in F#.