Series C# hay ho: Những điều thú vị trong C# (Phần 1)

Như đã giới thiệu, mình là một lập trình viên C#.NET, do đó C# là ngôn ngữ mình tiếp xúc hằng ngày. Lẽ dĩ nhiên, trong quá trình sử dụng + tìm hiểu, mình nhận thấy có C# có những điều nhỏ nhặt, nhưng lại khá hay ho, cho thấy các cụ Microsoft có suy nghĩ tới developer khi tạo ra ngôn ngữ này.

Nội dung bài viết này là những điều “hay ho” mình đã nói. Những điều “hay ho” (mà ít người biết) này giúp cho việc code được nhanh hơn, code dễ đọc dễ hiểu hơn1. Trong quá trình so sánh, mình có nhắc tới sự thuận tiện khi developer bằng C# so với “các ngôn ngữ khác”. Ở đây cũng giống như so sánh OMO với “bột giặt thường” vậy, không có ý so sánh C# với Java hay PHP của các bạn đâu nhé, các bạn đừng ném đá tội nghiệp =))).

1. Từ khóa “var” và Anonymous Object

Ngày trước, khi khai báo 1 biến, chúng ta phải khai báo type của biến đó (Ở đây là stream).


Stream stream = new FileStream("C:\\abc.txt", FileMode.CreateNew);

Tuy nhiên, với từ khóa var, chúng ta có thể khai báo biến mà không cần quan tâm đến type. Các chức năng nhắc lệnh vẫn được thực hiện bình thường.


var stream = new FileStream("C:\\abc.txt", FileMode.CreateNew);

Kết hợp với anonymous object, ta có thể khai báo 1 object với các properties định sẵn, không cần phải khai báo class:


var sampleObj = new { FirstProp = "A", SecondProp = "B"};
Console.WriteLine(sampleObj.FirstProp + sampleObj.SecondProp ); //AB

Anonymous object này có thể được serialize thành XML, JSON. Có thể nói từ khóa “var” là 1 cứu cánh cho những developer “lười” như mình. (Nói nhỏ các bạn nghe, trong Java không có anonymous object cũng như từ khóa “var” này đâu).

2. Tự động tạo Properties

Khi được học về tính bao đóng (Encapsulation) trong trường đại học, chúng ta đều được dạy là không nên access trực tiếp field của object, mà phải thông qua các method như sau.


public class Student
{
    private string _name;
    public string Name
    {
        get { return _name; }
        set { _name = value; }
    }
 }

Với C#, khi ta khai báo 1 auto-property, ngôn ngữ sẽ tự tạo 1 field private, gettter và setter cho field đó. Ta còn có thể set private cho getter và setter đó. Code mới như sau:


public string Name { get; set; }

public string Name { get; private set; } //Field is read only, private setter

3. using blocks

Ngày xửa ngày xưa,khi chưa có using, mỗi khi muốn đóng 1 stream, connection, ta thường cho vào block try/finally.


try
 {
    stream = new FileStream("C:\\abc.txt", FileMode.CreateNew);
    stream2 = new FileStream("C:\\abc2.txt", FileMode.CreateNew);
 //Do some readding
 }
 finally
 {
    if (stream != null) stream.Close();
    if (stream2 != null) stream2.Close();
 }

Sau 1 thời gian, đống code này sẽ khá rối. Với using, ta không cần phải lo chuyện đóng connection bằng tay, code ngắn và dễ hiểu hơn nhiều


 using(var stream = new FileStream("C:\\abc.txt", FileMode.CreateNew))
 using(var stream2 = new FileStream("C:\\abc.txt", FileMode.CreateNew))
 {
   //Do some readding
 }

4. Đo thời gian với class Stopwatch

Đo thời gian 1 method chạy chỉ với 2 dòng code, StartNew và Stop, vô cùng đơn giản.


 var sw = Stopwatch.StartNew();
 DoSomething();
 sw.Stop();
 Console.WriteLine("Time elapsed: " + sw.ElapsedMilliseconds);

5. Toán tử 3 ngôi, toán tử null

Thông thường, khi gán giá trị default cho 1 biến null, ta thường set bằng 1 trong 2 cách sau


if (input == null)
{
   input = "default";
}

// Toán tử 3 ngôi
input = input != null ? input : "default";

Với C#, ta có toán tử null, giúp code ngắn hơn và dễ đọc hơn

input = input ?? "default"; //Nếu index là null thì set bằng default

Việc implement một toán tử nhỏ nhặt thế này trong ngôn ngữ cho thấy các bạn developer của Microsoft rất biết suy nghĩ cho giới developer chúng ta.

6. Khởi tạo object và collection

Thông thường, khi khởi tạo object và property, ta thường làm như sau


Student student = new Student();
student.Name = "Hoang";
student.Age = 10;

Với C#, mọi chuyện trở nên đơn giản ngắn gọn hơn

Student student = new Student { Name = "Hoang", Age = 10};

Có thể bạn sẽ hỏi: Tại sao không tạo constructor cho object, cũng vậy thôi mà. Mình xin trả lời: Khi tạo constructor, ta phải khai báo toàn tham số truyền vào. Với cách này, ta có thể truyền vào số lượng tham số ta muốn (Ví dụ object student có 10 fields, ta chỉ muốn set 2 fields).

Tiếp theo là khởi tạo 1 collection, cách thông thường và cách C#. Cách nào ngắn gọn, dễ hiểu hơn các bạn tự thấy nhỉ.


