Tham số tên và tham số tuỳ chọn là 2 chức năng khác nhau, nhưng thường được dùng với nhau. Tham số tùy chọn cho các bạn sự lựa chọn dùng hoặc không dùng tham số đó khi gọi một hàm có tham số tùy chọn, trong khi tham số tên là phương pháp để đưa một tham số qua một hàm bằng cách dùng tên của tham số thay vì dùng vị thế của tham số đó theo thứ tự từ trái qua phải.

Có nhiều API, đặc biệt là những linh kiện COM như Microsoft Office API, đã được viết để cung cấp những hàm dùng tham số tên và tham số tùy chọn. Hiện tại (khi chưa có phiên bản C# 4.0), một lập trình C# gặp phải rất nhiều khó khăn khi muốn gọi những hàm có tham số tên và tham số tuỳ chọn. Đôi khi, phải gọi một hàm có hơn 30 tham số, và phải đưa qua hơn 30 tham số đó, thay vì chỉ đưa qua những tham số tuỳ chọn bằng cách dùng tên của tham số.

Và ngay cả những hàm được định nghĩa trong những lớp đối tượng mà các bạn đã tạo lên, muốn gọi những hàm đó, phải đưa qua đầy đủ những tham số thích hợp đã được định nghĩa.

Tham số tuỳ chọn (optional parameters)

Muốn định nghĩa một hàm có những tham số tuỳ chọn, các bạn cần phải cho những tham số đó một giá trị mặc định, như sau:

public void HamThamSoTuyChon(int I1, int I2=0, bool b1=true){}

Trong hàm mẫu trên, hai tham số I2 và B1 là những tham số tuỳ chọn, và không bắt buộc phải dùng khi gọi hàm HamThamSoTuyChon():

Code:
Code:
HamThamSoTuyChon(5);                 // Gọi với 1 tham số
 HamThamSoTuyChon(5,10);            // Gọi với 2 tham số
 HamThamSoTuyChon(5,10, false); // Gọi với tất cả tham số
Tham số tên (dùng với tham số tùy chọn)

C# 4.0 không hổ trợ cú pháp không dùng tham số tùy chọn có vị thế ở chính giữa bằng cách dùng những dấu phảy như sau:

Code:
Code:
HamThamSoTuyChon(5,, false); // Gọi với 2 tham số 1 và 3  (không được hổ trợ)
Cú pháp như trên, nếu được hổ trợ, sẽ đưa đến hậu quả nhầm lẫn và khó đọc nếu có hàng chục dấu phảy khi gọi một hàm. Các bạn sẽ khó nhận ra tham số nào đã được dùng, và tham số nào đã không được dùng. Với tham số tên, các bạn có thể chỉ định tham số tuỳ chọn khi gọi một hàm có nhiều tham số tùy chọn, như sau:

Code:
Code:
HamThamSoTuyChon(5,B1: false); // Gọi với 2 tham số 1 và 3
 HamThamSoTuyChon(5,B1: false, I2:10 ); // Gọi với 3 tham số, nhưng không  theo thứ tự
Với cú pháp được hổ trợ trên, khi gọi một hàm có nhiều tham số tùy chọn, các bạn có thể chỉ định tham số được dùng bằng cách dùng tên của tham số đó. Không cần phải lý giải thêm, chắc chắn các bạn đã thấy sự dễ dàng cho người viết, và sự dễ hiểu cho người đọc cho những cú pháp này.

Lý giải vận hành trên những hàm nạp chồng

Tham số tên và tham số tùy chọn, khi được dùng để gọi những hàm nạp chồng, dĩ nhiên, ảnh hưởng đến bộ vận hành .NET, nhưng thật ra rất giản dị khi bộ vận hành phải lý giải một hàm được gọi.

Dấu ký sẽ được dùng nếu tất cả những tham số đã dùng đều là những tham số tuỳ chọn, hoặc tất cả đều có tên, hoặc tất cả đều nằm theo vị thế đã được định nghĩa.

Luật “chính-xác-hơn” (betterness) sẽ được dùng cho những tham số được chỉ định (và bác bỏ những tham số tuỳ chọn).

Nếu 2 dấu ký bằng nhau, dấu ký nào có tất cả tham số sẽ được chọn. Thí dụ như, nếu các bạn đã có 4 hàm nạp chồng M(...) được định nghĩa như sau:

Code:
Code:
M(string s, int i=1)
 {}
 M(object o)
 {}
 M(int i, string s=“Chào”)
 {}
 M(int i)
 {}
Và mã nguồn mẫu dưới đây gọi hàm M()

M(5);

Trong đoạn mã mẫu trên, các bạn có thể nhận ra, M(string 2, int i=1) không được dùng, vì 5 là một hằng số không thể nào chuyển hóa (suy định) qua dạng string. M(int I, string s=“Chào”) có thể được dùng vì tham số thứ 2 là một tham số tùy chọn. M(int i) cũng có thể được dùng.

Nhưng sau cùng, M(int I) sẽ được dùng để gọi, vì không có tham số tùy chọn.

Chức năng cho COM interop

Đây có lẽ là một chức năng sẽ được rất nhiều người ưa thích. Hãy nghĩ đến việc các bạn có thể dùng những gì sẵn có trong Exel để hiển thị những dữ liệu trong CSDL của bạn như một bảng Exel thường dùng ở các văn phòng, và có thể hiển thị những đồ họa (graphs) đẹp mắt được người xử dụng ưa chuộng.
Nhập khẩu năng động (dynamic import)
Các bạn có thể dùng từ khóa using để nhập khẩu một linh kiện COM (được hổ trợ), và sau đó khởi tạo một đối tượng Exel để dùng trực tiếp (thay vì những cách dùng kiểu ép dạng cũ):

Code:
Code:
excel.Cells[1, 1].Value=Chào"
 
 // Thay vì
 
 ((Excel.Range)excel.Cells[1, 1]).Value2=Chào";
 
 Excel.Range range=excel.Cells[1, 1];
 
 // Thay vì
 
 Excel.Range range=(Excel.Range)excel.Cells[1, 1];
Vận hành không cần tới PIA (Program Interop Assemblies)

PIA là những linh kiện .NET có kích thước lớn được tạo dựng từ những linh kiện COM để có thể khởi tạo những dạng vững mạnh (được định nghĩa trong linh kiện COM) khi dùng với một lập trình C#. PIA cung cấp những hổ trợ tốt đẹp khi các bạn thiết kế một phần mềm. Đổi lại, trong lúc vận hành, những linh kiện có kích thước lớn này, khi được đưa vào bộ nhớ, có những tác dụng không tốt đến phần mềm của các bạn. Không những thế, lại là nguyên nhân có thể làm cho phần mềm của các bạn không thể vận hành vì lý do không có phiên bản COM thích hợp.

Chức năng no-PIA (không cần tói PIA) cho phép phần mềm của các bạn tiếp tục dùng PIA trong lúc thiết kế, nhưng không cần tới PIA khi vận hành. Thay vì đó, biên trình csc.exe đưa thẳng những phần đã được dùng từ PIA vào phần mềm của các bạn.

Loại bỏ tham số dạng tham chiếu (ref)

Nhiều linh kiện COM có những hàm nhận những tham số có dạng ref (tham chiếu). Không giống như tham số dạng tham chiếu của C#, dạng tham số tham chiếu của COM vẫn là những tham số có giá trị thực.
Do đó, C# 4.0 sẽ loại bỏ tất cả những dạng tham chiếu khi gọi một hàm của COM bằng cách tạo những biến từ tạm thời để lưu giữ giá trị của những tham số, và dùng những biến từ đó khi vận hành.

Hổ trợ dạng khả biến (variance)

Trong chương III - 10, các bạn đã được hướng dẫn về những dạng tập hợp chung mẫu (System.Collections.Generic). Các bạn có thể sẽ ngạc nhiên, khi biết, hàng mã nguồn thứ 2 dưới đây là một hàng mã nguồn có lỗi biên lập:

Code:
Code:
IList<string> mangChuoi= new List<string>();
 IList<object> mangDoiTuong = mangChuoi;   // Lỗi biên lập
 IEnumerable<object> mangDoiTuong2 = mangChuoi;   // Lỗi  biên lập
Hàng mã nguồn trên bị lỗi, vì biến từ mangChuoi đã không được định nghĩa đồng dạng với mảngDoiTuong. C# không hổ trợ sự chuyển dạng trên, vì có lý do rất chính đáng, vì hai biến từ mảng trên có thể được thao tác nhầm lẫn như sau:

Code:
Code:
mangDoiTuong[0]=5.15d;
 string strTest=mangChuoi[0];
Một đối tượng dạng Object có thể lưu giữ một giá trị dạng double, nhưng một chuỗi ký tự thì không thể. Mặc dù một đối tượng dạng Object có thể lưu giữ một giá trị dạng chuỗi ký tự, nhưng khi có những gán ghép giá trị giống như những đoạn mẫu trên, chương trình sẽ bị lỗi vận hành.

Tuy nhiên, nếu những mảng tập hợp trên được dùng với dạng khả biến (variance), mã nguồn sẽ không bị lỗi biên lập.

Dạng đồng biến (covariance)

Với C# 4.0, giao ước IEnumerable<T> sẽ được định nghĩa với cú pháp và ngữ nghĩa như sau:

Code:
Code:
public interface IEnumerable<out T> : IEnumerable
 {
         IEnumerator<T> GetEnumerator();
 }
 public interface IEnumerator<out T> : IEnumerator
 {
         bool MoveNext();
         T Current { get; }
 }
Chỉnh từ out trong những định nghĩa trên chỉ định tham số dạng T chỉ có thể xảy ra trong điểm ra của giao ước, nếu không, sẽ nhận được lỗi biên lập. Đổi lại cho sự giới hạn này, giao ước IEnumerable trở thành một giao ước có tham số dạng đồng biến ở điểm giữ chỗ <T>, có nghĩa là IEnumerable<X> có thể coi là IEnumerable<Y> nếu X có định nghĩa dùng để chuyển hóa dạng.

Chức năng này rất hữu dụng cho nhiều hàm của LINQ, sẽ được hướng dẫn trong chương kế tiếp.

Dạng nghịch biến (contra-variance)

Một giao ước tập hợp chung mẫu cũng có thể có tham số dạng thuộc dạng nghịch biến. Tham số dạng thuộc dạng nghịch biến được định nghĩa với chỉnh từ in, như sau:

Code:
Code:
public interface IComparer<in T>
 {
     public int Compare(T trái, T phải);
 }
Giao ước chung mẫu, hoặc uỷ nhiệm chung mẫu, còn có thể có những tham số dạng thuộc dạng đồng biến và nghịch biến, như sau:

Code:
Code:
public delegate TResult Func<in TArg, out TResult>(TArg arg);
Giới hạn

Tham số dạng khả biến chỉ có thể định nghĩa cho giao ước và uỷ nhiệm, và dạng khả biến chỉ có thể áp dụng cho những lớp đối tượng tham chiếu có hổ trợ chuyển hóa dạng. Chẳng hạn như chuyển hóa dạng giữa NhanVien và NhanCong, hoặc NhanCong qua Object. Từ int, hoặc double qua object chỉ là đóng gói, không phải là chuyển dạng, vì int và double không phải là những dạng tham chiếu, mà là những dạng có giá trị thực.