Skip to content Skip to sidebar Skip to footer

Materi Lengkap tentang OOP dalam Bahasa C#

Assalamu‘alaikum wr. wb.

Hello guys! Apakah kalian suka Coding? Ataukah Anda adalah seorang Programmer? Jika sebelumnya kita telah membahas tentang dasar-dasar dalam Pemrograman Berorientasi Objek (PBO) atau Object-Oriented Programming (OOP), sekarang kita akan mengimplementasikan dalam Bahasa C#.



Sumber Utama : C-Sharpcorner.com

C# atau yang dibaca C Sharp adalah bahasa pemrograman sederhana yang digunakan untuk tujuan umum, dalam artian bahasa pemrograman ini dapat digunakan untuk berbagai fungsi misalnya untuk pemrograman server-side pada website, membangun aplikasi desktop ataupun mobile, pemrograman game dan sebagainya. Selain itu C# juga bahasa pemrograman yang berorientasi objek, jadi C# juga mengusung konsep objek seperti inheritance, class, polymorphism dan encapsulation.

Dalam praktiknya C# sangat bergantung dengan framework yang disebut .NET Framework, framework inilah yang nanti digunakan untuk meng-compile dan menjalankan kode C#. C# dikembangkan oleh Microsoft dengan merekrut Anders Helsberg. Tujuan dibangunnya C# adalah sebagai bahasa pemrograman utama dalam lingkungan .NET Framework. Banyak pihak juga yang menganggap bahwa Java dengan C# saling bersaing, bahkan ada juga yang menyatakan jika pernah belajar Java maka belajar C# akan sangat mudah dan begitu juga sebaliknya. Anggapan tersebut sebenarnya tidak salah karena perlu diketahui sebelum adanya C# Microsoft mengembangkan J++ dengan maksud mencoba membuat Java agar berjalan pada platform Windows, karena adanya masalah dari pihak luar maka Microsoft menghentikan proyek J++ dan beralih untuk mengembangkan bahasa baru yaitu C#.


PENGENALAN