//Cách cũ
 List<string> list = new List<string>();
 list.Add("string 1");
 list.Add("string 2");
 list.Add("string 3");

//Cách mới
 List<string> list = new List<string> { "string 1" , "string 2", "string 3" };

Kết hợp cả class và collection


List<Student> list = new List<Student>
{
    new Student { Name = "Student 2", Age = 2},
    new Student { Name = "Student 3", Age = 4}
};

7. Extension method

Có 1 số trường hợp, ta muốn thêm method cho một số class sealed, hoặc class từ các library khác. Với một số ngôn ngữ, điều này là ko thể được, nhưng với C#, chúng ta có thể dùng extension method.

VD ở đây, chúng ta có class Student từ library khác, không thể sửa code. Ta muốn thêm method Print.


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

Chúng ta tạo 1 extenstion class, class này phải là static class, method cũng phải static, params đầu tiên truyền vào là class cần extention, với từ khóa this.


public static class StudentExtension
{
   public static void Print(this Student student)
   {
      Console.WriteLine(student.ToString());
   }
}

//Sử dụng
var student = new Student();
student.Print();

Trong quá trình tìm hiểu, bạn sẽ thấy extension method rất hữu dụng. (Nói nhỏ nữa là trong Java không có cái extension method này đâu hen).

8. LINQQQQQQQQQQQQQQQQ

Thật ra chỉ có 1 chữ q thôi, những vì đây là 1 trong những điều cực kì hay ho của C#, nên mình nhấn mạnh.

Linq khá dễ sử dụng, nhưng để hiểu nó cần biết về Predicate, Func, lambda v…v, mình sẽ dành 1 bài viết để nói rõ hơn. Ở đây mình chỉ giới thiệu sợ, vì sao nó hay.

Ngày xưa, khi chưa có linq, giả sử ta muốn tìm những học sinh có tuổi <20 trong list, ta cần viết code dài như sau:


var studentsUnder20 = new List<Student>();
foreach (var student in students)
{
    if (student.Age < 20) studentsUnder20.Add(student);
}

Ngày nay, với linq, ta chỉ cần đúng 1 dòng code:


var studentsUnder20 = students.Where(student => student.Age < 20);

Đó chỉ là 1 trong vô vàn những tính năng hay ho của Linq thôi, mình sẽ nói rõ hơn ở bài viết khác. (Nói nhỏ luôn, trong javascript ta có thể dùng thư việc underscore để có tính năng tương tự. Trong Java 7 trở xuống thì không có Linq, từ Java 8 trở lên mới bắt đầu thêm Linq vào để bắt chước C#).

Tới đây bài viết cũng đã khá dài. Hẹn gặp lại các bạn ở phần 2 nhé. Mọi ý kiến hay gạch đá đều được tiếp thu nhiệt liệt.

Bài viết được phỏng dịch + lượt từ bản gốc tiếng Anh (Đã xin phép tác giả) : http://geekswithblogs.net/BlackRabbitCoder/archive/2011/10/24/c.net-little-wonders-the-complete-collection-again.aspx

25 thoughts on “Series C# hay ho: Những điều thú vị trong C# (Phần 1)”

  1. Có cái số 5 chưa biết :))
    Dùng linq thì tốc độ có chậm hơn so với cách thông thường không?

    Like

      1. Ví dụ mình có một Table(manv, tennv, nhomnv) chừng 3000 dòng mình muốn lọc ra một table gồm nhomnv=”KeToan”, thì cái này nếu mình dùng For rồi check từng dòng nó có nhanh hơn khi mình dùng LINQ không anh.
        Trường hợp ít dòng hơn và nhìu dòng hơn, a cho ý kiến luôn ạ.
        Cám ơn anh !

        Like

  2. Linq thì chỉ dùng dữ liệu lớn còn đơn vừa và nhỏ thì nên thông thường sẽ nhanh hơn, ví dụ như tìm sinh viên tuổi <20 foreach nhanh gấp mấy lần nếu dữ liệu nằm giá vài ngàn dòng

    Liked by 1 person

  3. đó giờ chưa dùng var bao giờ, toàn khai báo datatype cho variable rõ ràng không à. LINQ hay nhưng chỉ nên áp dụng trong những trường hợp cần thiết như data lớn, còn với lượng data không đáng kể thì nên chọn giải pháp thông thường vì performance của câu truy vấn.

    Like

  4. Trên visual 2015 đã có đo thời gian chạy từng dòng code or method được cài sẵn rùi nha anh 😀

    Like

  5. #7. Extension method:
    chư vị huynh đài cho đệ hỏi ngu chút, nếu thư viện nó đóng gói dạng .dll thì mình có Extension nó được không nhỉ??

    Like

  6. ” Khi tạo constructor, ta phải khai báo toàn tham số truyền vào. Với cách này, ta có thể truyền vào số lượng tham số ta muốn (Ví dụ object student có 10 fields, ta chỉ muốn set 2 fields). ”
    mình cũng có thể tạo constructor chỉ set 2 fields thôi cũng được mà anh .

    Like

  7. Và cuối cùng cũng có những người đồng quan điểm rằng cần thay đổi giao diện 😀
    Phải công nhận là đọc mỏi mắt quá trời 😀

    Like

  8. a Hoàng cho e hỏi cái auto-property mình viết singleton vô luôn đc ko?
    e làm trên unity thì viết singleton vô cái auto-property luôn thì nó báo lỗi. Viết bình thường thì lại đc

    Liked by 2 people

Leave a comment