When it comes to sugar and fancy features in programming languages, C # and Kotlin are among the first options in mind. Since these two languages occupy similar niches, that is, they are strongly typed, garbage collected, cross-platform, used both in the backend and in mobile development, today we will try to compare their syntactic capabilities and arrange a small vote. To make the comparison fair, we will consider the latest versions of both languages. I will make a reservation about my impartiality: I equally like both languages, they are in continuous development and do not lag behind each other. This article is a comparison article, not a tutorial, so some run-of-the-mill syntactic possibilities may be omitted.
Let's start at the entry point
In C #, this role is played by the static Main or top-level entry point method, for example
using static System.Console;
WriteLine("Ok");
Kotlin needs a main function
fun main() = println("Ok")
From these small two examples, first of all, it is noticeable that in Kotlin you can omit the semicolon. With a deeper analysis, we see that in C #, despite the conciseness of the indicative entry point, static methods in other files still need to be wrapped in a class and explicitly imported from it ( using static System.Console ), and Kotlin goes further and allows you to create full-fledged functions ...
Declaring Variables
In C #, the type is written on the left, and the new keyword is used to create an instance. There is a special word var, which can replace the type name on the left. However, variables within methods in C # remain susceptible to re-assignment.
Point y = new(0, 0);
var x = new Point(1, 2);
x = y; //
Kotlin , . var, val . new.
val y: Point = Point(0, 0)
val x = Point(1, 2)
x = y // !
C# ( ) ( ) . .
'==' , , . .
// ,
struct ValueType {}
// ,
class ReferenceType {}
Kotlin, . '==' , '==='. , , Int, Char, Double, jvm , . .NET , Kotlin , / .
Null safety
C# ( 8 ) null. !
var legalValue = maybeNull!;
// legalValue null,
// exception
Kotlin null ,
val legalValue = maybeNull!!
// maybeNull == null,
// exception
C# get/set, . .
class Example
{
// backing field
public string Name1 { get; set; } = "Pre-calculated expression";
//
public string Name2 => "Calculated now";
//
private const string Name3 = "Field";
}
Kotlin , , . , C#, public , . , set , var/val.
class Example {
// backing field
val name1 = "Pre-calculated expression"
//
val name2 get() = "Calculated now"
}
C# record , , ( ):
class JustClass
{
public string FirstName { init; get; }
public string LastName { init; get; }
}
record Person(string FirstName, string LastName);
...
Person person1 = new("Nancy", "Davolio");
Person person2 = person1 with { FirstName = "John" };
Kotlin data class
class JustClass(val firstName: String, val lastName: String)
data class Person(val firstName: String, val lastName: String)
...
val person1 = Person("Nancy", "Davolio")
val person2 = person1.copy(firstName = "John")
C# , this
static class StringExt
{
public static Println(this string s) => System.Console.WriteLine(s)
public static Double(this string s) => s + s
}
Kotlin , . ,
fun String.println() = println(this)
fun String.double get() = this * 2
C# =>
numbers.Any(e => e % 2 == 0);
numbers.Any(e =>
{
// ...
return calculatedResult;
})
Kotlin - , . DSL (Gradle + Kotlin ).
numbers.any { it % 2 == 0 }
numbers.any {
// ...
calculatedResult
}
C# pattern matching c ( )
static Point Transform(Point point) => point switch
{
{ X: 0, Y: 0 } => new Point(0, 0),
{ X: var x, Y: var y } when x < y => new Point(x + y, y),
{ X: var x, Y: var y } when x > y => new Point(x - y, y),
{ X: var x, Y: var y } => new Point(2 * x, 2 * y),
};
Kotlin switch when, , , , :
fun transform(p: Point) = when(p) {
Point(0, 0) -> Point(0, 0)
else -> when {
p.x > p.y -> Point(...)
p.x < p.y -> Point(...)
else -> Point(...)
}
}
. . Kotlin-way , , C# . Kotlin C# , C# Microsoft .