Những tính năng mới của C# 3.0

Những tính năng mới của C# 3.0

Xin chào các bạn. Trong bài viết này mình sẽ đề cập đến một số tính năng mới của C# 3.0 được giới thiệu trong .NET 3.5.

I/ Automatically Implemented Properties (Thuộc tính cài đặt tự động)

public class Point {
private int _x, _y;
public int X {
   get { return _x; }
   set { _x = value; }
  }
public int Y {
  get { return _y; }
  set { _y = value; }
  }
}

Đoạn code trên định nghĩa một class với hai thuộc tính cơ bản. Thuộc tính cài đặt tự động cho phép chúng ta viết ngắn hơn bằng cánh tự động sinh ra trường private và các thao tác get/set.

public class Point {
public int X { get; set; }
public int Y { get; set; }
}

Đặc tính mới này giúp cho code dễ hiểu và ngắn gọn hơn
II/ Local Variable Type Inference (Suy diễn kiểu cho biến cục bộ)
Với đặc tính này, kiểu của biến local được suy ra từ biểu thức sử dụng khởi tạo cho biến. Nó được dung bằng cách sử dụng từ khóa “var”.

var num = 50;
var str = "simple string";
var obj = new myType();
var numbers = new int[] {1,2,3};
var dic = new Dictionary();
Trình biên dịch sẽ sinh ra file MSIL giống như chúng ta biên dịch đoạn code dưới:
int num = 50;
string str = "simple string";
myType obj = new myType();
int[] numbers = new int[] {1,2,3};
Dictionary dic = new Dictionary();

III/ Object Initializers (Khai báo đối tượng bằng một dòng lệnh)
Có class Point ban đầu , giả sử rằng chúng ta muốn định nghĩa một instance cho class này. Chúng ta sẽ phải tạo một đối tượng và bắt đầu set thuộc tính cho nó, chúng ta sẽ viết như sau:

Point p = new Point();
p.X = 0;
p.Y = 0;

Ta có thể viết lại đoạn code trên sử dụng Objects Initializers và gộp lại như sau:

Point p = new Point() { X = 0, Y = 0 };

Đặc điểm này cũng có thể áp dụng với Collection như ví dụ dưới:

List points = new List {
new Point { X = 2, Y = 5 },
new Point { X = 1, Y = -10 },
new Point { X = 3, Y = 0 }
};

Phương thức add() của List sẽ được gọi tự động để add các đối tượng Point vào List.
IV/ Anonymous Types (Tạo đối tượng không cần định nghĩa lớp)
Đặc tính mới này cho phép chúng ta định nghĩa nhiều kiểu biến trong cùng một dòng mà không phải định nghĩa một class cho kiểu đó. Hãy tưởng tượng chúng ta muốn sử dụng đối tượng Point mà không cần định nghĩa lớp Point. Chúng ta sẽ sử dụng cùng một cú pháp ban đầu để khởi tạo đối tượng mà không cần “type name”.

var p = new {X = 0, Y = 2};

V/ Lambda Expressions (Biểu thức Lambda)
Biểu thức lambda là một hàm vô danh có chứa những biểu thức và những câu lệnh, và có thể được sử dụng để tạo những delegate hoặc những những cây biểu thức.
Tất cả biểu thức lambda sử dụng toán tử “=>“ . Bên trái toán tử là những tham số input, và bên phải là biểu thức hay khối lệnh. Biểu thức có thể gán tới delegate như sau:

delegate int del(int i);
static void Main(string[] args)
{
del myDelegate = x => x * x;
int j = myDelegate(5); //j = 25
}

Tham số của biểu thức lambda có thể là kiểu tường minh hay không tường minh. Đối với kiểu tường minh, kiểu của mỗi biểu thức là được xác định rõ ràng. Trong kiểu không tường minh, kiểu của biểu thức được suy ra từ nội dung của nó.

(int x) => x + 1 // explicitly typed parameter
(y,z) => return y * z; // implicitly typed parameter

VI/ Extension Methods (Thêm hàm vào đối tượng mà không cần viết lại mã hay kế thừa)
Extension methods cho phép mở rộng các lớp đã tồn tại với các method bổ sung, mà không cần phải có mã nguồn của lớp đó. Vì vậy thay vì viết các helper method cho đối tượng, các method sẽ trở thành một phần của đối tượng.
Giả sử chúng ta muốn kiểm tra một chuỗi để xem nó có phải đúng là địa chỉ email hay không. Chúng ta có thể làm điều này bằng cách viết một hàm lấy một chuối như một argument và trả về giá trị true/ false. Dùng extension methods chúng ta có thể làm như sau:

public static class MyExtensions {
public static bool IsValidEmailAddress(this String s) {
Regex regex = new Regex( @"^[w-.]+@([w-]+.)+[w-]{2,4}$" );
return regex.IsMatch(s);
}
}

Chúng ta định nghĩa một static class với một static method chính là extension method. Chú ý, từ khóa “this” trước tham số đầu tiên của kiểu “string”. Nó sẽ nói với trình biên dịch rằng: extension method này được thêm vào các object của kiểu “String”. Và sau đó chúng ta có thể gọi nó từ các đối tượng kiểu “String” như một member function.

using MyExtensions;

String email = Request.QueryString["email"];
if ( email.IsValidEmailAddress() ) {
// ...

}

VII/ LinQ
Trước khi có LinQ

using System;
using System.Collections.Generic;
namespace Demo01
{
class Program
{
static void Main(string[] args)
{
string[] greetings = { "hello world", "hello LINQ", "hello CSharp" };
List result = new List();
foreach (string greeting in greetings)
{
if (greeting.EndsWith("LINQ"))
{
result.Add(greeting);
}
}
foreach (string item in result)
{
Console.WriteLine(item);
}
Console.ReadLine();
}
}
}

khi có Linq

using System;
using System.Linq;
namespace Demo01
{
class Program
{
static void Main(string[] args)
{
string[] greetings = { "hello world", "hello LINQ", "hello CSharp" };
var items = from s in greetings where s.EndsWith("LINQ") select s;
foreach (var item in items)
Console.WriteLine(item);
Console.ReadLine();
}
}
}

Tại sao lai dùng linq?
• Với mỗi datasource, thì chúng có ngôn ngữ truy vấn, cấu trúc riêng. Như vậy, nếu muốn sử dụng một datasource mới, chúng ta sẽ phải tìm hiểu ngôn ngữ truy vấn, và cú pháp của nó. Linq, một cho tất cả.
• Linq giúp viết code ngắn hơn, có ỹ nghĩa hơn
Phân loại:
• Linq to Objects
• Linq to ADO . Net
-> Linq to Dataset
-> Linq to SQL
-> Linq to Entities
• Linq to XML
VIII/ Friend Assemblies (Cho phép một Assembly truy cập những thành phần internalcủa một Assembly khác)
Với friend assembly, một internal class hoặc internal member trong một assembly có thể được truy nhập từ assembly khác. Private class hay private member thì không thể truy cập được.
Để cho một assembly B có thể truy cập vào những internal class hay internal member của assembly A, thuộc tính InternalsVisibleToAttribute trong assembly A phải được sử dụng. Khi biên dịch một assembly B, phải xác định rõ ràng tên của output file(.exe hoặc .dll) với option /out của trình biên dịch.
Ví dụ: trong ví dụ dưới đây, các internal class và internal member có thể truy cập được từ assembly cs_friend_assemblies_2.

// cs_friend_assemblies.cs
// compile with: /target:library
using System.Runtime.CompilerServices;
using System;

[assembly:InternalsVisibleTo("cs_friend_assemblies_2")]

// internal by default
class Class1
{
public void Test()
{
Console.WriteLine("Class1.Test");
}
}

// public type with internal member
public class Class2
{
internal void Test()
{
Console.WriteLine("Class2.Test");
}
}

IX / Partial Method
Partial method có khai báo nằm trong một phần của partial class, còn cài đặt nó nằm trong một phần khác của partial class. Khi khai báo một partial method, nếu lập trình viên không cài đặt nó, trình biên dịch xóa bỏ khai báo đó. Những điều kiện sau được áp dụng cho Partial Method:
• Khai báo trong cả hai phần của partial class phải phù hợp.
• Method phải return void.
• Partial method phải là private
Ví dụ dưới đây thể hiện partial method được định nghĩa tại hai phần của partial class:

namespace PM
{
partial class A
{
partial void OnSomethingHappened(String s);
}

// This part can be in a separate file.
partial class A
{
// Comment out this method and the program
// will still compile.
partial void OnSomethingHappened(String s)
{
Console.WriteLine("Something happened: {0}", s);
}
}
}

Happy coding :)

Khi trích dẫn bài viết từ tek.eten.vn, xin vui lòng ghi rõ nguồn. Chúng tôi sẽ rất cảm ơn bạn!