Sumber : W3schools.com (OOP C#) dan Docs.Microsoft.com (OOP) [Diterjemahkan melalui Google Translate]

OOP adalah singkatan dari Pemrograman Berorientasi Objek. Pemrograman prosedural adalah tentang menulis prosedur atau metode yang melakukan operasi pada data, sedangkan pemrograman berorientasi objek adalah tentang membuat objek yang berisi data dan metode.

Pemrograman berorientasi objek memiliki beberapa keunggulan dibandingkan pemrograman prosedural :
  • OOP lebih cepat dan lebih mudah untuk dieksekusi
  • OOP menyediakan struktur yang jelas untuk program
  • OOP membantu menjaga Kode C# JUDS "Jangan Ulangi Diri Sendiri" (C# Code DRY "Don't Repeat Yourself"), dan membuat kode lebih mudah untuk dipelihara, dimodifikasi, dan di-debug
  • OOP memungkinkan untuk membuat aplikasi penuh yang dapat digunakan kembali dengan lebih sedikit kode dan waktu pengembangan yang lebih singkat
  • Tip: Prinsip "Jangan Ulangi Diri Sendiri" (JUDS) adalah tentang mengurangi pengulangan kode. Anda harus mengekstrak kode yang umum untuk aplikasi, dan menempatkannya di satu tempat dan menggunakannya kembali alih-alih mengulanginya.

Empat prinsip dasar pemrograman berorientasi objek adalah :
  • Abstraction Pemodelan atribut yang relevan dan interaksi entitas sebagai kelas untuk mendefinisikan representasi abstrak dari suatu sistem.
  • Encapsulation Menyembunyikan status internal dan fungsionalitas suatu objek dan hanya mengizinkan akses melalui serangkaian fungsi publik.
  • Inheritance Kemampuan untuk membuat abstraksi baru berdasarkan abstraksi yang ada.
  • Polymorphism Kemampuan untuk mengimplementasikan properti atau metode yang diwarisi dengan cara yang berbeda di berbagai abstraksi.

Dalam tutorial ini, Anda akan memperluas aplikasi tersebut untuk menggunakan pewarisan dan polimorfisme untuk menambahkan fitur baru. Anda juga akan menambahkan fitur ke kelas BankAccount, memanfaatkan teknik abstraksi dan enkapsulasi yang Anda pelajari di tutorial sebelumnya.


OOP DASAR (KELAS-OBJEK)

A. Class dan Object

Segala sesuatu di C# dikaitkan dengan kelas dan objek, bersama dengan atribut dan metodenya. Sebagai contoh adalah dalam kehidupan nyata, mobil adalah sebuah objek. Mobil memiliki atribut, seperti berat dan warna, dan metode, seperti drive dan rem.

1. Class

Dalam C#, Class adalah sekelompok objek serupa. Ini adalah template dari mana object dibuat. Itu dapat memiliki fields, method, constructor, dll.

Definisi kelas dimulai dengan kata kunci kelas diikuti dengan nama class; dan badan kelas diapit oleh sepasang kurung kurawal. Berikut ini adalah bentuk umum dari definisi class.

<access specifier> class  class_name {
   // member variables
   <access specifier> <data type> variable1;
   <access specifier> <data type> variable2;
   ...
   <access specifier> <data type> variableN;
   // member methods
   <access specifier> <return type> method1(parameter_list) {
      // method body
   }
   <access specifier> <return type> method2(parameter_list) {
      // method body
   }
   ...
   <access specifier> <return type> methodN(parameter_list) {
      // method body
   }
}

Catatan :
  • Penentu akses menentukan aturan akses untuk anggota serta kelas itu sendiri. Jika tidak disebutkan, maka penentu akses default untuk tipe kelas adalah internal. Akses default untuk anggota adalah pribadi.
  • Tipe data menentukan tipe variabel, dan tipe pengembalian menentukan tipe data dari data yang dikembalikan metode, jika ada.
  • Untuk mengakses anggota kelas, Anda menggunakan operator titik (.).
  • Operator titik menghubungkan nama objek dengan nama anggota.

Mari kita lihat contoh kelas C# yang hanya memiliki dua bidang.

class Mobil {
  string warna = "merah";
}

2. Object

Dalam C#, Object adalah entitas dunia nyata, misalnya, kursi, mobil, pena, ponsel, laptop, dll. Dengan kata lain, objek adalah entitas yang memiliki status dan perilaku. Di sini, state berarti data dan behavior berarti fungsionalitas. Objek adalah entitas runtime, dibuat saat runtime.

Objek adalah turunan dari kelas. Semua anggota kelas dapat diakses melalui object. Mari kita lihat contoh untuk membuat objek menggunakan kata kunci baru.

class Mobil {
  string warna = "merah";

  static void Main(string[] args) {
    Mobil myObj = new Mobil();
    Console.WriteLine(myObj.warna);
  }
}

Beberapa Objek

Anda dapat membuat beberapa objek dari satu kelas :

using System;

class Mobil {
    string warna = "merah";

    static void Main(string[] args) {
        Mobil myObj = new Mobil();
        Console.WriteLine(myObj.warna);
    }
}
Anda juga dapat membuat objek kelas dan mengaksesnya di class lain. Ini sering digunakan untuk organisasi kelas yang lebih baik (satu kelas memiliki semua field dan method, sedangkan kelas lainnya memegang method Main() (kode yang akan dieksekusi)).

using System;

class Mobil {
    public string warna = "merah";
}

class Program{
    static void Main(string[] args){
        Mobil myObj = new Mobil();
        Console.WriteLine(myObj.warna);
    }
}
Contoh Program :

using System;

public class Student{
    public int nim;
    public String nama;  
}

class StudentTest{
    public static void Main(string[] args){
        Student mahasiswa = new Student();
        mahasiswa.nim = 2110101017;
        mahasiswa.nama = "Inzaghi Posuma";
        Console.WriteLine(mahasiswa.nim);
        Console.WriteLine(mahasiswa.nama);
    }
}
Output :

2110101017
Inzaghi Posuma

using System;

namespace BoxApplication {
    class Box {
        public double length;   // Panjang dari box
        public double breadth;  // Lebar dari box
        public double height;   // Tinggi box
    }

    class Boxtester {
        static void Main(string[] args) {
            Box Box1 = new Box();   // Deklarasi Box1 dari tipe Box
            Box Box2 = new Box();   // Deklarasi Box2 dari tipe Box
            double volume = 0.0;    // Simpan volume box di sini

            // Spesifikasi box 1
            Box1.height = 5.0;
            Box1.length = 6.0;
            Box1.breadth = 7.0;

            // Spesifikasi box 2
            Box2.height = 10.0;
            Box2.length = 12.0;
            Box2.breadth = 13.0;
           
            // Volume dari box 1
            volume = Box1.height * Box1.length * Box1.breadth;
            Console.WriteLine("Volume of Box1 : {0}",  volume);

            // Volume dari box 2
            volume = Box2.height * Box2.length * Box2.breadth;
            Console.WriteLine("Volume of Box2 : {0}", volume);
            Console.ReadKey();
        }
    }
}
Output :

Volume of Box1 : 210
Volume of Box2 : 1560

B. Class Members


1. Properties

Properti diberi nama anggota kelas, struktur, dan antarmuka. Variabel anggota atau metode dalam kelas atau struktur disebut Fields. Properti adalah perpanjangan dari bidang dan diakses menggunakan Sintaks yang sama. Mereka menggunakan pengakses (accessors) di mana nilai-nilai bidang pribadi dapat dibaca, ditulis atau dimanipulasi.

Properti tidak memberi nama lokasi penyimpanan. Sebaliknya, mereka memiliki pengakses (accessors) yang membaca, menulis, atau menghitung nilainya.

Misalnya, mari kita memiliki kelas bernama Mahasiswa, dengan bidang pribadi untuk usia, nama, dan kode. Kami tidak dapat mengakses bidang ini secara langsung dari luar lingkup kelas, tetapi kami dapat memiliki properti untuk mengakses bidang pribadi ini.

using System;

class Person{
    public string Name  // property
    { get; set; }
}

class Program{
    static void Main(string[] args){
        Person myObj = new Person();
        myObj.Name = "Inzaghi";
        Console.WriteLine(myObj.Name);
    }
}
Output :

Inzaghi

Sekarang kita dapat menggunakan properti Name untuk mengakses dan memperbarui bidang private dari class Person :

using System;

class Person{
    private string name; // field
    public string Name   // property
    {
        get { return name; }
        set { name = value; }
    }
}

class Program{
    static void Main(string[] args){
        Person myObj = new Person();
        myObj.Name = "Inzaghi";
        Console.WriteLine(myObj.Name);
    }
}
Output :

Inzaghi

Mengapa Encapsulation?
  • Kontrol yang lebih baik terhadap anggota kelas (kurangi kemungkinan diri Anda sendiri (atau orang lain) untuk mengacaukan kode)
  • Fields dapat dibuat read-only (jika Anda hanya menggunakan metode get), atau write-only (jika Anda hanya menggunakan metode set)
  • Fleksibel: programmer dapat mengubah satu bagian dari kode tanpa mempengaruhi bagian lain
  • Peningkatan keamanan data.

2. Fields

Sebelumnya, Anda telah mempelajari bahwa variabel di dalam kelas disebut fields, dan Anda dapat mengaksesnya dengan membuat objek kelas (class object), dan dengan menggunakan sintaks titik (.).

Contoh berikut akan membuat objek dari kelas Mobil, dengan nama myObj. Kemudian akan mencetak nilai field warna dan maxSpeed :

using System;

class Mobil {
    string warna = "merah";
    int maxSpeed = 200;

    static void Main(string[] args){
        Mobil myObj = new Mobil();
        Console.WriteLine(myObj.warna);
        Console.WriteLine(myObj.maxSpeed);
    }
}
Kalian juga dapat mengosongkan bidang, dan memodifikasinya saat membuat object :

using System;

class Mobil {
    string warna;
    int maxSpeed;

    static void Main(string[] args){
        Mobil myObj = new Mobil();
        myObj.warna = "merah";
        myObj.maxSpeed = 200;
        Console.WriteLine(myObj.warna);
        Console.WriteLine(myObj.maxSpeed);
    }
}
Ini sangat berguna saat membuat beberapa objek dari satu kelas. Berikut, inilah kode lainnya untuk yang lebih banyak lagi :

using System;

class Mobil {
    string model;
    string warna;
    int tahun;

    static void Main(string[] args){
        Mobil Honda = new Mobil();
        Honda.model = "Mobilio";
        Honda.warna = "putih";
        Honda.tahun = 2017;

        Mobil Toyota = new Mobil();
        Toyota.model = "Calya";
        Toyota.warna = "abu-abu";
        Toyota.tahun = 2019;

        Console.WriteLine(Honda.model);
        Console.WriteLine(Toyota.model);
    }
}
Output :

Mobilio
Calya

3. Methods

Metode adalah blok kode yang hanya berjalan ketika dipanggil. Anda dapat meneruskan data, yang dikenal sebagai parameter, ke dalam metode. Method digunakan untuk melakukan tindakan tertentu, dan mereka juga dikenal sebagai fungsi. Mengapa menggunakan metode? Untuk menggunakan kembali kode yaitu tentukan kode sekali, dan gunakan berkali-kali.

Sama seperti bidang, Anda dapat mengakses metode dengan sintaks titik. Namun, perhatikan bahwa metode ini harus bersifat publik. Dan ingat bahwa kita menggunakan nama metode yang diikuti oleh dua tanda kurung () dan titik koma ; untuk memanggil (mengeksekusi) method :

using System;

class Mobil {
    string warna;                 // field
    int maxSpeed;                 // field
    public void fullThrottle()    // method
    {
        Console.WriteLine("Mobil melaju secepat mungkin!");
    }

    static void Main(string[] args){
        Mobil myObj = new Mobil();
        myObj.fullThrottle();  // Memanggil method
    }
}
Output :

Mobil melaju secepat mungkin!

Gunakan Beberapa Kelas

Ingat, bahwa kita dapat menggunakan beberapa class untuk organisasi yang lebih baik (satu untuk field dan method, dan satu lagi untuk eksekusi). Ini disarankan :

using System;

class Mobil {
    public string model;
    public string warna;
    public int tahun;
    public void fullThrottle(){
        Console.WriteLine("Mobil melaju secepat mungkin!");
    }
}

class Program{
    static void Main(string[] args){
        Mobil Honda = new Mobil();
        Honda.model = "Mobilio";
        Honda.warna = "putih";
        Honda.tahun = 2017;

        Mobil Toyota = new Mobil();
        Toyota.model = "Calya";
        Toyota.warna = "abu-abu";
        Toyota.tahun = 2019;

        Console.WriteLine(Honda.model);
        Console.WriteLine(Toyota.model);
    }
}
Output :

Mobilio
Calya

4. Constructor

Konstruktor adalah metode khusus yang digunakan untuk menginisialisasi objek. Keuntungan dari sebuah konstruktor, adalah bahwa hal itu dipanggil ketika sebuah objek dari sebuah kelas dibuat. Ini dapat digunakan untuk menetapkan nilai awal untuk bidang :

using System;

// Membuat class Mobil
class Mobil{
    public string model;  // Membuat a field

    // Membuat class constructor class Mobil
    public Mobil(){
        model = "Mobilio"; // Tetapkan nilai awal untuk model
    }

    static void Main(string[] args){
        Mobil Honda = new Mobil();  // Membuat objek Class Mobil (ini akan memanggil constructor)
        Console.WriteLine(Honda.model);  // Mencetak nilai model
    }
}

// Hasil output adalah "Mobilio"

OOP LANJUTAN 1

A. Reference & Value Type


Value Type dan tipe referensi adalah dua kategori utama tipe C#. Variabel dari tipe nilai berisi turunan dari tipe tersebut. Ini berbeda dari variabel tipe referensi, yang berisi referensi ke turunan tipe. Secara default, pada penugasan, meneruskan argumen ke metode, dan mengembalikan hasil metode, nilai variabel disalin. Dalam kasus variabel tipe nilai, instance tipe yang sesuai akan disalin.

Dalam C#, tipe data ini dikategorikan berdasarkan cara mereka menyimpan nilainya di memori. C# mencakup kategori tipe data berikut :
  • Value type
  • Reference type
  • Pointer type

1. Value Type

Tipe data adalah tipe nilai jika menyimpan nilai data dalam ruang memorinya sendiri. Artinya variabel dari tipe data ini secara langsung mengandung nilai. Sebagai contoh, pertimbangkan variabel integer int i = 100;

Sistem menyimpan 100 di ruang memori yang dialokasikan untuk variabel i. Gambar berikut mengilustrasikan bagaimana 100 disimpan di beberapa lokasi hipotetis dalam memori (0x239110) untuk 'i' :


INGAT!

Semua tipe nilai berasal dari System.ValueType, yang pada gilirannya, berasal dari System.Object.

Tipe data berikut adalah semua value type :
  • bool
  • byte
  • char
  • decimal
  • double
  • enum
  • float
  • int
  • long
  • sbyte
  • short
  • struct
  • uint
  • ulong
  • ushort

Passing Value Type Variables

Saat Anda meneruskan variabel tipe nilai dari satu metode ke metode lainnya, sistem akan membuat salinan terpisah dari variabel di metode lain. Jika nilai diubah dalam satu metode, itu tidak akan memengaruhi variabel dalam metode lain.

using System;
                   
public class Program{
    static void ChangeValue(int x){
        x =  200;
        Console.WriteLine(x);
    }
   
    public static void Main(){
        int i = 100;
        Console.WriteLine(i);
        ChangeValue(i);
        Console.WriteLine(i);
    }
}
Output :

100
200
100

Dalam contoh di atas, variabel i dalam metode Main() tetap tidak berubah bahkan setelah kita meneruskannya ke metode ChangeValue() dan mengubah nilainya di sana.

2. Reference Type

Tidak seperti value types, reference type tidak menyimpan nilainya secara langsung. Sebagai gantinya, ia menyimpan alamat tempat nilai disimpan. Dengan kata lain, tipe referensi (reference type) berisi penunjuk ke lokasi memori lain yang menyimpan data.

Misalnya, memandang variabel string berikut :

string s = "Hello World!!";
string s = "Hello World!!";

Gambar berikut menunjukkan bagaimana sistem mengalokasikan memori untuk variabel string di atas.


Seperti yang Anda lihat pada gambar di atas, sistem memilih lokasi acak di memori (0x803200) untuk variabel s. Nilai variabel s adalah 0x600000, yang merupakan alamat memori dari nilai data aktual. Jadi, tipe referensi menyimpan alamat lokasi di mana nilai sebenarnya disimpan, bukan nilai itu sendiri.

Berikut ini adalah tipe data reference type :
  • String
  • Arrays (bahkan jika elemen mereka adalah tipe nilai)
  • Class
  • Delegate

Passing Reference Type Variables

Saat Anda meneruskan variabel reference type dari satu metode ke metode lain, itu tidak membuat salinan baru; sebagai gantinya, ia melewati alamat variabel. Jadi, Jika kita mengubah nilai variabel dalam suatu metode, itu juga akan tercermin dalam metode pemanggilan.

using System;

public class Student{
    public string StudentName { get; set; }
}

public class Program
{
    public static void ChangeReferenceType(Student siswa2){
        siswa2.StudentName = "Adi";
    }
   
    public static void Main(){
        Student siswa1 = new Student();
        siswa1.StudentName = "Budi";
        ChangeReferenceType(siswa1);
        Console.WriteLine(siswa1.StudentName);
    }
}
Output :

Adi

Dalam contoh di atas, kita meneruskan objek Student siswa1 ke metode ChangeReferenceType(). Di sini, itu benar-benar melewati alamat memori siswa1. Jadi, ketika metode ChangeReferenceType() mengubah StudentName, itu sebenarnya mengubah StudentName dari objek siswa1, karena siswa1 dan siswa2 keduanya menunjuk ke alamat yang sama di memori.

String adalah tipe referensi (reference type), tetapi tidak dapat diubah. Artinya, sekali kita menetapkan suatu nilai, itu tidak dapat diubah. Jika kita mengubah nilai string, maka kompiler membuat objek string baru di memori dan mengarahkan variabel ke lokasi memori baru. Jadi, meneruskan nilai string ke suatu fungsi akan membuat variabel baru di memori, dan setiap perubahan nilai dalam fungsi tidak akan tercermin dalam nilai aslinya, seperti yang ditunjukkan di bawah ini.

Contoh : Passing String

using System;

public class Program
{
    static void ChangeReferenceType(string name){
        name = "Adi";
    }

    public static void Main(string[] args){
        string name = "Budi";
        ChangeReferenceType(name);
        Console.WriteLine(name);
    }
}
Output :

Budi

[BONUS] Null Reference Type

Nilai default dari variabel tipe referensi adalah null ketika tidak diinisialisasi. Null berarti tidak mengacu pada objek apapun.


Variabel tipe nilai tidak boleh nol karena menyimpan nilai, bukan alamat memori. C# 2.0 memperkenalkan tipe nullable, yang dengannya Anda dapat menetapkan null ke variabel tipe nilai atau mendeklarasikan variabel tipe nilai tanpa menetapkan nilai padanya.


Kelas Statis (Static Class) pada dasarnya sama dengan kelas non-statis, tetapi ada satu perbedaan: kelas statis tidak dapat dipakai. Dengan kata lain, kita tidak dapat menggunakan kata kunci new untuk membuat variabel bertipe kelas. Karena tidak ada variabel instan, kami mengakses anggota kelas statis dengan menggunakan nama kelas itu sendiri.

1. Static / Non-Static Fields

Filed dalam C# harus dideklarasikan di dalam class. Namun, jika kita mendeklarasikan metode atau bidang sebagai statis, kita dapat memanggil metode atau mengakses bidang dengan menggunakan nama kelas. Tidak diperlukan instans. Kita juga dapat menggunakan kata kunci static ketika mendefinisikan sebuah field. Dengan fitur ini, kita dapat membuat satu bidang yang dibagikan di antara semua objek yang dibuat dari satu kelas. Bidang non-statis bersifat lokal untuk setiap instance objek.

Saat Anda mendefinisikan metode atau bidang statis, itu tidak memiliki akses ke bidang instans apa pun yang ditentukan untuk kelas; itu hanya dapat menggunakan bidang yang ditandai sebagai statis. Selain itu, ia dapat secara langsung memanggil hanya metode lain di kelas yang ditandai sebagai statis; method atau nonstatic field (instance) harus terlebih dahulu membuat objek untuk memanggilnya.

Berikut ini adalah contohnya.

using System;
using System.Collections.Generic;
using System.Text;

namespace TestiClass{
   class Program{
       int val = 20;  
       static void Main (string[] args){
           Program x = new Program();
           int newval = x.val;
           Console.WriteLine(newval);
           Console.ReadKey();
       }
   }
}
Dalam contoh di atas, kami memiliki bidang non-statis bernama val. Dari metode utama (metode statis), saya mencoba mengakses bidang itu dan untuk melakukan ini saya perlu membuat instance kelas di dalam metode utama (metode statis) karena metode statis hanya mengakses bidang statis dan val adalah tidak statis di sini. Jadi, untuk mengakses ini saya telah membuat instance (bernama x) dari kelas Program yang memiliki bidang val dan kemudian menetapkan bidang val ke bidang newval di dalam metode utama statis. Ini benar-benar rumit untuk dilakukan. Untuk memperbaiki ketidaknyamanan, C# menggunakan bidang statis. Mari kita lihat penggunaan statis di sini.

Lihatlah contoh yang diberikan di bawah ini.

using System;
using System.Collections.Generic;
using System.Text;

namespace TestiClass{  
   class Program{  
       static int val = 20;  
       static void Main(string[] args){  
           Console.WriteLine(val);  
           Console.ReadKey();  
       }
   }
}
Output :

20

Coba bandingkan kedua contoh, Anda akan melihat perbedaannya. Di sini kami belum menggunakan instance kelas apa pun di dalam metode utama statis. Ini adalah penggunaan bidang statis dalam penerapan kita.

2. Static / Non-Static Methods

Bidang C# harus dideklarasikan di dalam kelas. Namun, jika kita mendeklarasikan metode atau bidang sebagai statis, kita dapat memanggil metode atau mengakses bidang menggunakan nama kelas. Tidak diperlukan instans. Kita juga dapat menggunakan kata kunci static ketika mendefinisikan sebuah field. Dengan fitur ini, kita dapat membuat satu bidang yang dibagikan di antara semua objek yang dibuat dari satu kelas. Bidang non-statis bersifat lokal untuk setiap instance objek.

Saat Anda mendefinisikan metode atau bidang statis, itu tidak memiliki akses ke bidang instans apa pun yang ditentukan untuk kelas; itu hanya dapat menggunakan bidang yang ditandai sebagai statis. Selain itu, ia dapat secara langsung memanggil hanya metode lain di kelas yang ditandai sebagai statis; metode atau bidang nonstatis (instance) pertama-tama memerlukan pembuatan objek untuk memanggilnya.

Berikut ini adalah contohnya.

using System;
using System.Collections.Generic;
using System.Text;

namespace TestiClass{
    class Program{
        public int calculation(int x, int y){
            int val = x * y;
            return val;
        }
        static void Main(string[] args){
            Program x = new Program();
            int newval = x.calculation(12,12);
            Console.WriteLine(newval);
            Console.ReadKey();
        }
    }
}
Dalam contoh di atas, kami memiliki metode non-statis bernama perhitungan. Dari metode utama (metode statis), saya mencoba mengakses metode non-statis itu dan untuk melakukan ini saya perlu membuat instance kelas di dalam metode utama (metode statis) karena metode statis hanya mengakses metode statis atau bidang statis dan perhitungan tidak statis di sini. Jadi, untuk mengakses ini saya telah membuat sebuah instance (bernama x) dari kelas Program yang memiliki metode perhitungan dan kemudian menetapkan nilai yang dihitung ke bidang newval di dalam metode utama statis. Ini benar-benar tugas yang merepotkan. Untuk memperbaiki ketidaknyamanan, C# menggunakan metode statis. Mari kita lihat penggunaan statis di sini.

Lihatlah contoh yang diberikan di bawah ini.

using System;
using System.Collections.Generic;
using System.Text;

namespace TestiClass{
    class Program{
        public static int calculation(int x, int y){
            int val = x * y;
            return val;
        }
        static void Main(string[] args){
            Console.WriteLine(calculation(12,12));
            Console.ReadKey();
        }
    }
}
Output :

144

Coba bandingkan kedua contoh, Anda akan melihat perbedaannya. Di sini kami belum menggunakan instance kelas apa pun di dalam metode utama statis. Ini adalah penggunaan metode statis dalam penerapan kita.



Access Modifiers di C# digunakan untuk menentukan cakupan aksesibilitas anggota kelas atau tipe kelas itu sendiri. Misalnya, kelas publik dapat diakses oleh semua orang tanpa batasan apa pun, sedangkan kelas internal hanya dapat diakses oleh assembly.

Semua tipe dan tipe anggota memiliki tingkat aksesibilitas. Tingkat aksesibilitas mengontrol apakah mereka dapat digunakan dari kode lain di rakitan Anda atau rakitan lain. Assembly adalah .dll atau .exe yang dibuat dengan mengompilasi satu atau lebih file .cs dalam satu kompilasi. Gunakan access modifiers berikut untuk menentukan aksesibilitas tipe atau anggota saat Anda mendeklarasikannya :
  • Public : Jenis atau anggota dapat diakses oleh kode lain di Assembly yang sama atau assembly lain yang mereferensikannya. Tingkat aksesibilitas anggota publik suatu tipe dikendalikan oleh tingkat aksesibilitas tipe itu sendiri.
  • Private : Tipe atau anggota hanya dapat diakses dengan kode di class atau struct yang sama.
  • Protected : Tipe atau anggota hanya dapat diakses dengan kode di kelas yang sama, atau di kelas yang diturunkan dari kelas itu.
  • Internal : Jenis atau anggota dapat diakses oleh kode apa pun di Assembly yang sama, tetapi tidak dari assembly lain. Dengan kata lain, tipe internal atau anggota dapat diakses dari kode yang merupakan bagian dari kompilasi yang sama.
  • Protected Internal : Jenis atau anggota dapat diakses oleh kode apa pun di Assembly di mana itu dideklarasikan, atau dari dalam kelas turunan di assembly lain.
  • Private Protected : Tipe atau anggota dapat diakses oleh tipe yang diturunkan dari kelas yang dideklarasikan di dalam assembly yang memuatnya.

A. Tabel Ringkasan

Di C# ada 6 tipe Access Modifier yang berbeda.



Contoh berikut menunjukkan cara menentukan access modifiers pada type dan member :

public class Sepeda
{
    public void Pedal() { }
}

Tidak semua access modifiers valid untuk semua tipe atau anggota dalam semua konteks. Dalam beberapa kasus, aksesibilitas anggota tipe dibatasi oleh aksesibilitas tipe yang memuatnya.

B. Jenis-jenis

Sekarang, mari buat contoh untuk memeriksa aksesibilitas setiap penentu akses.

1. Public

Dalam C#, Public modifier digunakan untuk menentukan bahwa akses tidak dibatasi, sehingga tipe atau anggota yang ditentukan dapat diakses oleh kode lain di Majelis saat ini atau Majelis lain yang mereferensikannya.

Berikut adalah contoh mendefinisikan anggota dengan Public modifier dalam bahasa pemrograman C#.

using System;

namespace InzaghisBlog
{
    class User
    {
        public string Name;
        public string Location;
        public int Age;
        public void GetUserDetails()
        {
           Console.WriteLine("Nama : {0}", Name);
           Console.WriteLine("Lokasi : {0}", Location);
           Console.WriteLine("Usia : {0}", Age);
        }
    }
    class Program
    {
        static void Main(string[] args)
        {
            User u = new User();
            u.Name = "Inzaghi Posuma";
            u.Location = "Tangerang";
            u.Age = 19;
            u.GetUserDetails();
            Console.WriteLine("\nPress Enter Key to Exit..");
            Console.ReadLine();
        }
    }
}
Jika Anda mengamati contoh di atas, kami mendefinisikan kelas Pengguna dengan variabel dan metode yang diperlukan menggunakan pengubah akses publik dan mencoba mengakses variabel dan metode tersebut di kelas lain dengan referensi objek kelas Pengguna.

Ketika Anda menjalankan program C# di atas, Anda akan mendapatkan hasil seperti yang ditunjukkan di bawah ini.

Nama : Inzaghi Posuma
Lokasi : Tangerang
Usia : 19

Press Enter Key to Exit..

Jika Anda mengamati hasil di atas, kami dapat mengakses variabel dan metode kelas Pengguna di kelas lain karena menentukan dengan penentu publik berdasarkan persyaratan kami.

Seperti yang telah dibahas, penentu akses publik akan membuat semua anggota atau tipe yang ditentukan tersedia untuk semua tipe dalam aplikasi kita.

2. Private

Dalam C#, Private modifier digunakan untuk menentukan bahwa akses terbatas pada tipe yang memuatnya, sehingga tipe atau anggota yang ditentukan hanya dapat diakses oleh kode di kelas atau struktur yang sama.

Berikut adalah contoh mendefinisikan anggota dengan Private modifier dalam bahasa pemrograman C#.

using System;

namespace InzaghisBlog
{
    class User
    {
        private string Name;
        private string Location;
        private int Age;
        private void GetUserDetails()
        {
            Console.WriteLine("Nama : {0}", Name);
            Console.WriteLine("Lokasi : {0}", Location);
            Console.WriteLine("Usia : {0}", Age);
        }
    }
    class Program
    {
        static void Main(string[] args)
        {
            User u = new User();
            // Complier Error
            // These are inaccessible due to private specifier
            u.Name = "Inzaghi Posuma";
            u.Location = "Tangerang";
            u.Age = 19;
            u.GetUserDetails();
            Console.WriteLine("\nPress Enter Key to Exit..");
            Console.ReadLine();
        }
    }
}
Jika Anda mengamati contoh di atas, kami mendefinisikan kelas Pengguna dengan variabel dan metode yang diperlukan menggunakan pengubah akses pribadi dan mencoba mengakses variabel dan metode tersebut di kelas lain dengan referensi objek kelas Pengguna.

Ketika Anda menjalankan program C# di atas, Anda akan mendapatkan kesalahan waktu kompilasi seperti yang ditunjukkan di bawah ini.

Compilation error (line 24, col 15): 'User.Name' is inaccessible due to its protection level
Compilation error (line 25, col 15): 'User.Location' is inaccessible due to its protection level
Compilation error (line 26, col 15): 'User.Age' is inaccessible due to its protection level
Compilation error (line 27, col 15): 'User.GetUserDetails()' is inaccessible due to its protection level
Compilation error (line 7, col 23): Field 'User.Name' is never assigned to, and will always have its default value null
Compilation error (line 8, col 23): Field 'User.Location' is never assigned to, and will always have its default value null
Compilation error (line 9, col 20): Field 'User.Age' is never assigned to, and will always have its default value 0

Jika Anda mengamati hasil di atas, kami mendapatkan kesalahan waktu kompilasi karena anggota pengubah pribadi dari kelas Pengguna dirujuk ke kelas lain.

Seperti yang telah dibahas, tipe atau anggota pengubah pribadi hanya dapat diakses dengan kode di kelas atau struktur yang sama.

3. Protected

Dalam C#, Protected modifier digunakan untuk menentukan bahwa akses dibatasi pada tipe yang mengandung atau tipe yang diturunkan dari kelas yang mengandung, sehingga tipe atau anggota hanya dapat diakses dengan kode di kelas yang sama atau di kelas turunan.

Berikut adalah contoh mendefinisikan anggota dengan Protected modifier dalam bahasa pemrograman C#.

using System;

namespace InzaghisBlog
{
    class User
    {
        protected string Name;
        protected string Location;
        protected int Age;
        protected void GetUserDetails()
        {
            Console.WriteLine("Nama : {0}", Name);
            Console.WriteLine("Lokasi : {0}", Location);
            Console.WriteLine("Usia : {0}", Age);
        }
    }
    class Program
    {
        static void Main(string[] args)
        {
            User u = new User();
            // Complier Error
            // These are inaccessible due to protected specifier
            u.Name = "Inzaghi Posuma";
            u.Location = "Tangerang";
            u.Age = 19;
            u.GetUserDetails();
            Console.WriteLine("\nPress Enter Key to Exit..");
            Console.ReadLine();
        }
    }
}
Jika Anda mengamati contoh di atas, kami mendefinisikan kelas Pengguna dengan variabel dan metode yang diperlukan menggunakan pengubah akses yang dilindungi dan mencoba mengakses variabel dan metode tersebut di kelas lain dengan referensi objek kelas Pengguna.

Ketika Anda menjalankan program c# di atas, Anda akan mendapatkan kesalahan waktu kompilasi seperti yang ditunjukkan di bawah ini.

Compilation error (line 24, col 15): 'User.Name' is inaccessible due to its protection level
Compilation error (line 25, col 15): 'User.Location' is inaccessible due to its protection level
Compilation error (line 26, col 15): 'User.Age' is inaccessible due to its protection level
Compilation error (line 27, col 16): 'User.GetUserDetails()' is inaccessible due to its protection level
Compilation error (line 7, col 27): Field 'User.Name' is never assigned to, and will always have its default value null
Compilation error (line 9, col 24): Field 'User.Age' is never assigned to, and will always have its default value 0
Compilation error (line 8, col 27): Field 'User.Location' is never assigned to, and will always have its default value null

Jika Anda mengamati hasil di atas, kami mendapatkan kesalahan waktu kompilasi karena anggota pengubah yang dilindungi dari kelas Pengguna dirujuk ke kelas lain.

Seperti yang telah dibahas, anggota kelas dasar yang dilindungi dapat diakses di kelas turunan hanya ketika akses terjadi melalui tipe kelas turunan.

Berikut adalah contoh mengakses anggota kelas dasar yang dilindungi di kelas turunan melalui tipe kelas turunan.

using System;

namespace InzaghisBlog
{
    class User
    {
        protected string Name;
        protected string Location;
        protected int Age;
        protected void GetUserDetails()
        {
            Console.WriteLine("Nama : {0}", Name);
            Console.WriteLine("Lokasi : {0}", Location);
            Console.WriteLine("Usia : {0}", Age);
        }
    }
    class Program: User
    {
        static void Main(string[] args)
        {
            User u = new User();
            Program p = new Program();
            // Complier Error
            // protected members can only accessible with derived classes
            //u.Name = "Inzaghi Posuma";
            p.Name = "Inzaghi Posuma";
            p.Location = "Tangerang";
            p.Age = 19;
            p.GetUserDetails();
            Console.WriteLine("\nPress Enter Key to Exit..");
            Console.ReadLine();
        }
    }
}
Jika Anda mengamati contoh di atas, kami mengakses anggota kelas dasar (Pengguna) yang dilindungi menggunakan referensi kelas turunan (Program). Jika kami menghapus komentar pada kode yang dikomentari, kami akan mendapatkan kesalahan waktu kompilasi karena kami mencoba mengakses anggota yang dilindungi dengan referensi kelas dasar (Pengguna) alih-alih kelas turunan (Program).

Ketika Anda menjalankan program C# di atas, Anda akan mendapatkan hasil seperti yang ditunjukkan di bawah ini.

Nama : Inzaghi Posuma
Lokasi : Tangerang
Usia : 19

Press Enter Key to Exit..

Ini adalah bagaimana Anda dapat menggunakan pengubah yang dilindungi dalam aplikasi C# kami untuk membatasi akses ke tipe atau anggota di kelas yang sama atau kelas turunan berdasarkan persyaratan kami.

4. Internal

Dalam C#, Pengubah Internal digunakan untuk menentukan bahwa akses terbatas pada rakitan saat ini. Jenis atau anggota dapat diakses oleh kode apa pun di Majelis yang sama tetapi tidak dari Majelis lain.

Berikut adalah contoh mendefinisikan anggota dengan pengubah internal dalam bahasa pemrograman C#.

using System;

namespace InzaghisBlog
{
    class User
    {
        internal string Name;
        internal string Location;
        internal int Age;
        internal void GetUserDetails()
        {
            Console.WriteLine("Nama : {0}", Name);
            Console.WriteLine("Lokasi : {0}", Location);
            Console.WriteLine("Usia : {0}", Age);
        }
    }
    class Program
    {
        static void Main(string[] args)
        {
            User u = new User();
            u.Name = "Inzaghi Posuma";
            u.Name = "Inzaghi Posuma";
            u.Location = "Tangerang";
            u.Age = 19;
            u.GetUserDetails();
            Console.WriteLine("\nPress Enter Key to Exit..");
            Console.ReadLine();
        }
    }
}
Jika Anda mengamati contoh di atas, kami mendefinisikan kelas Pengguna dengan variabel dan metode yang diperlukan menggunakan pengubah akses internal dan mencoba mengakses variabel dan metode tersebut di kelas lain dengan referensi objek kelas Pengguna.

Ketika Anda menjalankan program C# di atas, Anda akan mendapatkan hasil seperti yang ditunjukkan di bawah ini.

Nama : Inzaghi Posuma
Lokasi : Tangerang
Usia : 19

Press Enter Key to Exit..

Jika Anda mengamati hasil di atas, kami dapat mengakses variabel dan metode kelas Pengguna di kelas lain karena menentukan penentu internal berdasarkan persyaratan kami.

Seperti yang dibahas dalam C# tipe internal atau anggota dapat diakses dalam file Majelis yang sama.

5. Protected Internal

Dalam C#, Protected internal modifier digunakan untuk menentukan bahwa akses terbatas pada rakitan saat ini atau tipe yang diturunkan dari kelas yang memuatnya. Jenis atau anggota dapat diakses oleh kode apa pun di Majelis yang sama atau kelas turunan apa pun di Majelis lain.

Berikut adalah contoh mendefinisikan anggota dengan pengubah internal yang dilindungi dalam bahasa pemrograman C#.

using System;

namespace InzaghisBlog
{
    class User
    {
        protected internal string Name;
        protected internal string Location;
        protected internal int Age;
        protected internal void GetUserDetails()
        {
            Console.WriteLine("Nama : {0}", Name);
            Console.WriteLine("Lokasi : {0}", Location);
            Console.WriteLine("Usia : {0}", Age);
        }
    }
    class Program
    {
       static void Main(string[] args)
       {
            User u = new User();
            u.Name = "Inzaghi Posuma";
            u.Name = "Inzaghi Posuma";
            u.Location = "Tangerang";
            u.Age = 19;
            u.GetUserDetails();
            Console.WriteLine("\nPress Enter Key to Exit..");
            Console.ReadLine();
       }
    }
}
Jika Anda mengamati contoh di atas, kami mendefinisikan kelas Pengguna dengan variabel dan metode yang diperlukan menggunakan pengubah akses internal yang dilindungi dan mencoba mengakses variabel dan metode tersebut di kelas lain dengan referensi objek kelas Pengguna.

Ketika Anda menjalankan program C# di atas, kita akan mendapatkan hasil seperti gambar di bawah ini.

Nama : Inzaghi Posuma
Lokasi : Tangerang
Usia : 19

Press Enter Key to Exit..

Jika Anda mengamati hasil di atas, kami dapat mengakses variabel dan metode kelas Pengguna di kelas lain karena menentukan penentu internal berdasarkan persyaratan kami.

Seperti yang dibahas dalam C#, tipe atau anggota internal yang dilindungi dapat diakses dari rakitan saat ini atau jenis yang diturunkan dari kelas yang memuatnya di rakitan lain.

6. Private Protected

Di C#, pengubah terproteksi pribadi tersedia dari versi 7.2. Ini digunakan untuk menentukan bahwa akses terbatas pada kelas yang berisi atau tipe yang diturunkan dari kelas yang berisi dalam perakitan saat ini. Tipe atau anggota dapat diakses dengan kode di kelas yang sama atau kelas turunan dalam perakitan kelas dasar.

Berikut adalah contoh mendefinisikan anggota dengan pengubah terproteksi pribadi dalam bahasa pemrograman C#.

using System;

namespace Tutlane
{
    class User
    {
        private protected string Name;
        private protected string Location;
        private protected int Age;
        private protected void GetUserDetails()
        {
            Console.WriteLine("Nama : {0}", Name);
            Console.WriteLine("Lokasi : {0}", Location);
            Console.WriteLine("Usia : {0}", Age);
        }
    }
    class Program: User
    {
        static void Main(string[] args)
        {
            User u = new User();
            Program p = new Program();
            // Complier Error
            // protected members can only accessible with derived classes
            //u.Name = "Inzaghi Posuma";
            p.Name = "Inzaghi Posuma";
            p.Location = "Tangerang";
            p.Age = 19;
            p.GetUserDetails();
            Console.WriteLine("\nPress Enter Key to Exit..");
            Console.ReadLine();
        }
    }
}
Jika Anda mengamati contoh di atas, kami mengakses anggota kelas dasar (Pengguna) yang dilindungi pribadi menggunakan referensi kelas turunan (Program). Jika kami menghapus komentar pada kode yang dikomentari, kami akan mendapatkan kesalahan waktu kompilasi karena kami mencoba mengakses anggota yang dilindungi pribadi dengan referensi kelas dasar (Pengguna) alih-alih kelas turunan (Program).

Ketika Anda menjalankan program C# di atas, Anda akan mendapatkan hasil seperti yang ditunjukkan di bawah ini.

Nama : Inzaghi Posuma
Lokasi : Tangerang
Usia : 19

Press Enter Key to Exit..

Ini adalah bagaimana kita dapat menggunakan pengubah terproteksi pribadi dalam aplikasi C# untuk membatasi kelas atau tipe yang mengandung yang berasal dari kelas yang mengandung dalam perakitan saat ini.


OOP PEWARISAN (INHERITANCE OOP)

A. Inheritance


Salah satu konsep terpenting dalam pemrograman berorientasi objek adalah pewarisan. Warisan memungkinkan kita untuk mendefinisikan kelas dalam kaitannya dengan kelas lain, yang membuatnya lebih mudah untuk membuat dan memelihara aplikasi. Ini juga memberikan kesempatan untuk menggunakan kembali fungsionalitas kode dan mempercepat waktu implementasi.

Saat membuat kelas, alih-alih menulis anggota data dan fungsi anggota yang benar-benar baru, pemrogram dapat menetapkan bahwa kelas baru harus mewarisi anggota kelas yang ada. Kelas yang sudah ada ini disebut kelas dasar, dan kelas baru disebut sebagai kelas turunan.

1. Base Class dan Derived Class

Sebuah kelas dapat diturunkan dari lebih dari satu kelas atau antarmuka, yang berarti bahwa ia dapat mewarisi data dan fungsi dari beberapa kelas dasar atau antarmuka. Sintaks yang digunakan dalam C# untuk membuat kelas turunan adalah sebagai berikut.

<acess-specifier> class <base_class> {
...
}

class <derived_class> : <base_class> {
...
}

Perhitungkan kelas dasar Shape dan kelas turunannya Rectangle :

using System;

class Shape {
    public void setWidth(int w) {
        width = w;
    }
    public void setHeight(int h) {
        height = h;
    }
    protected int width;
    protected int height;
}

// Derived class
class Rectangle : Shape {
    public int getArea() {
        return (width * height);
    }
}
class RectangleTester {
    static void Main(string[] args) {
        Rectangle Rect = new Rectangle();

        Rect.setWidth(5);
        Rect.setHeight(7);

        // Print the area of the object.
        Console.WriteLine("Luas total : {0}",  Rect.getArea());
        Console.ReadKey();
    }
}
Output :

Luas total : 35

2. Inisialsasi Base Class

Kelas turunan mewarisi variabel anggota kelas dasar dan metode anggota. Oleh karena itu objek kelas super harus dibuat sebelum subkelas dibuat. Anda dapat memberikan instruksi untuk inisialisasi superclass dalam daftar inisialisasi anggota.

Program berikut menunjukkan ini :

using System;

class Rectangle {
       
    // Member variables
    protected double length;
    protected double width;
       
    public Rectangle(double l, double w) {
        length = l;
        width = w;
    }
    public double GetArea() {
        return length * width;
    }
    public void Display() {
        Console.WriteLine("Panjang : {0}", length);
        Console.WriteLine("Lebar : {0}", width);
        Console.WriteLine("Luas : {0}", GetArea());
        }
} // End class Rectangle  
class Tabletop : Rectangle {
    private double cost;
    public Tabletop(double l, double w) : base(l, w) { }
       
    public double GetCost() {
        double cost;
        cost = GetArea() * 70;
        return cost;
    }
    public void Display() {
        base.Display();
        Console.WriteLine("Harga : {0}", GetCost());
    }
}
class ExecuteRectangle {
    static void Main(string[] args) {
        Tabletop t = new Tabletop(4.5, 7.5);
        t.Display();
        Console.ReadLine();
    }
}
Output :

Panjang : 4.5
Lebar : 7.5
Luas : 33.75
Harga : 2362.5

B. Polymorphism


1. Polymorphism dalam C#

Polymorphism (Polimorfisme) dari Bahasa Yunani berarti "banyak bentuk", dan itu terjadi ketika kita memiliki banyak kelas yang terkait satu sama lain melalui pewarisan. Seperti yang telah kita bahas di atas, Inheritance memungkinkan kita mewarisi bidang dan metode dari kelas lain. Polymorphism menggunakan metode tersebut untuk melakukan tugas yang berbeda. Ini memungkinkan kita untuk melakukan satu tindakan dengan cara yang berbeda.

2. Jenis-jenis Polymorphism

Ada 2 (Dua) Jenis Polymorphism dalam C#, yaitu :
  • Static / Compile Time Polymorphism.
  • Dynamic / Runtime Polymorphism.


3. Polymorphism Waktu Statis atau Kompilasi

Ini juga dikenal sebagai Pengikatan Awal. Metode overloading adalah contoh dari Polimorfisme Statis. Dalam overloading, metode/fungsi memiliki nama yang sama tetapi tanda tangan yang berbeda. Ini juga dikenal sebagai Polimorfisme Waktu Kompilasi karena keputusan metode mana yang akan dipanggil dibuat pada waktu kompilasi. Overloading adalah konsep di mana nama metode sama dengan set parameter yang berbeda.

Di sini kompiler C# memeriksa jumlah parameter yang dilewatkan dan jenis parameter dan membuat keputusan metode mana yang akan dipanggil dan itu menimbulkan kesalahan jika tidak ada metode yang cocok ditemukan.

Dalam contoh berikut, sebuah kelas memiliki dua metode dengan nama "Tambah" yang sama tetapi dengan parameter input yang berbeda (metode pertama memiliki tiga parameter dan metode kedua memiliki dua parameter).

using System;

public class TestData {
    public int Add(int a, int b, int c) {
        return a + b + c;
    }
    public int Add(int a, int b) {
        return a + b;
    }
}
class Program {
    static void Main(string[] args) {  
        TestData dataClass = new TestData();
        int add2 = dataClass.Add(45, 34, 67);
        int add1 = dataClass.Add(23, 34);
    }
}


4. Polymorphism Dinamis / Runtime

Polimorfisme dinamis/runtime juga dikenal sebagai late binding. Di sini, nama metode dan tanda tangan metode (jumlah parameter dan tipe parameter harus sama dan mungkin memiliki implementasi yang berbeda). Metode overriding adalah contoh polimorfisme dinamis.

Metode overriding dapat dilakukan dengan menggunakan pewarisan. Dengan metode overriding dimungkinkan untuk kelas dasar dan kelas turunan memiliki nama metode yang sama dan sesuatu yang sama. Kompilator tidak akan mengetahui metode yang tersedia untuk mengesampingkan fungsionalitas, sehingga kompiler tidak membuat kesalahan pada waktu kompilasi. Kompiler akan memutuskan metode mana yang akan dipanggil saat runtime dan jika tidak ada metode yang ditemukan maka ia akan membuat kesalahan.

using System;

public class Drawing{  
    public virtual double Area(){  
        return 0;  
    }  
}  
 
public class Circle : Drawing {  
    public double Radius { get; set; }  
        public Circle(){  
            Radius = 5;  
        }
    public override double Area(){  
        return (3.14) * Math.Pow(Radius, 2);  
    }  
}  
 
public class Square : Drawing {  
    public double Length { get; set; }  
        public Square(){  
            Length = 6;
        }  
    public override double Area() {  
        return Math.Pow(Length, 2);  
    }  
}  
 
public class Rectangle : Drawing {  
    public double Height { get; set; }  
    public double Width { get; set; }  
    public Rectangle(){  
        Height = 5.3;
        Width = 3.4;
    }  
    public override double Area(){  
        return Height * Width;  
    }  
}  
 
class Program{  
    static void Main(string[] args){  
 
        Drawing circle = new Circle();  
        Console.WriteLine("Area : " + circle.Area());  
 
        Drawing square = new Square();  
        Console.WriteLine("Area : " + square.Area());  
 
        Drawing rectangle = new Rectangle();  
        Console.WriteLine("Area : " + rectangle.Area());  
    }  
}


Output :

Area : 78.5
Area : 36
Area : 18.02

Kompilator memerlukan metode Area() dan berhasil dikompilasi tetapi versi yang tepat dari method Area() tidak ditentukan pada waktu kompilasi tetapi ditentukan pada waktu proses. Akhirnya override method harus memiliki nama dan tanda tangan yang sama (jumlah parameter dan tipe), seperti metode virtual atau abstrak yang didefinisikan dalam metode kelas dasar dan yang ditimpa di kelas turunan.

Metode atau fungsi dari kelas dasar tersedia untuk kelas turunan (turunan) tanpa menggunakan kata kunci "override". Kompiler menyembunyikan fungsi atau metode dari kelas dasar. Konsep ini dikenal sebagai shadowing atau metode penyembunyian. Anda mungkin menemukan perbedaan antara menimpa dan membayangi di sini.

5. Mencegah Kelas Berasal dari Menimpa Anggota Virtual (Overriding Virtual Member)

Anggota virtual tetap "virtual" tanpa batas. Dengan kata lain, anggota virtual tetap "virtual" terlepas dari berapa banyak kelas yang telah ada antara anggota virtual dan kelas yang awalnya mendeklarasikannya. Misalnya, jika kelas X memiliki metode virtual "A" dan kelas Y diturunkan dari X dan kelas Z diturunkan dari Y, kelas Z mewarisi metode virtual "A" dan menimpanya.

public class X  
{  
    public virtual void A()  
    {  
    }  
}  
public class Y : X  
{  
    public override void A()  
    {  
    }  
}  

Kelas turunan dapat menghentikan pewarisan virtual dengan mendeklarasikan anggota timpa sebagai "disege (sealed)l".

public class Y : X  
{
    public sealed override void A()  
    {
    }
}

6. Accessing Base class virtual member

Menggunakan kata kunci "base", kelas turunan dapat mengakses metode.

public class X  
{  
    public virtual void A()  
    {  
    }  
}  
public class Y : X  
{  
    public override void A()  
    {  
        base.A();  
    }  
} 

Ringkasan :
  • Arti dari Polimorfisme adalah satu nama yang memiliki banyak bentuk.
  • Berikut ini adalah dua jenis Polimorfisme:
    • Polimorfisme statis atau waktu kompilasi (misalnya, kelebihan metode dan kelebihan operator).
    • Polimorfisme dinamis atau runtime (misalnya, penggantian).
  • Metode Overriding berbeda dari shadowing.
  • Menggunakan kata kunci "baru", kita dapat menyembunyikan anggota kelas dasar.
  • Kita dapat mencegah kelas turunan dari menimpa anggota virtual.
  • Kita dapat mengakses anggota virtual kelas dasar dari kelas turunan.

C. Abstraction


Abstraksi data adalah proses menyembunyikan detail tertentu dan hanya menampilkan informasi penting kepada pengguna. Abstraction dapat dicapai dengan kelas atau antarmuka abstrak.

Kata kunci abstract digunakan untuk kelas dan metode (class and methods) :

Kelas abstrak : adalah kelas terbatas yang tidak dapat digunakan untuk membuat objek (untuk mengaksesnya harus diwarisi dari kelas lain).

Metode abstrak : hanya dapat digunakan di kelas abstrak, dan tidak memiliki badan. Tubuh disediakan oleh kelas turunan (diwarisi dari).

1. Abstract Base Class

Ada beberapa poin penting tentang Kelas Dasar Abstrak :
  • Kelas Basis Abstrak tidak dapat dipakai; itu berarti objek dari kelas itu tidak dapat dibuat.
  • Kelas yang memiliki kata kunci abstrak dengan beberapa metodenya (tidak semua) dikenal sebagai Kelas Dasar Abstrak.
  • Kelas yang memiliki kata kunci Abstrak dengan semua metodenya dikenal sebagai Kelas Dasar Abstrak murni.
  • Metode kelas abstrak yang tidak memiliki implementasi dikenal sebagai "operasi". Ini dapat didefinisikan sebagai abstract void method();
  • Kelas abstrak menampung metode tetapi implementasi sebenarnya dari metode tersebut dibuat di kelas turunan.
Yuk kita lihat kode ini!

abstract class animal { 
    public abstract void eat();    
    public void sound() { 
        Console.WriteLine("Cat can sound");    
    } 
}

Ini adalah Kelas Basis Abstrak, jika saya membuat kedua metodenya abstrak maka kelas ini akan menjadi Kelas Basis Abstrak murni.
 
Sekarang, kita menurunkan kelas 'kucing' dari kelas hewan.

abstract class animal {
    public abstract void eat();    
    public void sound() {
        Console.WriteLine("Cat can sound");    
    }
}
class cat : animal {
    public override void eat() {
        Console.WriteLine("Cat can eat");    
    }
}

Di sini Anda dapat melihat bahwa kami memiliki 2 metode di Kelas Dasar Abstrak, metode eat() tidak memiliki implementasi; itulah sebabnya ia dideklarasikan sebagai 'abstrak' sedangkan metode sound() memiliki tubuhnya sendiri sehingga tidak dideklarasikan sebagai 'abstrak'.
 
Di kelas turunan, kami memiliki metode nama yang sama tetapi metode ini memiliki tubuhnya. Kami melakukan abstraksi di sini sehingga kami dapat mengakses metode kelas turunan tanpa masalah.

Mari kita lihat!

using System;

class program  {
    abstract class animal {
        public abstract void eat();  
        public void sound(){
            Console.WriteLine("Cat can sound");  
        }
    }
    class cat : animal {
        public override void eat(){
            Console.WriteLine("Cat can eat");  
        }
    }
    static void Main (string[] args){
        cat mycat = new cat();  
        animal thePet = mycat;  
        thePet.eat();  
        mycat.sound();  
    }
}
Output :

Cat can eat
Cat can sound

Terakhir, kita membuat Obyek 'mycat' dari kelas Kucing, tetapi kami tidak membuat instance objek dari 'animal' Kelas Dasar Abstrak.
 
Menurut Ivor Horton (seorang programmer Java) suatu objek tidak dapat dipakai, tetapi kita dapat mendeklarasikan variabel dari tipe Kelas Abstrak. Jika pernyataan ini benar maka kemungkinannya adalah :
 
animal thePet;
 
Ini adalah objek yang dideklarasikan sebagai thePet dan tipe datanya adalah 'animal' kelas dasar abstrak.

Kita dapat menggunakan Object ini untuk menyimpan Object dari subclass.
 
Dalam kode di atas, kita mendeklarasikan Obyek 'thePet', dari jenis hewan (Kelas Basis Abstrak) dan hanya menyalin objek dari objek lain (hanya referensi yang disalin karena termasuk dalam tipe referensi). Sekarang kita dapat menggunakan objek 'thePet' seperti halnya objek 'mycat'.


OOP LANJUTAN 2

A. Encapsulation


Enkapsulasi (Encapsulation) adalah konsep membungkus data menjadi satu kesatuan. Ini mengumpulkan anggota data dan fungsi anggota ke dalam satu unit yang disebut kelas. Tujuan enkapsulasi adalah untuk mencegah perubahan data dari luar. Data ini hanya dapat diakses oleh fungsi pengambil kelas.

Kelas yang dienkapsulasi sepenuhnya memiliki fungsi pengambil dan penyetel yang digunakan untuk membaca dan menulis data. Kelas ini tidak mengizinkan akses data secara langsung.

1. Encapsulation menggunakan Accestor dan Mutator

Di sini, kita membuat contoh di mana kami memiliki kelas yang merangkum properti dan kita mendefinisikan accessor (get method) dan mutator (set method).

using system;  
public class Department {  
    private string departname;.......  
    // Accessor.  
    public string GetDepartname() {  
        return departname;  
    }  
    // Mutator.  
    public void SetDepartname(string a) {  
        departname = a;  
    }  
}  

Seperti cara diatas kita bisa melindungi data pribadi dari dunia luar. Di sini kami menggunakan dua metode terpisah untuk menetapkan dan mendapatkan data yang diperlukan.

public static int Main(string[] args) {  
    Department d = new Department();  
    d.SetDepartname("ELECTRONICS");  
    Console.WriteLine("The Department is :" + d.GetDepartname());  
    return 0;  
}  

Dalam contoh di atas, kita tidak dapat mengakses namadepar data pribadi dari instance objek. Kami memanipulasi data hanya menggunakan dua metode tersebut.

2. Encapsulation menggunakan Properti

Properties adalah fitur bahasa baru yang diperkenalkan dengan C#. Hanya beberapa bahasa yang mendukung properti ini. Properti di C# membantu dalam melindungi bidang di kelas dengan membaca dan menulis untuk itu. Metode pertama itu sendiri bagus tetapi Enkapsulasi dapat diselesaikan lebih lancar dengan properti.

Sekarang mari kita lihat sebuah contoh.

using System;

public class Department {
    private string departname;
    public string Departname {
        get {
            return departname;
        }
        set {
            departname = value;
        }  
    }  
}  
public class Departmentmain {
    public static int Main(string[] args) {
        Department d = new Department();
        d.departname = "Communication";
        Console.WriteLine("The Department is :{0}", d.Departname);
        return 0;
    }
}
Dari contoh di atas kita melihat penggunaan Enkapsulasi dengan menggunakan properti. Properti ini memiliki dua accessor get and set. Aksesor get mengembalikan nilai dari beberapa bidang properti. Aksesor yang ditetapkan menetapkan nilai dari beberapa bidang properti dengan konten "nilai". Properti dapat dibuat hanya-baca. Ini dicapai dengan hanya memiliki pengakses get dalam implementasi properti.

a. Read Only Property

using system;

public class ReadDepartment {
    private string departname;
    public ReadDepartment(string avalue) {
        departname = avalue;
    }
    public string Departname {
        get {
            return departname;
        }
    }
}
public class ReadDepartmain {
    public static int Main(string[] args) {
        ReadDepartment d = new ReadDepartment("COMPUTERSCIENCE");
        Console.WriteLine("The Department is: {0}", d.Departname);
        return 0;
    }
}
Dalam contoh di atas kita melihat bagaimana mengimplementasikan properti read-only. Kelas ReadDepartment memiliki properti Departname yang hanya mengimplementasikan get accessor. Itu meninggalkan set accessor. Kelas khusus ini memiliki konstruktor, yang menerima parameter string. Metode Main dari kelas ReadDepartmain membuat objek baru bernama d. Instansiasi objek d menggunakan konstruktor ReadDepartment yang mengambil parameter string. Karena program di atas bersifat read-only, kami tidak dapat menetapkan nilai ke nama bidang berangkat dan kami hanya membaca atau mendapatkan nilai data dari bidang tersebut. Properties dapat dibuat juga Write-only. Ini dicapai dengan hanya memiliki satu set accessor dalam implementasi properti.

b. Write Only Property

using system;

public class WriteDepartment {
    private string departname;
    public string Departname {
        set {
            departname = value;
            Console.WriteLine("The Department is :{0}", departname);
        }
    }
}
public class WriteDepartmain {
    public static int Main(string[] args) {
        WriteDepartment d = new WriteDepartment();
        d.departname = "COMPUTERSCIENCE";
        return 0;
    }
}
Dalam contoh di atas kita melihat bagaimana mengimplementasikan properti Write-only. Kelas WriteDepartment sekarang memiliki properti Departname yang hanya mengimplementasikan set accessor. Itu meninggalkan get accessor. Metode set accessor divariasikan sedikit dengan mencetak nilai namadepartemen setelah ditetapkan.

B. Enumeration Types


Tipe Enumerasi (atau tipe enum) adalah tipe nilai yang ditentukan oleh sekumpulan konstanta bernama dari tipe numerik integral yang mendasarinya. Untuk menentukan jenis Enumerasi, gunakan kata kunci enum dan tentukan nama anggota enum :

enum Season
{
    Spring,
    Summer,
    Autumn,
    Winter
}

Secara default, nilai konstanta terkait dari anggota enum bertipe int; mereka mulai dengan nol dan bertambah satu mengikuti urutan teks definisi. Anda dapat secara eksplisit menentukan tipe numerik integral lainnya sebagai tipe yang mendasari tipe enumerasi. Anda juga dapat secara eksplisit menentukan nilai konstanta terkait, seperti yang ditunjukkan contoh berikut :

enum ErrorCode : ushort
{
    None = 0,
    Unknown = 1,
    ConnectionLost = 100,
    OutlierReading = 200
}

Anda tidak dapat mendefinisikan metode di dalam definisi tipe enumerasi. Untuk menambahkan fungsionalitas ke tipe enumerasi, buat metode ekstensi.

Nilai default dari tipe enumerasi E adalah nilai yang dihasilkan oleh ekspresi (E)0, bahkan jika nol tidak memiliki anggota enum yang sesuai.

Anda menggunakan tipe enumerasi untuk mewakili pilihan dari sekumpulan nilai yang saling eksklusif atau kombinasi pilihan. Untuk mewakili kombinasi pilihan, tentukan tipe enumerasi sebagai flag bit.

1. Enum di dalam Kelas

Untuk membuat enum, gunakan kata kunci enum (bukan kelas atau antarmuka), dan pisahkan item enum dengan koma :

using System;

enum Level{
    Low,
    Medium,
    High
}

class Program{
    static void Main(string[] args){
    Level myVar = Level.Medium;
    Console.WriteLine(myVar);
    }
}
Output :

Medium

2. Enum Values

Secara default, item pertama dari Enum memiliki nilai 0. Yang kedua memiliki nilai 1, dan seterusnya.

Untuk mendapatkan nilai integer dari sebuah item, Anda harus secara eksplisit mengonversi item tersebut menjadi int :

using System;

class Program {
    enum Bulan {
        Januari,    // 0
        Februari,   // 1
        Maret,      // 2
        April,      // 3
        Mei,        // 4
        Juni,       // 5
        Juli,       // 6
        Agustus,    // 7
        September,  // 8
        Oktober,    // 9
        November,   // 10
        Desember    // 11
    }
    static void Main(string[] args) {
        int myNum = (int) Bulan.September;
        Console.WriteLine(myNum);
    }
}
Output :

8

Anda juga dapat menetapkan nilai enum Anda sendiri, dan item berikutnya akan memperbarui nomor yang sesuai :

using System;

class Program {
    enum Bulan {
        Januari,    // 0
        Februari,   // 1
        Maret,      // 2
        April,      // 3
        Mei,        // 4
        Juni,       // 5
        Juli = 10,  // 10
        Agustus,    // 11
        September,  // 12
        Oktober,    // 13
        November,   // 14
        Desember    // 15
    }
    static void Main(string[] args) {
        int myNum = (int) Bulan.September;
        Console.WriteLine(myNum);
    }
}
Output :

12

3. Enum dalam Pernyataan Beralih

Enum sering digunakan dalam pernyataan switch untuk memeriksa nilai yang sesuai :

using System;

class Program {
    enum Level {
        Low,
        Medium,
        High
    }
    static void Main(string[] args) {
        Level myVar = Level.Medium;
        switch(myVar) {
            case Level.Low:
                Console.WriteLine("Level Rendah");
                break;
            case Level.Medium:
                Console.WriteLine("Level Sedang");
                break;
            case Level.High:
                Console.WriteLine("Level Tinggi");
                break;
        }    
    }
}
Output :

Level Sedang


OOP EXECPTIONS

A. Exceptions


Fitur penanganan pengecualian bahasa C# membantu Anda menangani situasi tak terduga atau luar biasa yang terjadi saat program sedang berjalan. Penanganan pengecualian menggunakan kata kunci try, catch, dan finally untuk mencoba tindakan yang mungkin tidak berhasil, untuk menangani kegagalan saat Anda memutuskan bahwa hal itu wajar untuk dilakukan, dan untuk membersihkan sumber daya sesudahnya. Pengecualian dapat dihasilkan oleh runtime bahasa umum (CLR), oleh .NET atau perpustakaan pihak ketiga, atau dengan kode aplikasi. Pengecualian dibuat dengan menggunakan kata kunci throw.

Dalam banyak kasus, eksepsi mungkin dilontarkan bukan oleh metode yang telah dipanggil oleh kode Anda secara langsung, tetapi oleh metode lain yang lebih jauh di tumpukan panggilan. Ketika eksepsi dilempar, CLR akan melepas tumpukan, mencari metode dengan blok tangkap untuk tipe pengecualian tertentu, dan CLR akan mengeksekusi blok tangkap pertama yang ditemukannya. Jika tidak menemukan blok tangkapan yang sesuai di mana pun di tumpukan panggilan, itu akan menghentikan proses dan menampilkan pesan kepada pengguna.

Dalam contoh ini, sebuah metode menguji pembagian dengan nol dan menangkap kesalahannya. Tanpa penanganan eksepsi, program ini akan berakhir dengan kesalahan DivideByZeroException yang tidak tertangani.

C# .NET menyertakan kelas pengecualian (exception class) bawaan untuk setiap kemungkinan kesalahan. Kelas Exception adalah kelas dasar dari semua kelas pengecualian.

Berikut ini adalah hierarki kelas pengecualian di .NET :


1. Built-in Exception Classes (Kelas Pengecualian Bawaan)

Tabel berikut mencantumkan kelas pengecualian bawaan yang penting di .NET.

Exception Class
Description
Raised when a non-null argument that is passed to a method is invalid.
Raised when null argument is passed to a method.
Raised when the value of an argument is outside the range of valid values.
Raised when an integer value is divide by zero.
Raised when a physical file does not exist at the specified location.
Raised when a value is not in an appropriate format to be converted from a string by a conversion method such as Parse.
Raised when an array index is outside the lower or upper bounds of an array or collection.
Raised when a method call is invalid in an object's current state.
Raised when the specified key for accessing a member in a collection is not exists.
Raised when a method or operation is not supported.
Raised when program access members of null object.
Raised when an arithmetic, casting, or conversion operation results in an overflow.
Raised when a program does not get enough memory to execute the code.
Raised when a stack in memory overflows.
The time interval allotted to an operation has expired.

Ketika Kesalahan (Error) terjadi, baik kode aplikasi atau handler default menangani pengecualian/exception. Pelajari cara menangani excetion di bagian selanjutnya.


Di sini, Anda akan belajar tentang penanganan eksepsi dalam C# menggunakan blok coba, tangkap, dan akhirnya.

Pengecualian dalam aplikasi harus ditangani untuk mencegah crash program dan hasil yang tidak diharapkan, pengecualian log dan melanjutkan fungsi lainnya. C# menyediakan dukungan bawaan untuk menangani pengecualian menggunakan blok coba, tangkap & akhirnya.

Sintaks :

try
{
    // put the code here that may raise exceptions
    // letakkan kode di sini yang dapat menimbulkan pengecualian
}
catch
{
    // handle exception here
    // tangani pengecualian di sini
}
finally
{
    // final cleanup code
    // kode pembersihan akhir
}

  • try block : Setiap kode yang dicurigai dapat menimbulkan pengecualian harus dimasukkan ke dalam blok try{}. Selama eksekusi, jika pengecualian terjadi, aliran kontrol melompat ke blok catch pertama yang cocok.
  • catch block : Blok catch adalah blok penangan pengecualian tempat Anda dapat melakukan beberapa tindakan seperti mencatat dan mengaudit pengecualian. Blok catch mengambil parameter dari tipe pengecualian yang dengannya Anda bisa mendapatkan detail pengecualian/exception.
  • finally block : Blok finally akan selalu dieksekusi apakah pengecualian dimunculkan atau tidak. Biasanya, blok finally harus digunakan untuk melepaskan sumber daya, misalnya, untuk menutup aliran atau objek file apa pun yang dibuka di blok try.
Berikut ini mungkin menimbulkan pengecualian/exception jika Anda memasukkan karakter non-numerik.

using System;

public class Program{
    public static void Main(){
        Console.WriteLine("Masukkan angka : "); // enter non-numeric value to see the exception
        var num = int.Parse(Console.ReadLine());
        Console.WriteLine("Kuadrat dari {0} adalah {1}", num , num * num);
    }
}
Untuk menangani kemungkinan pengecualian dalam contoh di atas, bungkus kode di dalam blok try dan tangani exception di blok catch, seperti yang ditunjukkan di bawah ini.

using System;

public class Program {
    public static void Main() {
        try {
            Console.WriteLine("Masukkan angka : ");

            var num = int.Parse(Console.ReadLine());

           Console.WriteLine("Kuadrat dari {0} adalah {1}", num, num * num);
        }
        catch {
            Console.WriteLine("Terjadi kesalahan.");
        }
        finally {
            Console.WriteLine("Coba lagi dengan angka yang berbeda.");
        }
    }
}
Dalam contoh di atas, kami membungkus kode ini di dalam blok try. Jika pengecualian terjadi di dalam blok try, maka program akan melompat ke blok catch. Di dalam blok catch, kami menampilkan pesan untuk menginstruksikan pengguna tentang kesalahannya, dan di blok finally, kami menampilkan pesan tentang apa yang harus dilakukan setelah menjalankan program.

Catatan :
  • Sebuah blok try harus diikuti oleh catch atau akhirnya atau kedua blok. Blok coba tanpa tangkapan atau blok akhirnya akan memberikan kesalahan waktu kompilasi.

Idealnya, blok catch harus menyertakan parameter kelas pengecualian bawaan atau khusus untuk mendapatkan detail kesalahan. Berikut ini termasuk parameter Jenis Exception yang menangkap semua jenis pengecualian.

1. Filter Exception

Anda dapat menggunakan beberapa blok catch dengan parameter tipe pengecualian yang berbeda. Ini disebut filter pengecualian. Filter pengecualian berguna saat Anda ingin menangani berbagai jenis pengecualian dengan cara yang berbeda.

using System;

public class Program
{
    public static void Main()
    {      
        Console.Write("Silakan masukkan angka untuk membagi 100 : ");
        try
        {
            int num = int.Parse(Console.ReadLine());
            int result = 100 / num;
            Console.WriteLine("100 / {0} = {1}", num, result);
        }
        catch(DivideByZeroException ex)
        {
            Console.WriteLine("Tidak dapat dibagi dengan nol. Silakan coba lagi.");
        }
        catch(InvalidOperationException ex)
        {
            Console.WriteLine("Operasi tidak valid. Silakan coba lagi.");
        }
        catch(FormatException ex)
        {
            Console.WriteLine("Bukan format yang valid. Silakan coba lagi.");
        }
        catch(Exception ex)
        {
            Console.WriteLine("Terjadi kesalahan! Silakan coba lagi.");
        }
    }  
}
Dalam contoh di atas, kami telah menentukan beberapa blok catch dengan tipe pengecualian yang berbeda. Kami dapat menampilkan pesan yang sesuai kepada pengguna, tergantung pada kesalahannya, sehingga pengguna tidak mengulangi kesalahan yang sama lagi.

Catatan :
  • Beberapa blok catch dengan tipe pengecualian yang sama tidak diperbolehkan. Blok catch dengan tipe Pengecualian dasar harus menjadi blok terakhir.

2. Blok Catch tidak valid

Blok catch tanpa parameter dan blok catch dengan parameter Exception tidak diperbolehkan dalam pernyataan try-catch yang sama, karena keduanya melakukan hal yang sama.

Contoh : Tangkapan tidak valid

try
{
    // code that may raise an exception
    // kode yang dapat memunculkan eksepsi
}
catch //cannot have both catch and catch(Exception ex)
{ 
    Console.WriteLine("Exception occurred");
}
catch(Exception ex) //cannot have both catch and catch(Exception ex)
{
    Console.WriteLine("Exception occurred");
}
    Juga, catch block tanpa parameter catch{} atau catch block catch umum (Exception ex){} harus menjadi blok terakhir. Kompilator akan memberikan kesalahan jika Anda memiliki blok catch lain setelah blok catch{} atau catch(Exception ex).

    try
    {
        // code that may raise an exception
        // kode yang dapat memunculkan eksepsi
    }
    catch
    { 
        // this catch block must be last block
        // blok tangkapan ini harus menjadi blok terakhir
    }
    catch (NullReferenceException nullEx)
    {
        Console.WriteLine(nullEx.Message);
    }
    catch (InvalidCastException inEx)
    {
        Console.WriteLine(inEx.Message);
    }

      3. Blok Finally

      Blok finally adalah blok opsional dan harus muncul setelah blok coba atau tangkap. Blok finally akan selalu dieksekusi apakah terjadi pengecualian atau tidak. Blok finally umumnya digunakan untuk kode pembersihan misalnya, membuang objek yang tidak dikelola.

      using System;

      static void Main(string[] args)
      {
          FileInfo file = null;

          try
          {
              Console.Write("Enter a file name to write: ");
              string fileName = Console.ReadLine();
              file = new FileInfo(fileName);
              file.AppendText("Hello World!")
          }
          catch(Exception ex)
          {
              Console.WriteLine("Error occurred: {0}", ex.Message );
          }
          finally
          {
              // clean up file object here;
              file = null;
          }
      }
      Catatan :
      • Beberapa blok finally tidak diperbolehkan. Juga, blok finally tidak dapat memiliki kata kunci kembali, lanjutkan, atau putus. Itu tidak membiarkan kontrol untuk meninggalkan blok finally.

      4. Try-catch Bersarang (Nested try-catch)

      C# memungkinkan blok try-catch bersarang. Saat menggunakan blok try-catch bersarang, pengecualian akan ditangkap di blok catch pertama yang cocok yang mengikuti blok try tempat pengecualian terjadi.

      using System;

      public class Program{
          public static void Main(string[] args){
              var divider = 0;

              try {
                  try {
                      var result = 100/divider;
                  }
                  catch {
                      Console.WriteLine("Inner catch");
                  }
              }
              catch {
                  Console.WriteLine("Outer catch");
              }
          }
      }
      Output :

      Inner catch


      MULTITHREADING


      Sebuah thread didefinisikan sebagai jalur eksekusi suatu program. Setiap utas mendefinisikan aliran kontrol yang unik. Jika aplikasi Anda melibatkan operasi yang rumit dan memakan waktu, maka sering kali membantu untuk mengatur jalur atau utas eksekusi yang berbeda, dengan setiap utas melakukan pekerjaan tertentu.

      Thread adalah proses yang ringan. Salah satu contoh umum penggunaan thread adalah implementasi pemrograman konkuren oleh sistem operasi modern. Penggunaan utas menghemat pemborosan siklus CPU dan meningkatkan efisiensi aplikasi.

      Sejauh ini kami menulis program di mana satu utas berjalan sebagai satu proses yang merupakan contoh aplikasi yang sedang berjalan. Namun, dengan cara ini aplikasi dapat melakukan satu pekerjaan pada satu waktu. Untuk membuatnya menjalankan lebih dari satu tugas pada satu waktu, itu dapat dibagi menjadi utas yang lebih kecil.

      1. Siklus Hidup Benang (Thread Life Cycle)

      Siklus hidup utas dimulai ketika objek dari kelas System.Threading.Thread dibuat dan berakhir ketika utas dihentikan atau menyelesaikan eksekusi.

      Berikut ini adalah berbagai keadaan dalam siklus hidup utas :
      • Status Belum Memulai Ini adalah situasi ketika instance dari utas dibuat tetapi metode Mulai tidak dipanggil.
      • Status Siap Ini adalah situasi ketika utas siap untuk dijalankan dan menunggu siklus CPU.
      • Status Tidak Dapat Dijalankan Sebuah utas tidak dapat dieksekusi, ketika :
        • Metode tidur telah disebut
        • Metode tunggu telah dipanggil
        • Diblokir oleh operasi I/O

      2. Urutan Utama (The Main Thread)

      Dalam C#, kelas System.Threading.Thread digunakan untuk bekerja dengan utas. Hal ini memungkinkan membuat dan mengakses utas individu dalam aplikasi multithreaded. Utas pertama yang dieksekusi dalam suatu proses disebut utas utama.

      Ketika program C# memulai eksekusi, utas utama dibuat secara otomatis. Utas yang dibuat menggunakan kelas Utas disebut utas anak dari utas utama. Anda dapat mengakses utas menggunakan properti CurrentThread dari kelas Utas.

      Program berikut menunjukkan Eksekusi Utas Utama (Main Thread Execution) :

      using System;
      using System.Threading;

      namespace MultithreadingApplication {
         class MainThreadProgram {
            static void Main(string[] args) {
               Thread th = Thread.CurrentThread;
               th.Name = "MainThread";
               
               Console.WriteLine("Ini adalah {0}", th.Name);
               Console.ReadKey();
            }
         }
      }
      Ketika kode di atas dikompilasi dan dijalankan, menghasilkan hasil sebagai berikut :

      Ini adalah MainThread

      3. Membuat Thread (Creating Threads)

      Thread dibuat dengan memperluas kelas Thread. Kelas Thread yang diperluas kemudian memanggil method Start() untuk memulai eksekusi thread anak.

      The following program demonstrates the concept :

      using System;
      using System.Threading;

      namespace MultithreadingApplication {
          class ThreadCreationProgram {
              public static void CallToChildThread() {
                  Console.WriteLine("Child thread starts");
              }
             
              static void Main(string[] args) {
                  ThreadStart childref = new ThreadStart(CallToChildThread);
                  Console.WriteLine("In Main: Creating the Child thread");
                  Thread childThread = new Thread(childref);
                  childThread.Start();
                  Console.ReadKey();
              }
          }
      }
      Ketika kode di atas dikompilasi dan dijalankan, menghasilkan hasil sebagai berikut :

      In Main: Creating the Child thread
      Child thread starts

      4. Mengelola Thread

      Kelas Thread menyediakan berbagai metode untuk mengelola utas.

      Contoh berikut menunjukkan penggunaan method sleep() untuk membuat thread dijeda selama jangka waktu tertentu.

      using System;
      using System.Threading;

      namespace MultithreadingApplication {
          class ThreadCreationProgram {
              public static void CallToChildThread() {
                  Console.WriteLine("Child thread starts");
                 
                  // the thread is paused for 5000 milliseconds
                  int sleepfor = 5000;
                 
                  Console.WriteLine("Child Thread Paused for {0} seconds", sleepfor / 1000);
                  Thread.Sleep(sleepfor);
                  Console.WriteLine("Child thread resumes");
              }
             
              static void Main(string[] args) {
                  ThreadStart childref = new ThreadStart(CallToChildThread);
                  Console.WriteLine("In Main: Creating the Child thread");
                 
                  Thread childThread = new Thread(childref);
                  childThread.Start();
                  Console.ReadKey();
              }
          }
      }
      Ketika kode di atas dikompilasi dan dijalankan, menghasilkan hasil sebagai berikut :

      In Main: Creating the Child thread
      Child thread starts
      Child Thread Paused for 5 seconds
      Child thread resumes

      5. Menghancurkan Thread (Destroying Threads)

      Metode Abort() digunakan untuk menghancurkan utas/thread. Runtime membatalkan utas dengan melemparkan ThreadAbortException. Pengecualian ini tidak dapat ditangkap, kontrol dikirim ke blok terakhir, jika ada.

      Program berikut mengilustrasikan hal ini :

      using System;
      using System.Threading;

      namespace MultithreadingApplication {
          class ThreadCreationProgram {
              public static void CallToChildThread() {
                  try {
                      Console.WriteLine("Child thread starts");
                     
                      // do some work, like counting to 10
                      for (int counter = 0; counter <= 10; counter++) {
                      Thread.Sleep(500);
                      Console.WriteLine(counter);
                      }
                     
                      Console.WriteLine("Child Thread Completed");
                  } catch (ThreadAbortException e) {
                      Console.WriteLine("Thread Abort Exception");
                  } finally {
                      Console.WriteLine("Couldn't catch the Thread Exception");
                  }
              }
             
              static void Main(string[] args) {
                  ThreadStart childref = new ThreadStart(CallToChildThread);
                  Console.WriteLine("In Main: Creating the Child thread");
                 
                  Thread childThread = new Thread(childref);
                  childThread.Start();
                 
                  //stop the main thread for some time
                  Thread.Sleep(2000);
                 
                  //now abort the child
                  Console.WriteLine("In Main: Aborting the Child thread");
                 
                  childThread.Abort();
                  Console.ReadKey();
              }
          }
      }
      Ketika kode di atas dikompilasi dan dijalankan, menghasilkan hasil sebagai berikut :

      In Main: Creating the Child thread
      Child thread starts
      0
      1
      2
      In Main: Aborting the Child thread
      Thread Abort Exception
      Couldn't catch the Thread Exception

      6. Properti dan Metode Kelas Thread

      Tabel berikut menunjukkan beberapa properti yang paling umum digunakan dari kelas Thread :
      • CurrentContext : Mendapatkan konteks saat ini di mana utas dieksekusi.
      • CurrentCulture : Mendapatkan atau menetapkan budaya untuk thread saat ini.
      • CurrentPrinciple : Mendapatkan atau menetapkan prinsip thread saat ini (untuk keamanan berbasis peran).
      • CurrentThread : Mendapatkan thread yang sedang berjalan.
      • CurrentUICulture : Mendapatkan atau menetapkan budaya saat ini yang digunakan oleh Manajer Sumber Daya untuk mencari sumber daya khusus budaya saat run-time.
      • ExecutionContext : Mendapat objek ExecutionContext yang berisi informasi tentang berbagai konteks dari utas saat ini.
      • IsAlive : Mendapat nilai yang menunjukkan status eksekusi thread saat ini.
      • IsBackground : Mendapat atau menetapkan nilai yang menunjukkan apakah suatu utas adalah utas latar belakang atau tidak.
      • IsThreadPoolThread : Mendapatkan nilai yang menunjukkan apakah utas termasuk dalam kumpulan utas terkelola atau tidak.
      • ManagedThreadId : Mendapatkan pengidentifikasi unik untuk utas terkelola saat ini.
      • Name : Mendapat atau menetapkan nama thread.
      • Prioritas : Mendapat atau menetapkan nilai yang menunjukkan prioritas penjadwalan utas.
      • ThreadState : Mendapat nilai yang berisi status utas saat ini.

      Selengkapnya, silakan baca di sini (Tutorialspoint.com).


      DATA LISTS

      A. List


      List<T> adalah kumpulan objek yang sangat diketik yang dapat diakses oleh indeks dan memiliki metode untuk menyortir, mencari, dan memodifikasi daftar. Ini adalah versi generik dari ArrayList yang berada di bawah System.Collections.Generic namespace.

      1. Karakteristik List<T>

      Inilah beberapa Ciri-ciri dari List :
      • List<T> setara dengan ArrayList, yang mengimplementasikan IList<T>.
      • Muncul di bawah System.Collections.Generic namespace.
      • List<T> dapat berisi elemen dari tipe yang ditentukan. Ini menyediakan pemeriksaan tipe waktu kompilasi dan tidak melakukan boxing-unboxing karena generik.
      • Elemen dapat ditambahkan menggunakan metode Add()AddRange() atau sintaks penginisialisasi koleksi.
      • Elemen dapat diakses dengan melewatkan indeks mis. myList[0]. Indeks mulai dari nol.
      • List<T> berkinerja lebih cepat dan lebih sedikit kesalahan daripada ArrayList.

      2. Hirarki Kelas List<T>

      Diagram berikut mengilustrasikan hierarki List<T>.


      3. Membuat List

      List<T> adalah kumpulan umum, jadi Anda perlu menentukan parameter tipe untuk tipe data yang dapat disimpannya. Contoh berikut menunjukkan cara membuat daftar dan menambahkan elemen.

      using System;
      using System.Collections.Generic;

      public class Program {
          public static void Main(string[] args) {
              // adding elements using add() method
              var primeNumbers = new List<int>();
              primeNumbers.Add(1);
              primeNumbers.Add(3);
              primeNumbers.Add(5);
              primeNumbers.Add(7);
             
              Console.WriteLine("No of elelemts : "+ primeNumbers.Count);

              var cities = new List<string>();
              cities.Add("New York");
              cities.Add("London");
              cities.Add("Mumbai");
              cities.Add("Chicago");
              cities.Add(null); // null is allowed
             
              Console.WriteLine("No of elelemts : " + cities.Count);

              // adding elements using collection initializer syntax
              var bigCities = new List<string>() {"New York", "London", "Mumbai", "Chicago"};
             
              Console.WriteLine("No of elelemts : " + bigCities.Count);
             
              var students = new List<Student>() {
                      new Student() {Id = 1, Name="Bill"},
                      new Student() {Id = 2, Name="Steve"},
                      new Student() {Id = 3, Name="Ram"},
                      new Student() {Id = 4, Name="Abdul"}
                  };
         
              Console.WriteLine("No of elelemts : " + students.Count);
          }
      }

      class Student {
          public int Id { get; set; }
          public string Name { get; set; }
      }
      Dalam contoh di atas, List<int> primeNumbers = new List<int>(); membuat daftar tipe int. Dengan cara yang sama, cities dan bigCities adalah daftar tipe string. Anda kemudian dapat menambahkan elemen dalam daftar menggunakan metode Add() atau sintaks penginisialisasi koleksi.

      Anda juga dapat menambahkan elemen kelas khusus menggunakan sintaks penginisialisasi koleksi. Berikut ini menambahkan objek kelas Student  dalam List<Student>.

      Contoh : Tambahkan Objek Kelas Kustom dalam Daftar/List

      var students = new List<Student>() { 
                      new Student(){ Id = 1, Name="Bill"},
                      new Student(){ Id = 2, Name="Steve"},
                      new Student(){ Id = 3, Name="Ram"},
                      new Student(){ Id = 4, Name="Abdul"}
                  };

      4. Menambahkan Array dalam List

      Gunakan metode AddRange() untuk menambahkan semua elemen dari larik atau koleksi lain ke Daftar.

      AddRange() signature : void AddRange(IEnumerable<T> collection)

      using System;
      using System.Collections.Generic;

      public class Program
      {
          public static void Main()
          {
              IList<int> intList1 = new List<int>();
              intList1.Add(10);
              intList1.Add(20);
              intList1.Add(30);
              intList1.Add(40);
             
              List<int> intList2 = new List<int>();
             
              intList2.AddRange(intList1);


              Console.WriteLine(intList2.Count);
             
          }
      }
      Output :

      4

      5. Mengakses List

      Daftar dapat diakses dengan indeks, loop for/foreach, dan menggunakan kueri LINQ. Indeks daftar mulai dari nol. Lewati indeks dalam tanda kurung siku untuk mengakses item daftar individual, sama seperti array. Gunakan foreach atau for loop untuk mengulang koleksi List<T>.

      using System;
      using System.Collections.Generic;

      public class Program
      {
          public static void Main()
          {      
              List<int> intList = new List<int>() { 10, 20, 30, 40, 50 };

              intList.ForEach(el => Console.WriteLine(el));

              foreach (var el in intList)
                  Console.WriteLine(el);
             
              for(int i =0; i < intList.Count; i++)
                  Console.WriteLine(intList[i]);
             
          }
      }
      Output :

      10
      20
      30
      40
      50
      10
      20
      30
      40
      50
      10
      20
      30
      40
      50

      6. Mengakses List menggunakan LINQ

      List<T> mengimplementasikan antarmuka IEnumerable. Jadi, kita dapat membuat kueri daftar menggunakan sintaks kueri LINQ atau sintaks metode, seperti yang ditunjukkan di bawah ini.

      Contoh : Kueri LINQ dalam List

      using System;
      using System.Linq;
      using System.Collections.Generic;

      public class Program
      {
          public static void Main(string[] args)
          {
              var students = new List<Student>() {
                      new Student() {Id = 1, Name="Bill"},
                      new Student() {Id = 2, Name="Steve"},
                      new Student() {Id = 3, Name="Ram"},
                      new Student() {Id = 4, Name="Abdul"},
                      new Student() {Id = 5, Name="Bill"}
              };
             
              // Get all students whose name is Bill
              // Dapatkan semua siswa yang bernama Bill
              var studNames = from s in students
                  where s.Name == "Bill"
                  select s;
             
              foreach(var student in studNames)
                  Console.WriteLine(student.Id + ", " +student.Name);
          }
      }

      public class Student
      {
          public int Id { get; set; }
          public string Name { get; set; }
      }
      Output :

      1, Bill
      5, Bill

      7. Sisipkan Elemen dalam List

      Gunakan metode Insert() untuk menyisipkan elemen ke dalam koleksi List<T> pada indeks yang ditentukan.

      Insert() signature : void Insert(int index, T item);

      using System;
      using System.Collections.Generic;
                         
      public class Program
      {
          public static void Main()
          {
              var numbers = new List<int>(){ 10, 20, 30, 40 };

              numbers.Insert(1, 11);// inserts 11 at 1st index: after 10.
             
              foreach (var num in numbers)
                  Console.WriteLine(num);
          }
      }
      Output :

      10
      11
      20
      30
      40

      8. Hapus Elemen dari List

      Gunakan method Remove() untuk menghapus kemunculan pertama dari elemen yang ditentukan dalam koleksi List<T>. Gunakan metode RemoveAt() untuk menghapus elemen dari indeks yang ditentukan. Jika tidak ada elemen pada indeks yang ditentukan, maka ArgumentOutOfRangeException akan dilempar.

      • Remove() signature : bool Remove(T item)
      • RemoveAt() signature : void RemoveAt(int index)

      using System;
      using System.Collections.Generic;
                         
      public class Program
      {
          public static void Main()
          {
              var numbers = new List<int>(){ 10, 20, 30, 40, 10 };
              numbers.Remove(10); // Removes 10 elements from a list
              numbers.RemoveAt(2); // Removes the 3rd element (index starts from 0)
              //numbers.RemoveAt(10); // Removes the 3rd element (index starts from 0)

              foreach (var num in numbers)
                  Console.WriteLine(num);
          }
      }
      Output :

      20
      30
      10

      9. Periksa Elemen dalam List

      Gunakan metode Contains() untuk menentukan apakah suatu elemen ada dalam List<T> atau tidak.

      using System;
      using System.Collections.Generic;
                         
      public class Program
      {
          public static void Main()
          {
              var numbers = new List<int>(){ 10, 20, 30, 40 };

              Console.WriteLine(numbers.Contains(10));
              Console.WriteLine(numbers.Contains(11));
              Console.WriteLine(numbers.Contains(20));
          }
      }
      Output :

      True
      False
      True

      B. Dictionary


      Dictionary<TKey, TValue> adalah kumpulan umum yang menyimpan pasangan nilai kunci tanpa urutan tertentu.

      1. Ciri-ciri Dictionary

      • Dictionary<TKey, TValue> menyimpan pasangan nilai kunci.
      • Berada di bawah System.Collections.Generic namespace.
      • Mengimplementasikan antarmuka IDictionary<TKey, TValue>.
      • Kunci harus unik dan tidak boleh nol.
      • Nilai bisa nol atau duplikat.
      • Nilai dapat diakses dengan melewatkan kunci terkait di pengindeks mis. myDictionary[key].
      • Elemen disimpan sebagai objek KeyValuePair<TKey, TValue>.

      2. Kelas Hirarki Dictionary di C#

      Diagram berikut mengilustrasikan hierarki kelas Kamus generik.


      3. Membuat Dictionary

      Anda dapat membuat objek Dictionary<TKey, TValue> dengan meneruskan jenis kunci dan nilai yang dapat disimpannya. Contoh berikut menunjukkan cara membuat kamus dan menambahkan pasangan nilai kunci.

      using System;
      using System.Collections.Generic;

      public class Program
      {
          public static void Main(string[] args)
          {
              IDictionary<int, string> numberNames = new Dictionary<int, string>();
              numberNames.Add(1,"One"); // Adding key/value using the Add() method
              numberNames.Add(3,"Three"); // Menambahkan key/value menggunakan method Add()
              numberNames.Add(2,"Two");
              numberNames.Add(4,"Four");
             
              foreach(KeyValuePair<int, string> kvp in numberNames)
                  Console.WriteLine("Key: {0}, Value: {1}", kvp.Key, kvp.Value);
             
              // Creating a dictionary using collection-initializer syntax
              // Membuat dictionary menggunakan sintaks penginisialisasi koleksi
              var cities = new Dictionary<string, string>(){
                  {"UK","London, Manchester, Birmingham"},
                  {"USA","Chicago, New York, Washington"},
                  {"India","Mumbai, New Delhi, Pune"},
                  {"Indonesia","Jakarta, Bandung, Surabaya"}
              };
             
              foreach(var kvp in cities)
                  Console.WriteLine("Key: {0}, Value: {1}", kvp.Key, kvp.Value);
             
          }
      }
      Pada contoh di atas, numberNames adalah kamus tipe Dictionary<int, string>, sehingga dapat menyimpan kunci int dan nilai string. Dengan cara yang sama, cities adalah kamus tipe Dictionary<string, string>, sehingga dapat menyimpan kunci string dan nilai string. Kamus tidak dapat menyertakan kunci duplikat atau nol, sedangkan nilai dapat digandakan atau nol. Kunci harus unik jika tidak, itu akan mengeluarkan pengecualian runtime.

      4. Access Dictionary Elements

      Dictionary dapat diakses menggunakan pengindeks. Tentukan kunci untuk mendapatkan nilai terkait. Anda juga dapat menggunakan metode ElementAt() untuk mendapatkan KeyValuePair dari indeks yang ditentukan.

      using System;
      using System.Linq;

      using System.Collections.Generic;
                         
      public class Program
      {
          public static void Main(string[] args)
          {
              var cities = new Dictionary<string, string>(){
                  {"UK", "London, Manchester, Birmingham"},
                  {"USA", "Chicago, New York, Washington"},
                  {"India", "Mumbai, New Delhi, Pune"}
              };

              Console.WriteLine(cities["UK"]); //prints value of UK key
              Console.WriteLine(cities["USA"]);//prints value of USA key
              //Console.WriteLine(cities["Indonesia"]); // run-time exception: Key does not exist

              //use ContainsKey() to check for an unknown key
              if(cities.ContainsKey("Indonesia")){  
                  Console.WriteLine(cities["Indonesia"]);
              }

              //use TryGetValue() to get a value of unknown key
              string result;

              if(cities.TryGetValue("Indonesia", out result))
              {
                  Console.WriteLine(result);
              }

              Console.WriteLine("---access elements using for loop---");
              //use ElementAt() to retrieve key-value pair using index
              for (int i = 0; i < cities.Count; i++)
              {
                  Console.WriteLine("Key: {0}, Value: {1}",
                                                          cities.ElementAt(i).Key,
                                                          cities.ElementAt(i).Value);
              }
          }
      }
      5. Update Dictionary

      Perbarui value key dengan menentukan kunci di pengindeks. Ini akan membuang KeyNotFoundException jika kunci tidak ada dalam kamus, oleh karena itu gunakan metode ContainsKey() sebelum mengakses kunci yang tidak dikenal.

      using System;
      using System.Linq;
      using System.Collections.Generic;
                         
      public class Program
      {
          public static void Main()
          {
              var cities = new Dictionary<string, string>(){
                  {"UK", "London, Manchester, Birmingham"},
                  {"USA", "Chicago, New York, Washington"},
                  {"India", "Mumbai, New Delhi, Pune"},
                  {"Indonesia","Jakarta, Bandung, Surabaya"}
              };

              cities["UK"] = "Liverpool, Bristol"; // update value of UK key
              cities["USA"] = "Los Angeles, Boston"; // update value of USA key
              //cities["France"] = "Paris"; //throws run-time exception: KeyNotFoundException

              if(cities.ContainsKey("France")){
                  cities["France"] = "Paris";
              }
             
              foreach(var kvp in cities)
                  Console.WriteLine("Key: {0}, Value:{1}", kvp.Key, kvp.Value);
          }
      }
      6. Hapus Elemen dalam Dictionary

      Metode Remove() menghapus pasangan nilai kunci yang ada dari kamus. Metode Clear() menghapus semua elemen kamus.

      using System;
      using System.Collections.Generic;
                         
      public class Program
      {
          public static void Main()
          {
              var cities = new Dictionary<string, string>(){
                  {"UK", "London, Manchester, Birmingham"},
                  {"USA", "Chicago, New York, Washington"},
                  {"India", "Mumbai, New Delhi, Pune"},
                  {"Indonesia","Jakarta, Bandung, Surabaya"}
              };

              Console.WriteLine("Total Elements : {0}", cities.Count);
             
              cities.Remove("UK"); // removes UK
              //cities.Remove("France"); //throws run-time exception: KeyNotFoundException

              if(cities.ContainsKey("France")){ // check key before removing it
                  cities.Remove("France");
              }
             
              Console.WriteLine("Total Elements : {0}", cities.Count);

              cities.Clear(); //deletes all elements
             
              Console.WriteLine("Total Elements after Clear() : {0}", cities.Count);

          }
      }
      Output :

      Total Elements : 4
      Total Elements : 3
      Total Elements after Clear() : 0

      C. Key Value Pair


      Jika Anda telah membuat kode sebelumnya, Anda harus terbiasa dengan pasangan nilai kunci yang digunakan dalam struktur data seperti Peta, Kamus, dll.

      C# melakukan sesuatu yang istimewa dengannya, dan itu memberi kami kelas khusus untuk pasangan nilai kunci. Kita dapat menggunakannya seperti struktur data lainnya.

      Dalam tutorial ini, kita akan belajar tentang properti pasangan Key-Value di C# dan melihat cara membuat daftar pasangan kunci-nilai.

      Kelas KeyValuePair menyimpan sepasang nilai dalam satu daftar dengan C#. Setel KeyValuePair dan tambahkan elemen :

      var myList = new List<KeyValuePair<string, int>>();
      
      // adding elements
      myList.Add(new KeyValuePair<string, int>("Laptop", 20));
      myList.Add(new KeyValuePair<string, int>("Desktop", 40));
      myList.Add(new KeyValuePair<string, int>("Tablet", 60));

      Berikut adalah kode untuk mempelajari cara bekerja dengan KeyValuePair dan menampilkan kunci dan nilai :

      using System;
      using System.Collections.Generic;

      class Program {
          static void Main(string[] args) {
              var myList = new List<KeyValuePair<string, int>>();

              // Menambahkan elemen
              myList.Add(new KeyValuePair<string, int>("Laptop", 20));
              myList.Add(new KeyValuePair<string, int>("Desktop", 40));
              myList.Add(new KeyValuePair<string, int>("Tablet", 60));
              foreach (var val in myList) {
                  Console.WriteLine(val);
              }
          }
      }
      Output :

      [Laptop, 20]
      [Desktop, 40]
      [Tablet, 60]

      Penerapan dalam Key Value Pair, yaitu :
      • Daftar pasangan Nilai-Kunci (Value-Key) dapat digunakan untuk membuat Daftar Tertaut dengan kunci yang menyimpan data dan menilai tautan ke simpul berikutnya.
      • Dalam mengembalikan info non-tunggal yang dapat memiliki pasangan atau bahkan lebih dari sepasang nilai.
      • Ini dapat digunakan dalam permintaan informasi offline massal dan penyimpanan hasil yang efisien.


      LAMBDA EXPRESSIONS

      A. Lambda Expressions


      Ekspresi Lambda (Lambda Expression) adalah bagaimana fungsi anonim dibuat. Dalam artikel dan contoh kode ini, kita akan melihat bagaimana mengimplementasikan lambdas di C#.

      Lambda Expression adalah fungsi anonim yang berisi ekspresi atau urutan operator. Semua Ekspresi Lambda menggunakan operator lambda =>, yang dapat dibaca sebagai "pergi ke" atau "menjadi". Sisi kiri operator lambda menentukan parameter input dan sisi kanan menyimpan ekspresi atau blok kode yang berfungsi dengan parameter entri. Biasanya ekspresi lambda digunakan sebagai predikat atau sebagai ganti delegasi (tipe yang mereferensikan suatu metode).

      Anda menggunakan ekspresi lambda untuk membuat fungsi anonim. Gunakan operator deklarasi lambda => untuk memisahkan daftar parameter lambda dari tubuhnya. Ekspresi lambda dapat berupa salah satu dari dua bentuk berikut :

      Ekspresi Lambda : Terdiri dari input dan ekspresi.

      input => expression;
      input => ekspresi;
      

      Pernyataan Lambda : Terdiri dari input dan satu set pernyataan yang akan dieksekusi.

      input => { statements };
      input => { pernyataan };
      

      Ekspresi Lambda :

      Parameter => expression
      Parameter-list => expression
      Count => count + 2;
      Sum => sum + 2;
      n => n % 2 == 0
      

      Operator Lambda => membagi ekspresi lambda menjadi dua bagian. Sisi kiri adalah parameter input dan sisi kanan adalah badan lambda.

      Contoh Lambda Expression :

      using System;
      using System.Collections.Generic;
      using System.Linq;

      public static class demo  
      {
          public static void Main()  
          {
              List<int> list = new List<int>() { 1, 2, 3, 4, 5, 6 };  
              List<int> evenNumbers = list.FindAll(x => (x % 2) == 0);  
       
              foreach (var num in evenNumbers)  
              {  
                  Console.Write("{0} ", num);  
              }  
              Console.WriteLine();  
              Console.Read();
          }
      }
      Output :

      2 4 6 

      Contoh sebelumnya mengulang seluruh kumpulan angka dan setiap elemen (bernama x) diperiksa untuk menentukan apakah angka tersebut kelipatan 2 (menggunakan ekspresi Boolean (x % 2) == 0).

      Contoh lainnya :

      using System;
      using System.Collections.Generic;
      using System.Linq;

      class Cat {
          public string Name { get; set; }
          public int Age { get; set; }
      }

      class demo {  
          static void Main(string[] args) {
              List<Cat> cats = new List<Cat>() {
                  new Cat { Name = "Moza", Age = 1 },
                  new Cat { Name = "Zhie", Age = 2 },
                  new Cat { Name = "Zhou", Age = 0 }
               };

               var names = cats.Select(x => x.Name);  
               foreach (var name in names) {  
                   Console.WriteLine(name);  
               }  
               Console.Read();  
          }
      }
      Output :

      Moza
      Zhie
      Zhou

      Kami membuat koleksi, yang berisi data dari kelas tertentu. Dalam contoh, dari kelas Cat (dengan properti Nama dan Usia), kami ingin mendapatkan daftar yang berisi semua nama anjing. Dengan kata kunci var, kami memberi tahu kompiler untuk menentukan jenis variabel tergantung pada hasil yang kami tetapkan di sisi kanan tanda sama dengan.

      1. Menggunakan Lambda Expression dengan Tipe Anonim

      using System;
      using System.Collections.Generic;
      using System.Linq;

      class Cat {
          public string Name { get; set; }
          public int Age { get; set; }
      }

      class demo {  
          static void Main(string[] args) {
              List<Cat> cats = new List<Cat>() {
                  new Cat { Name = "Moza", Age = 1 },
                  new Cat { Name = "Zhie", Age = 2 },
                  new Cat { Name = "Zhou", Age = 0 }
              };
               
              var newCatsList = cats.Select(x => new { Age = x.Age, FirstLetter = x.Name[0] });
              foreach (var item in newCatsList) {  
                  Console.WriteLine(item);  
              }  
              Console.Read();  
          }
      }
      Output :

      { Age = 1, FirstLetter = M }
      { Age = 2, FirstLetter = Z }
      { Age = 0, FirstLetter = Z }

      Koleksi newCatsList yang baru dibuat memiliki elemen tipe anonim yang mengambil properti Age dan FirstLetter sebagai parameter.

      2. Mengurutkan menggunakan Lambda Expression

      Berikut ini adalah contoh pengurutan dengan Ekspresi Lambda :

      using System;
      using System.Collections.Generic;
      using System.Linq;

      class Cat {
          public string Name { get; set; }
          public int Age { get; set; }
      }

      class demo {  
          static void Main(string[] args) {
              List<Cat> cats = new List<Cat>() {
                  new Cat { Name = "Moza", Age = 1 },
                  new Cat { Name = "Zhie", Age = 2 },
                  new Cat { Name = "Zhou", Age = 0 }
              };
               
              var sortedCats = cats.OrderByDescending(x => x.Age);  
              foreach (var cat in sortedCats) {
                  Console.WriteLine(string.Format("Cat {0} is {1} years old.", cat.Name, cat.Age));  
              }
              Console.Read();
          }
      }
      Output :

      Cat Zhie is 2 years old.
      Cat Moza is 1 years old.
      Cat Zhou is 0 years old.

      B. Linq dalam C#


      Language-Integrated Query (LINQ) adalah seperangkat teknologi yang kuat berdasarkan integrasi kemampuan query langsung ke dalam Bahasa C#. Kueri LINQ adalah konstruksi bahasa kelas satu di C# .NET, seperti halnya kelas, metode, peristiwa. LINQ memberikan pengalaman kueri yang konsisten ke objek kueri (LINQ ke Objek), database relasional (LINQ ke SQL), dan XML (LINQ ke XML).

      LINQ (Language Integrated Query) adalah sintaks kueri yang seragam di C# dan VB.NET untuk mengambil data dari berbagai sumber dan format. Ini terintegrasi dalam C# atau VB, sehingga menghilangkan ketidakcocokan antara bahasa pemrograman dan database, serta menyediakan antarmuka kueri tunggal untuk berbagai jenis sumber data.

      Misalnya, SQL adalah Bahasa Kueri Terstruktur yang digunakan untuk menyimpan dan mengambil data dari database. Dengan cara yang sama, LINQ adalah sintaks kueri terstruktur yang dibangun di C# dan VB.NET untuk mengambil data dari berbagai jenis sumber data seperti koleksi, ADO.Net DataSet, XML Docs, layanan web dan MS SQL Server dan database lainnya.


      Kueri LINQ mengembalikan hasil sebagai objek. Ini memungkinkan Anda untuk menggunakan pendekatan berorientasi objek pada kumpulan hasil dan tidak perlu khawatir tentang mengubah format hasil yang berbeda menjadi objek.


      Contoh berikut menunjukkan kueri LINQ sederhana yang mendapatkan semua string dari larik yang berisi 'a'.

      using System;
      using System.Linq;

      public class Program {
          public static void Main() {
              // Data source
              string[] names = {"Inzaghi", "Steven", "Muhammad", "Bryan"};
             
              // LINQ Query
              var myLinqQuery =  from name in names
                                 where name.Contains('a')
                                 select name;
             
              // Query execution
              foreach (var name in myLinqQuery)
                  Console.Write(name + " ");
          }
      }
      Output :

      Inzaghi Muhammad Bryan

      Dalam contoh di atas, nama array string adalah sumber data. Berikut ini adalah kueri LINQ yang ditetapkan ke variabel myLinqQuery.

      from name in names
      where name.Contains('a')
      select name;
      

      Kueri di atas menggunakan sintaks kueri LINQ. Anda akan mempelajarinya lebih lanjut di bab Sintaks Kueri.

      Anda tidak akan mendapatkan hasil kueri LINQ sampai Anda menjalankannya. Kueri LINQ dapat dieksekusi dalam berbagai cara, di sini kami menggunakan foreach loop untuk mengeksekusi kueri kami yang disimpan di myLinqQuery. Loop foreach mengeksekusi kueri pada sumber data dan mendapatkan hasilnya, lalu mengulangi set hasil.

      Jadi, setiap kueri LINQ harus melakukan kueri ke beberapa jenis sumber data apakah itu bisa berupa array, koleksi, XML, atau database lainnya. Setelah menulis kueri LINQ, itu harus dijalankan untuk mendapatkan hasilnya.


      CLONING SERIALIZATIONS

      A. Object Clone


      Mengkloning objek dalam bahasa pemrograman apa pun itu rumit, tetapi saya pikir dalam C # itu mengambil kedudukan ekstra dengan memberi Anda beberapa alat yang sepertinya akan menyelesaikan masalah Anda, tetapi kemudian tidak memberi tahu Anda bahwa itu mungkin hanya menyelesaikan kasus penggunaan yang sangat tipis dan tidak ada yang lain. Panduan ini akan menjadi setengah panduan tentang kloning, tetapi juga penyegaran cepat tentang apa sebenarnya arti "Kloning" dalam konteks C#.

      Untuk membantu Anda menjadi sedikit lebih dewasa, saya telah mengumpulkan 5 cara untuk mengkloning objek di C# dan telah menyiapkan pro dan kontra dari masing-masing. Kita akan menggunakan dua kelas sederhana Person dan Address dalam semua contoh berikut.

      public class Person{
          public string Name { get; set; }
          public int Age { get; set; }
          public Address Address { get; set; }
      }

      public class Address{
          public string City { get; set; }
          public string Street { get; set; }
      }

      Tetapi sebelum kita mulai, saya ingin mengingatkan Anda tentang konsep salinan dangkal dan dalam di .NET. Salinan dangkal memiliki tipe nilainya sendiri, tetapi berbagi tipe referensi dengan objek aslinya. Salinan dalam memiliki nilai dan tipe referensi sendiri, yaitu, sepenuhnya terputus dari objek aslinya. Seorang insinyur perangkat lunak dapat membuat salinan dangkal hanya dengan memanggil metode MemberwiseClone, tetapi salinan dalam memerlukan beberapa kode khusus tambahan untuk ditulis.

      1. ICloneable Interface

      Cara pertama untuk mengkloning objek adalah dengan mengimplementasikan antarmuka ICloneable yang disediakan oleh .NET. Antarmuka ini memiliki metode Clone tunggal, di dalamnya kita harus memanggil metode MemberwiseClone dari kelas Object.

      public class Person : ICloneable {
          public string Name { get; set; }
          public int Age { get; set; }
          public Address Address { get; set; }

          public object Clone(){
              var person = (Person)MemberwiseClone();
              person.Address = (Address)Address.Clone();
              return person;
          }
      }

      public class Address : ICloneable {
          public string City { get; set; }
          public string Street { get; set; }

          public object Clone(){
              return MemberwiseClone();
          }
      }

      Pro :
      • Tidak perlu mendefinisikan antarmuka sendiri.
      • Kontrol penuh atas apa yang kita kloning. Bayangkan bahwa kelas Person menyertakan properti AccountHistory yang digunakan untuk tujuan audit. Saat mengkloning objek Person, kita mungkin memerlukan riwayat akun kosong. Persyaratan seperti itu dapat dinyatakan dalam kode seperti ini :
      public class Person : ICloneable{
          public string Name { get; set; }
          public int Age { get; set; }
          public Address Address { get; set; }
          public AccountHistory AccountHistory { get; set; }

          public object Clone(){
              var person = (Person)MemberwiseClone();
              person.Address = (Address)Address.Clone();
              person.AccountHistory = new AccountHistory(); //clear the history
              return person;
          }
      }

      Kontra :
      • Metode Clone mengembalikan tipe Objek. Kode panggilan harus mentransmisikan objek ke tipe data tertentu.
      • Antarmuka ICloneable harus diimplementasikan untuk setiap kelas yang termasuk dalam objek grafik.
      • Nama antarmuka atau metode tidak memberi tahu apakah salinan yang dalam atau dangkal dikembalikan ke pemanggil. Seorang insinyur perangkat lunak perlu menyelami detail implementasi.

      2. Custom Interface IPrototype

      Mengapa tidak membuat antarmuka generik sendiri daripada menggunakan ICloneable? Antarmuka khusus kami dapat memperbaiki beberapa masalah ICloneable.

      Mari kita panggil antarmuka kustom IPrototype dan tentukan satu metode CreateDeepCopy di dalamnya.

      public interface IPrototype<T>{
          T CreateDeepCopy();
      }

      public class Person : IPrototype<Person>{
          public string Name { get; set; }
          public int Age { get; set; }
          public Address Address { get; set; }

          public Person CreateDeepCopy(){
              var person = (Person)MemberwiseClone();
              person.Address = Address.CreateDeepCopy();
              return person;
          }
      }

      public class Address : IPrototype<Address>{
          public string City { get; set; }
          public string Street { get; set; }

          public Address CreateDeepCopy(){
              return (Address)MemberwiseClone();
          }
      }

      Pro :
      • Nama metode CreateDeepCopy secara akurat menjelaskan tujuannya.
      • Konsumen antarmuka IPrototype tidak perlu lagi menggunakan tipe pengembalian metode CreateDeepCopy.
      • Kontrol penuh atas apa yang kami klon dengan antarmuka ICloneable.

      Kontra :
      • Antarmuka harus didefinisikan secara manual oleh seorang insinyur perangkat lunak.
      • Antarmuka harus diimplementasikan untuk setiap kelas yang termasuk dalam grafik objek.

      3. Serialisasi Biner (Binary Serialization)

      Serialisasi Biner membantu Anda mengkloning objek tanpa mengimplementasikan antarmuka. Idenya sederhana — buat serial grafik objek ke dalam memori dan kemudian deserialize kembali ke objek.

      public static class Helper{
          public static T CreateDeepCopy<T>(T obj){
              using (var ms = new MemoryStream()){
                  IFormatter formatter = new BinaryFormatter();
                  formatter.Serialize(ms, obj);
                  ms.Seek(0, SeekOrigin.Begin);
                  return (T)formatter.Deserialize(ms);
              }
          }
      }

      Pro :
      • Tidak perlu lagi mengimplementasikan antarmuka.
      • Tidak peduli seberapa kompleks objeknya, itu akan sepenuhnya dikloning.
      • Logika kloning ada di satu tempat.

      Kontra :
      • Orang Kelas dan semua yang terkait harus ditandai dengan atribut [Serializable].
      • Tidak ada pilihan antara salinan dangkal dan dalam. Hanya opsi penyalinan dalam yang tersedia untuk insinyur perangkat lunak saat menggunakan serialisasi.

      4. Serialisasi XML (XML Serialization)

      Serialisasi XML adalah alternatif yang menarik untuk serialisasi biner. Contoh kode berikut ini sangat mirip dengan yang sebelumnya dengan satu penyesuaian baris tunggal :

      public static class Helper{
          public static T CreateDeepCopy<T>(T obj){
              using (var ms = new MemoryStream()){
                  XmlSerializer serializer = new XmlSerializer(obj.GetType());
                  serializer.Serialize(ms, obj);
                  ms.Seek(0, SeekOrigin.Begin);
                  return (T)serializer.Deserialize(ms);
              }
          }
      }

      Serialisasi XML tidak memerlukan atribut [Serializable], yang merupakan kabar baik. Namun, serialisasi XML mengharuskan setiap kelas memiliki konstruktor tanpa parameter. Persyaratan seperti itu mungkin tampak tidak berbahaya, tetapi tidak selalu demikian. Memiliki konstruktor tanpa parameter di kelas Person berarti bahwa sebuah instance dapat dibuat tanpa nama, nama keluarga, dll. Saya lebih suka agar semua properti yang diperlukan disetel pada saat pembuatan objek untuk menghindari objek yang diinisialisasi sebagian. Jadi serialisasi XML tidak akan berfungsi untuk saya dalam banyak kasus.

      5. Copy Constructor

      Konstruktor salinan adalah konstruktor sederhana dengan satu parameter dari tipe kelas terlampir. Di dalam konstruktor, kita hanya menginisialisasi ulang properti objek satu per satu.

      public class Person{
          public Person(Person person){
              Name = person.Name;
              Age = person.Age;
              Address = new Address(person.Address);
          }

          public string Name { get; set; }
          public int Age { get; set; }
          public Address Address { get; set; }
      }

      public class Address{
          public Address(Address address){
              City = address.City;
              Street = address.Street;
          }

          public string City { get; set; }
          public string Street { get; set; }
      }

      Pro :
      • Kontrol penuh atas apa yang kita kloning.

      Kontra :
      • Copy konstruktor harus diimplementasikan di setiap kelas yang termasuk dalam objek grafik.

      Antarmuka dan konstruktor salinan memberi insinyur perangkat lunak kendali penuh atas proses kloning. Teknik kloning berbasis serialisasi membebaskan insinyur perangkat lunak dari kebutuhan untuk menyesuaikan logika kloning setiap kali grafik objek dimodifikasi.

      Seperti biasa, tidak ada peluru perak, jadi kami insinyur perangkat lunak perlu hati-hati menganalisis setiap kasus tertentu dan memilih solusi yang paling tepat, dengan mempertimbangkan pro dan kontra.

      B. Object Serialization


      Sering kali, kita perlu menyimpan objek ke penyimpanan fisik sehingga dapat dibaca kembali dan diubah kembali menjadi objek. Proses menyimpan objek ke penyimpanan fisik disebut Serialisasi/Serialization. Proses membaca objek serial kembali ke memori adalah deserialization.

      Dengan kata sederhana Serialization dalam C# adalah proses menyimpan instance objek ke penyimpanan persisten. Serialization menyimpan status objek yaitu nilai variabel anggota ke penyimpanan permanen seperti disk. Deserialisasi adalah kebalikan dari serialisasi. Ini adalah proses membaca objek dari file tempat mereka disimpan. Dalam contoh kode ini kita akan melihat bagaimana membuat serial dan deserialize objek menggunakan C#.

      Berikut adalah cara kerja serialisasi. Sumber gambar : Microsoft Docs.


      Namespace Terlibat

      Ruang nama berikut terlibat dalam proses serialisasi :
      • System.Runtime.Serialization
      • System.Runtime.Serialization.Formatters.Binary

      Contoh 1

      using System;
      using System.IO;
      using System.Runtime.Serialization;
      using System.Runtime.Serialization.Formatters.Binary;

      public class SerialTest {
          public void SerializeNow() {
              ClassToSerialize c = new ClassToSerialize();
              File f = new File("temp.dat");
              Stream s = f.Open(FileMode.Create);
              BinaryFormatter b = new BinaryFormatter();
              b.Serialize(s, c);
              s.Close();
          }
          public void DeSerializeNow() {
              ClassToSerialize c = new ClassToSerialize();
              File f = new File("temp.dat");
              Stream s = f.Open(FileMode.Open);
              BinaryFormatter b = new BinaryFormatter();
              c = (ClassToSerialize) b.Deserialize(s);
              Console.WriteLine(c.name);
              s.Close();
          }
          public static void Main(string[] s) {
              SerialTest st = new SerialTest();
              st.SerializeNow();
              st.DeSerializeNow();
          }
      }
      public class ClassToSerialize {
          public int age = 100;
          public string name = "bipin";
      }
      Penjelasan :

      Di sini kita memiliki kelas kita sendiri bernama ClassToSerialize. Kelas ini memiliki dua nama dan usia yang valid untuk publik dengan beberapa nilai default. Kami akan menulis kelas ini ke file disk (temp.dat) menggunakan kelas SerializeTest.

      Kelas SerializeTest memiliki dua metode SerializeNow() dan DeSerializeNow() yang masing-masing melakukan tugas serialisasi dan deserialisasi.

      Langkah-langkah umum untuk membuat serial adalah :
      • Buat instance File yang akan menyimpan objek serial.
      • Buat aliran dari objek file.
      • Buat instance BinaryFormatter.
      • Panggil metode serialisasi dari instance yang meneruskannya ke aliran dan objek untuk membuat cerita bersambung.
      Langkah-langkah untuk de-serializing objek serupa. Satu-satunya perubahan adalah Anda perlu memanggil metode deserialize objek BinaryFormatter.

      Sekarang, mari kita lihat contoh di mana kita telah menggunakan kelas 'nyata' dengan anggota dan properti publik dan bersama untuk merangkumnya. Kelas tersebut juga menggunakan kelas pendukung lainnya. Ini hanya untuk memperjelas bahwa jika kelas Anda berisi kelas lebih lanjut, semua kelas dalam rantai akan diserialisasi.

      Contoh 2

      using System;
      using System.IO;
      using System.Runtime.Serialization;
      using System.Runtime.Serialization.Formatters.Binary;

      public class SerialTest {
          public void SerializeNow() {
              ClassToSerialize c = new ClassToSerialize();
              c.Name = "bipin";
              c.Age = 26;
              ClassToSerialize.CompanyName = "xyz";
              File f = new File("temp.dat");
              Stream s = f.Open(FileMode.Create);
              BinaryFormatter b = new BinaryFormatter();
              b.Serialize(s, c);
              s.Close();
          }
          public void DeSerializeNow() {
              ClassToSerialize c = new ClassToSerialize();
              File f = new File("temp.dat");
              Stream s = f.Open(FileMode.Open);
              BinaryFormatter b = new BinaryFormatter();
              c = (ClassToSerialize) b.Deserialize(s);
              Console.WriteLine("Name :" + c.Name);
              Console.WriteLine("Age :" + c.Age);
              Console.WriteLine("Company Name :" + ClassToSerialize.CompanyName);
              Console.WriteLine("Company Name :" + c.GetSupportClassString());
              s.Close();
          }
          public static void Main(string[] s) {
              SerialTest st = new SerialTest();
              st.SerializeNow();
              st.DeSerializeNow();
          }
      }
      public class ClassToSerialize {
          private int age;
          private string name;
          static string companyname;
          SupportClass supp = new SupportClass();
          public ClassToSerialize() {
              supp.SupportClassString = "In support class";
          }
          public int Age {
              get {
                  return age;
              }
              set {
                  age = value;
              }
          }
          public string Name {
              get {
                  return name;
              }
              set {
                  name = value;
              }
          }
          public static string CompanyName {
              get {
                  return companyname;
              }
              set {
                  companyname = value;
              }
          }
          public string GetSupportClassString() {
              return supp.SupportClassString;
          }
      }
      public class SupportClass {
          public string SupportClassString;
      }
      Contoh 3

      Contoh terakhir menunjukkan cara membuat serialisasi array objek.

      using System;
      using System.IO;
      using System.Runtime.Serialization;
      using System.Runtime.Serialization.Formatters.Binary;

      public class SerialTest {
          public void SerializeNow() {
              ClassToSerialize[] c = new ClassToSerialize[3];
              c[0] = new ClassToSerialize();
              c[0].Name = "bipin";
              c[0].Age = 26;
              c[1] = new ClassToSerialize();
              c[1].Name = "abc";
              c[1].Age = 75;
              c[2] = new ClassToSerialize();
              c[2].Name = "pqr";
              c[2].Age = 50;
              ClassToSerialize.CompanyName = "xyz";
              File f = new File("temp.dat");
              Stream s = f.Open(FileMode.Create);
              BinaryFormatter b = new BinaryFormatter();
              b.Serialize(s, c);
              s.Close();
          }
          public void DeSerializeNow() {
              ClassToSerialize[] c;
              File f = new File("temp.dat");
              Stream s = f.Open(FileMode.Open);
              BinaryFormatter b = new BinaryFormatter();
              c = (ClassToSerialize[]) b.Deserialize(s);
              Console.WriteLine("Name :" + c[2].Name);
              Console.WriteLine("Age :" + c[2].Age);
              Console.WriteLine("Company Name :" + ClassToSerialize.CompanyName);
              s.Close();
          }
          public static void Main(string[] s) {
              SerialTest st = new SerialTest();
              st.SerializeNow();
              st.DeSerializeNow();
          }
      }
      public class ClassToSerialize {
          private int age;
          private string name;
          static string companyname;
          public int Age {
              get {
                  return age;
              }
              set {
                  age = value;
              }
          }
          public string Name {
              get {
                  return name;
              }
              set {
                  name = value;
              }
          }
          public static string CompanyName {
              get {
                  return companyname;
              }
              set {
                  companyname = value;
              }
          }
      }


      CODING CONVERSIONS


      Konvensi Pengkodean (Coding Conversions) melayani tujuan berikut :
      • Mereka membuat tampilan kode yang konsisten, sehingga pembaca dapat fokus pada konten, bukan tata letak.
      • Mereka memungkinkan pembaca untuk memahami kode lebih cepat dengan membuat asumsi berdasarkan pengalaman sebelumnya.
      • Mereka memfasilitasi penyalinan, perubahan, dan pemeliharaan kode.
      • Mereka menunjukkan praktik terbaik C#.

      A. Naming Conventions (Konvensi Penamaan)

      Ada beberapa konvensi penamaan yang perlu dipertimbangkan saat menulis kode C#.

      Dalam contoh berikut, salah satu panduan yang berkaitan dengan elemen bertanda public juga berlaku saat bekerja dengan elemen protected internal dan protected, yang semuanya dimaksudkan agar terlihat oleh penelepon eksternal.

      1. Pascal Case

      Gunakan pascal casing ("PascalCasing") saat memberi nama classrecord, atau struct.

      public class DataService
      {
      }
      

      public record PhysicalAddress(
          string Street,
          string City,
          string StateOrProvince,
          string ZipCode);
      

      public struct ValueCoordinate
      {
      }
      

      Saat memberi nama interface, gunakan pascal casing selain awalan nama dengan I. Ini dengan jelas menunjukkan kepada konsumen bahwa itu adalah interface.

      public interface IWorkerQueue
      {
      }
      

      Saat memberi nama tipe anggota public, seperti bidang, properti, peristiwa, metode, dan fungsi lokal, gunakan casing pascal.

      public class ExampleEvents
      {
          // A public field, these should be used sparingly
          public bool IsValid;
      
          // An init-only property
          public IWorkerQueue WorkerQueue { get; init; }
      
          // An event
          public event Action EventProcessing;
      
          // Method
          public void StartEventProcessing()
          {
              // Local function
              static int CountQueueItems() => WorkerQueue.Count;
              // ...
          }
      }
      

      Saat menulis rekaman posisi, gunakan casing pascal untuk parameter karena itu adalah properti publik dari rekaman.

      public record PhysicalAddress(
          string Street,
          string City,
          string StateOrProvince,
          string ZipCode);

      2. Camel Case

      Gunakan camel casing ("camelCasing") saat memberi nama bidang 
      private atau internal, dan awali dengan _.

      public class DataService
      {
          private IWorkerQueue _workerQueue;
      }
      

      Saat bekerja dengan bidang static yang bersifat private atau internal, gunakan awalan s_ dan untuk benang statis gunakan t_.

      public class DataService
      {
          private static IWorkerQueue s_workerQueue;
      
          [ThreadStatic]
          private static TimeSpan t_timeSpan;
      }
      

      Saat menulis parameter metode, gunakan camel casing.

      public T SomeMethod<T>(int someNumber, bool isValid)
      {
      }
      

      3. Konvensi Penamaan Tambahan

      Contoh yang tidak termasuk menggunakan arahan, gunakan kualifikasi namespace. Jika Anda mengetahui bahwa namespace diimpor secara default dalam sebuah proyek, Anda tidak harus sepenuhnya memenuhi syarat nama dari namespace tersebut. Nama yang memenuhi syarat dapat diganti setelah titik (.) jika terlalu panjang untuk satu baris, seperti yang ditunjukkan pada contoh berikut.

      var currentPerformanceCounterCategory = new System.Diagnostics.
          PerformanceCounterCategory();
      

      Anda tidak perlu mengubah nama objek yang dibuat dengan menggunakan alat desainer Visual Studio agar sesuai dengan pedoman lainnya.

      B. Standar Pengkodean C# (C# Coding Standards)

      Object Name
      Notation
      Length
      Plural
      Prefix
      Suffix
      Abbreviation
      Char Mask
      Underscores
      Namespace name
      PascalCase
      128
      Yes
      Yes
      No
      No
      [A-z][0-9]
      No
      Class name
      PascalCase
      128
      No
      No
      Yes
      No
      [A-z][0-9]
      No
      Constructor name
      PascalCase
      128
      No
      No
      Yes
      No
      [A-z][0-9]
      No
      Method name
      PascalCase
      128
      Yes
      No
      No
      No
      [A-z][0-9]
      No
      Method arguments
      camelCase
      128
      Yes
      No
      No
      Yes
      [A-z][0-9]
      No
      Local variables
      camelCase
      50
      Yes
      No
      No
      Yes
      [A-z][0-9]
      No
      Constants name
      PascalCase
      50
      No
      No
      No
      No
      [A-z][0-9]
      No
      Field name
      camelCase
      50
      Yes
      No
      No
      Yes
      [A-z][0-9]
      Yes
      Properties name
      PascalCase
      50
      Yes
      No
      No
      Yes
      [A-z][0-9]
      No
      Delegate name
      PascalCase
      128
      No
      No
      Yes
      Yes
      [A-z]
      No
      Enum type name
      PascalCase
      128
      Yes
      No
      No
      No
      [A-z]
      No

      1. Gunakan PascalCasing untuk nama kelas dan nama method :

      public class ClientActivity
      {
        public void ClearStatistics()
        {
          //...
        }
        public void CalculateStatistics()
        {
          //...
        }
      }
      

      Mengapa? Konsisten dengan Microsoft .NET Framework dan mudah dibaca.

      2. Gunakan camelCasing untuk metode argumen dan variabel lokal :

      public class UserLog
      {
        public void Add(LogEvent logEvent)
        {
          int itemCount = logEvent.Items.Count;
          // ...
        }
      }
      

      Mengapa? Konsisten dengan Microsoft .NET Framework dan mudah dibaca.

      3. Jangan gunakan Notasi Hungaria atau jenis identifikasi lainnya dalam pengidentifikasi

      // Correct
      int counter;
      string name;
      
      // Avoid
      int iCounter;
      string strName
      

      Mengapa? Konsisten dengan Microsoft .NET Framework dan Visual Studio IDE membuat penentuan jenis menjadi sangat mudah (melalui tooltips). Secara umum, Anda ingin menghindari indikator tipe dalam pengenal apa pun.

      4. Jangan gunakan Screaming Caps untuk konstanta atau variabel readonly :

      // Correct
      public const string ShippingType = "DropShip";
      
      // Avoid
      public const string SHIPPINGTYPE = "DropShip";
      

      Mengapa? Konsisten dengan Microsoft .NET Framework. Caps menarik terlalu banyak perhatian.

      5. Gunakan nama yang bermakna untuk variabel.

      Contoh berikut menggunakan seattleCustomers untuk pelanggan yang berlokasi di Seattle :

      var seattleCustomers = from customer in customers
        where customer.City == "Seattle" 
        select customer.Name;
      

      Mengapa? Konsisten dengan Microsoft .NET Framework dan mudah dibaca.

      6. Hindari menggunakan Singkatan. 

      Pengecualian : singkatan yang biasa digunakan sebagai nama, seperti Id, Xml, Ftp, Uri.

      // Correct
      UserGroup userGroup;
      Assignment employeeAssignment;
      
      // Avoid
      UserGroup usrGrp;
      Assignment empAssignment; 
      
      // Exceptions
      CustomerId customerId;
      XmlDocument xmlDocument;
      FtpHelper ftpHelper;
      UriPart uriPart;
      

      Mengapa? Konsisten dengan Microsoft .NET Framework dan mencegah singkatan yang tidak konsisten.

      7. Gunakan PascalCasing atau camelCasing (Tergantung pada jenis pengenal) untuk singkatan 3 karakter atau lebih (2 karakter keduanya huruf besar ketika PascalCasing sesuai atau di dalam pengenal) :

      HtmlHelper htmlHelper;
      FtpTransfer ftpTransfer, fastFtpTransfer;
      UIControl uiControl, nextUIControl;
      

      Mengapa? Konsisten dengan Microsoft .NET Framework. Caps akan menarik terlalu banyak perhatian secara visual.

      8. Jangan gunakan Garis Bawah dalam pengidentifikasi. 

      Pengecualian : Anda dapat mengawali bidang pribadi dengan garis bawah:

      // Correct
      public DateTime clientAppointment;
      public TimeSpan timeLeft;
      
      // Avoid
      public DateTime client_Appointment;
      public TimeSpan time_Left;
      
      // Exception (Class field)
      private DateTime _registrationDate;
      

      Mengapa? Konsisten dengan Microsoft .NET Framework dan membuat kode lebih alami untuk dibaca (tanpa 'cercaan'). Juga menghindari stres garis bawah (ketidakmampuan untuk melihat garis bawah).

      9. Gunakan nama tipe yang telah ditentukan sebelumnya (alias C#) seperti intfloatstring untuk deklarasi lokal, parameter, dan anggota. 

      Gunakan nama .NET Framework seperti Int32, Single, String saat mengakses anggota statis tipe seperti Int32.TryParse atau String.Join.

      // Correct
      string firstName;
      int lastIndex;
      bool isSaved;
      string commaSeparatedNames = String.Join(", ", names);
      int index = Int32.Parse(input);
      
      // Avoid
      String firstName;
      Int32 lastIndex;
      Boolean isSaved;
      string commaSeparatedNames = string.Join(", ", names);
      int index = int.Parse(input);
      

      Mengapa? Konsisten dengan Microsoft .NET Framework dan membuat kode lebih alami untuk dibaca.

      10. Gunakan tipe implisit var untuk deklarasi variabel lokal. 

      Pengecualian : tipe primitif (int, string, double, dll) menggunakan nama yang telah ditentukan.

      var stream = File.Create(path);
      var customers = new Dictionary();
      
      // Exceptions
      int index = 100;
      string timeSheet;
      bool isCompleted;
      

      Mengapa? Menghilangkan kekacauan, terutama dengan tipe generik yang kompleks. Jenis mudah dideteksi dengan tooltips Visual Studio.

      11. Gunakan frasa kata benda atau kata benda untuk menamai kelas.

      public class Employee
      {
      }
      public class BusinessLocation
      {
      }
      public class DocumentCollection
      {
      }
      

      Mengapa? Konsisten dengan Microsoft .NET Framework dan mudah diingat.

      12. Lakukan awalan antar muka dengan huruf I.

      Nama antar muka berupa kata benda (frasa) atau kata sifat.

      public interface IShape
      {
      }
      public interface IShapeCollection
      {
      }
      public interface IGroupable
      {
      }
      

      Mengapa? Konsisten dengan Microsoft .NET Framework.

      13. Beri nama file sumber sesuai dengan kelas utamanya. 

      Pengecualian : nama file dengan kelas parsial mencerminkan sumber atau tujuannya, mis. desainer, dihasilkan, dll.

      // Located in Task.cs
      public partial class Task
      {
      }
      // Located in Task.generated.cs
      public partial class Task
      {
      }

      Mengapa? Konsisten dengan praktik Microsoft. File diurutkan menurut abjad dan sebagian kelas tetap berdekatan.

      14. Atur ruang nama dengan struktur yang jelas :

      // Examples
      namespace Company.Technology.Feature.Subnamespace
      {
      }
      namespace Company.Product.Module.SubModule
      {
      }
      namespace Product.Module.Component
      {
      }
      namespace Product.Layer.Module.Group
      {
      }

      Mengapa? Konsisten dengan Microsoft .NET Framework. Mempertahankan organisasi yang baik dari basis kode Anda.

      15. Lakukan perataan kurung kurawal secara vertikal :

      // Correct
      class Program
      {
        static void Main(string[] args)
        {
          //...
        }
      }

      Mengapa? Microsoft memiliki standar yang berbeda, tetapi pengembang lebih memilih tanda kurung yang disejajarkan secara vertikal.

      16. Mendeklarasikan semua variabel anggota di bagian atas kelas, dengan variabel statis di bagian paling atas.

      // Correct
      public class Account
      {
        public static string BankName;
        public static decimal Reserves;      
        public string Number { get; set; }
        public DateTime DateOpened { get; set; }
        public DateTime DateClosed { get; set; }
        public decimal Balance { get; set; }     
        // Constructor
        public Account()
        {
          // ...
        }
      }

      Mengapa? Praktik yang diterima secara umum yang mencegah kebutuhan untuk mencari deklarasi variabel.

      17. Gunakan nama tunggal untuk enum. 

      Pengecualian : enum bidang bit.

      // Correct
      public enum Color
      {
        Red,
        Green,
        Blue,
        Yellow,
        Magenta,
        Cyan
      }
      
      // Exception
      [Flags]
      public enum Dockings
      {
        None = 0,
        Top = 1,
        Right = 2, 
        Bottom = 4,
        Left = 8
      }

      Mengapa? Konsisten dengan Microsoft .NET Framework dan membuat kode lebih alami untuk dibaca. Bendera jamak karena enum dapat menyimpan banyak nilai (menggunakan bitwise 'OR').

      18. Jangan secara eksplisit menentukan jenis enum atau nilai enum (kecuali bidang bit) :

      // Don't
      public enum Direction : long
      {
        North = 1,
        East = 2,
        South = 3,
        West = 4
      } 
      // Correct
      public enum Direction
      {
        North,
        East,
        South,
        West
      }

      Mengapa? Dapat membuat kebingungan saat mengandalkan tipe dan nilai aktual.

      19. Jangan gunakan akhiran "Enum" dalam nama tipe enum :

      // Don't
      public enum CoinEnum
      {
        Penny,
        Nickel,
        Dime,
        Quarter,
        Dollar
      }
      
      // Correct
      public enum Coin
      {
        Penny,
        Nickel,
        Dime,
        Quarter,
        Dollar
      }

      Mengapa? Konsisten dengan Microsoft .NET Framework dan konsisten dengan aturan sebelumnya tanpa indikator tipe dalam pengidentifikasi.

      20. Jangan gunakan akhiran "Flag" atau "Flags" dalam nama tipe enum :

      // Don't
      [Flags]
      public enum DockingsFlags
      {
        None = 0,
        Top = 1,
        Right = 2, 
        Bottom = 4,
        Left = 8
      }
      
      // Correct
      [Flags]
      public enum Dockings
      {
        None = 0,
        Top = 1,
        Right = 2, 
        Bottom = 4,
        Left = 8
      }

      Mengapa? Konsisten dengan Microsoft .NET Framework dan konsisten dengan aturan sebelumnya tanpa indikator tipe dalam pengidentifikasi.

      21. Gunakan akhiran EventArgs pada pembuatan kelas baru yang berisi informasi tentang event :

      // Correct
      public class BarcodeReadEventArgs : System.EventArgs
      {
      }

      Mengapa? Konsisten dengan Microsoft .NET Framework dan mudah dibaca.

      22. Beri nama event handler (delegasi yang digunakan sebagai jenis event) dengan akhiran "EventHandler", seperti yang ditunjukkan pada contoh berikut :

      public delegate void ReadBarcodeEventHandler(object sender, ReadBarcodeEventArgs e);

      Mengapa? Konsisten dengan Microsoft .NET Framework dan mudah dibaca.

      23. Jangan membuat nama parameter dalam metode (atau konstruktor) yang hanya berbeda dengan register :

      // Avoid
      private void MyFunction(string name, string Name)
      {
        //...
      }

      Mengapa? Konsisten dengan Microsoft .NET Framework dan mudah dibaca, dan juga mengecualikan kemungkinan terjadinya situasi konflik.

      24. Gunakan dua parameter bernama sender dan e dalam event handler. 

      Parameter pengirim mewakili objek yang mengangkat acara. Parameter pengirim biasanya bertipe objek, bahkan jika dimungkinkan untuk menggunakan tipe yang lebih spesifik.

      public void ReadBarcodeEventHandler(object sender, ReadBarcodeEventArgs e)
      {
        //...
      }

      Mengapa? Konsisten dengan Microsoft .NET Framework dan konsisten dengan aturan sebelumnya tanpa indikator tipe dalam pengidentifikasi.

      25. Gunakan akhiran Pengecualian pada pembuatan kelas baru yang berisi informasi tentang pengecualian :

      // Correct
      public class BarcodeReadException : System.Exception
      {
      }

      Mengapa? Konsisten dengan Microsoft .NET Framework dan mudah dibaca.

      26. Gunakan awalan Any, Is, Have atau kata kunci serupa untuk pengidentifikasi boolean :

      // Correct
      public static bool IsNullOrEmpty(string value) {
          return (value == null || value.Length == 0);
      }

      Mengapa? Konsisten dengan Microsoft .NET Framework dan mudah dibaca.

      27. Gunakan Argumen Bernama dalam pemanggilan method :

      // Method
      public void DoSomething(string foo, int bar) 
      {
      ...
      }
      
      // Avoid
      DoSomething("someString", 1);
      
      // Correct
      DoSomething(foo: "someString", bar: 1);

      Mengapa? Konsisten dengan Microsoft .NET Framework dan mudah dibaca. Dalam Named Arguments, kita tidak perlu meneruskan parameter secara berurutan seperti yang didefinisikan pada definisi method, sehingga kita dapat meneruskan argumen dalam urutan apa pun pada pemanggilan method.


      Jadi OOP ini adalah untuk mempermudah Programmer untuk memogram dari suatu Kode Porgram. Mohon maaf apabila ada kesalahan dalam penulisan Kode. Dan mungkin saja untuk OOP Java akan menyusul dan Modul Pemrograman C# juga akan menysul.

      Terima Kasih šŸ˜„šŸ˜˜šŸ‘ŒšŸ‘ :)

      Wassalamu‘alaikum wr. wb.

      Ads