Translasi VB.NET dan C#

Membaca kode C# dan memetakkannya ke VB.NET sebagai pengembang VB.

Daftar isi

VB.NET dan C# adalah dua bahasa berbeda yang dikompilasi ke representasi menengah yang sama pada .NET. Topik ini membaca contoh kode C# yang pendek, menemukan perbedaan sintaks yang paling menonjol dari sudut pandang VB.NET, lalu menerjemahkannya menjadi program VB.NET yang dijalankan. Hasil yang diperoleh adalah kemampuan membaca contoh C# dari dokumentasi maupun artikel daring dan memindahkannya ke VB.NET dengan pemahaman mekanismenya.

Satu runtime, dua bahasa#

Kompiler VB.NET dan kompiler C# sama-sama menghasilkan Intermediate Language (IL), yaitu representasi menengah yang dijalankan oleh runtime .NET yang sama. Keduanya juga mengakses pustaka kelas .NET yang identik, dan Common Type System menetapkan tipe yang digunakan bersama oleh seluruh bahasa .NET. Akibat langsungnya, kelas yang ditulis dalam C# dapat digunakan dari proyek VB.NET tanpa konversi apa pun, dan sebaliknya.

Posisi keduanya berbeda dalam ekosistem. Fitur baru .NET biasanya tampil di C# lebih dahulu, sedangkan VB.NET tetap dipelihara dengan penambahan yang lebih jarang. Penggunaan praktisnya juga terbagi, yaitu aplikasi internal perusahaan masih banyak ditulis dengan VB, sementara proyek open source dan contoh daring didominasi C#. Karena sebagian besar contoh pada dokumentasi pustaka pihak ketiga, forum, dan tanya jawab daring ditulis dalam C#, kemampuan membaca C# memperluas akses terhadap pengetahuan teknis yang sudah terkumpul di sumber-sumber itu.

Untungnya, kedua bahasa berbagi konsep yang sama, mulai dari kelas, properti, exception, hingga generics, sehingga perbedaan terbesarnya berada di tata bahasa permukaan. Tabel berikut memetakan bentuk yang paling sering ditemui saat membaca contoh C#.

Pemetaan sintaks utama#

AspekC#VB.NET
Impor namespaceusing System;Imports System
Kelasclass RekapNilai { ... }Class RekapNilai ... End Class
Metodedouble RataRata() { ... }Function RataRata() As Double ... End Function
Prosedur tanpa hasilvoid Cetak() { ... }Sub Cetak() ... End Sub
Akhir pernyataantitik koma ;akhir baris
Blok kodekurung kurawal { }kata kunci End
Komentar// komentar' komentar
Huruf besar-kecilsensitiftidak sensitif
Deklarasi variabelvar nilai = new List<int>();Dim nilai As New List(Of Integer)
Interpolasi string$"Rata-rata: {x}"$"Rata-rata: {x}"
Properti otomatispublic int Umur { get; set; }Public Property Umur As Integer
Nilai yang mungkin kosongint? stokDim stok As Integer?
Pemeriksaan kosongx == null atau x is nullx Is Nothing
Lambdan => n * 2Function(n) n * 2

Dua baris pada tabel menonjol karena bentuknya sama persis, yaitu interpolasi string dengan awalan $ dan tanda kurung kurawal. Kedua bahasa menggunakan mekanisme kompilator yang sejenis untuk fitur itu. Baris int? dan Integer? sama-sama menyatakan tipe nilai yang boleh kosong (nullable), sedangkan anotasi string? pada C# adalah bagian dari fitur nullable reference type yang tidak memiliki padanan penulisan di VB.NET, sehingga cukup diterjemahkan menjadi String biasa.

Cara memanfaatkan tabel ini adalah membaca baris demi baris dari contoh C# yang sedang diterjemahkan, lalu mencari aspeknya pada kolom C# sebelum menuliskan bentuk VB.NET-nya. Baris-baris yang tidak ada padanannya satu banding satu, misalnya => untuk lambda, diterjemahkan sesuai konsepnya dan bukan sesuai bentuk penulisannya. Pemeriksaan tabel biasanya cukup untuk contoh pendek, sedangkan contoh yang panjang sebaiknya diterjemahkan satu kelas pada satu waktu agar kesalahannya mudah dilacak.

Membaca contoh C##

Contoh berikut adalah program C# lengkap yang akan diterjemahkan. Program ini menghitung rata-rata sekumpulan nilai lalu menetapkan predikatnya, dan keduanya dikerjakan oleh kelas RekapNilai.

csharp Contoh: kode C# yang akan diterjemahkan
// tidak-dijalankan
using System;
using System.Collections.Generic;

namespace Statistik
{
    public class RekapNilai
    {
        public string? Predikat(double rataRata)
        {
            if (rataRata >= 75.0)
            {
                return "Baik";
            }
            return "Perlu bimbingan";
        }

        public double RataRata(List<int> nilai)
        {
            int total = 0;
            foreach (int n in nilai)
            {
                total += n;
            }
            if (nilai.Count == 0)
            {
                return 0.0;
            }
            return total / (double)nilai.Count;
        }
    }

    public class Program
    {
        public static void Main()
        {
            var rekap = new RekapNilai();
            var nilai = new List<int> { 70, 80, 90 };
            Console.WriteLine($"Rata-rata: {rekap.RataRata(nilai)}");
            Console.WriteLine($"Predikat: {rekap.Predikat(rekap.RataRata(nilai))}");
        }
    }
}

Beberapa hal terbaca langsung setelah tabel pemetaan. Kata using di kepala berkas adalah Imports, kata namespace beserta kurung kurawalnya adalah Namespace ... End Namespace, dan foreach adalah For Each. Tipe ditulis sebelum nama di C#, misalnya double rataRata pada parameter, lalu berpindah menjadi rataRata As Double di VB. Kata var menyembunyikan tipe karena kompiler C# menyimpulkannya dari sisi kanan, sehingga pasangannya adalah Dim dengan tipe yang dituliskan eksplisit. Interpolasi $"..." dan pemanggilan Console.WriteLine tidak perlu diubah sama sekali karena bentuknya sudah identik.

Menerjemahkan ke VB.NET#

Terjemahan lengkapnya adalah program berikut yang dijalankan di sandbox.

vb Program.vb
Imports System.Collections.Generic

Namespace Statistik

    Public Class RekapNilai

        Public Function Predikat(rataRata As Double) As String
            If rataRata >= 75.0 Then
                Return "Baik"
            End If
            Return "Perlu bimbingan"
        End Function

        Public Function RataRata(nilai As List(Of Integer)) As Double
            Dim total As Integer = 0
            For Each n As Integer In nilai
                total += n
            Next
            If nilai.Count = 0 Then
                Return 0.0
            End If
            Return total / CDbl(nilai.Count)
        End Function

    End Class

    Public Class Program

        Public Shared Sub Main()
            Dim rekap As New RekapNilai()
            Dim nilai As New List(Of Integer) From {70, 80, 90}
            Console.WriteLine($"Rata-rata: {rekap.RataRata(nilai)}")
            Console.WriteLine($"Predikat: {rekap.Predikat(rekap.RataRata(nilai))}")
        End Sub

    End Class

End Namespace
text Keluaran
Rata-rata: 80
Predikat: Baik

Keputusan penerjemahannya dapat ditelusuri satu per satu sebagai berikut.

  1. using System.Collections.Generic; menjadi Imports System.Collections.Generic tanpa titik koma.
  2. namespace Statistik { ... } menjadi blok Namespace Statistik ... End Namespace, dan public menjadi Public.
  3. string? Predikat(double rataRata) menjadi Function Predikat(rataRata As Double) As String, dengan tipe hasil berpindah ke klausa As di akhir.
  4. foreach (int n in nilai) menjadi For Each n As Integer In nilai, dan penambahannya tetap total += n.
  5. Cast eksplisit (double)nilai.Count menjadi CDbl(nilai.Count), karena fungsi konversi memainkan peran yang sama.
  6. var rekap = new RekapNilai(); menjadi Dim rekap As New RekapNilai(), dan inisialisasi koleksi { 70, 80, 90 } menggunakan kata kunci From.
  7. public static void Main() menjadi Public Shared Sub Main(), karena static dipadankan dengan Shared.

Keluaran dari kedua bahasa itu identik karena keduanya menghitung dengan logika yang sama, yaitu rata-rata 80 dan predikat “Baik” dari ambang 75. Pemeriksaan semacam ini sebaiknya diulang untuk setiap terjemahan, karena kesamaan keluaran pada data contoh bukan jaminan kesamaan perilaku pada semua data.

Kesalahan umum#

Kesalahan pertama adalah menempelkan kode C# langsung ke berkas .vb berharap kompiler menyesuaikannya. Hasilnya deretan error sintaks karena titik koma, kurung kurawal, dan tanda ? bukan bagian tata bahasa VB.NET. Terjemahkan dahulu dengan tabel pemetaan, lalu periksa semantikanya.

Kesalahan kedua adalah mengabaikan sensitivitas huruf besar-kecil. Dua nama total dan Total pada C# adalah dua variabel berbeda, sedangkan VB.NET menganggapnya sama. Saat membaca C#, perbedaan kapitalisasi harus dicatat sebagai pembeda nama, dan saat menulis VB.NET, huruf besar-kecil tidak boleh dijadikan cara membedakan dua nama.

Kesalahan ketiga adalah menerjemahkan operator dan pemeriksaan kosong secara kata per kata. Pembagian int pada C# memotong hasilnya, pemeriksaan == null menjadi Is Nothing, dan string? tidak memiliki padanan penulisan. Kesalahan semacam ini lolos dari pemeriksaan sintaks karena bentuknya sah, tetapi programnya berperilaku berbeda dari aslinya.

Ringkasan#

  • VB.NET dan C# menghasilkan IL yang sama, berbagi runtime dan pustaka kelas, sehingga kelas dari keduanya saling digunakan tanpa konversi.
  • Perbedaannya menumpuk di permukaan, yaitu akhir baris melawan titik koma, blok kata kunci melawan kurung kurawal, dan sensitivitas huruf besar-kecil.
  • Terjemahan yang andal memeriksa semantika operator dan pemeriksaan kosong, misalnya pembagian int pada C# dan Is Nothing pada VB.NET.

Referensi#