Giả sử bạn có một phương pháp có quyền này:
abstract class ProviderBase<T>
{
public IEnumerable<T> Results
{
get
{
List<T> list = new List<T>();
using(IDataReader rdr = GetReader())
while(rdr.Read())
list.Add(Build(rdr));
return list;
}
}
protected abstract IDataReader GetReader();
protected T Build(IDataReader rdr);
}
Với việc triển khai khác nhau được sử dụng. Một trong số chúng được sử dụng trong:
public bool CheckNames(NameProvider source)
{
IEnumerable<string> names = source.Results;
switch(names.Count())
{
case 0:
return true;//obviously none invalid.
case 1:
//having one name to check is a common case and for some reason
//allows us some optimal approach compared to checking many.
return FastCheck(names.Single());
default:
return NormalCheck(names)
}
}
Hiện tại, không có điều gì đặc biệt lạ. Chúng tôi không giả định một triển khai cụ thể của IEnumerable. Thật vậy, điều này sẽ làm việc cho mảng và rất nhiều bộ sưu tập thường được sử dụng (không thể nghĩ ra một trong System.Collections.Generic mà không phù hợp với đỉnh đầu của tôi). Chúng tôi chỉ sử dụng các phương pháp thông thường và phương pháp mở rộng thông thường. Nó thậm chí không bình thường để có một trường hợp tối ưu hóa cho các bộ sưu tập một mục. Ví dụ, chúng ta có thể thay đổi danh sách thành một mảng, hoặc có thể là một HashSet (để tự động loại bỏ các bản sao), hoặc một LinkedList hoặc một vài thứ khác và nó sẽ tiếp tục hoạt động.
Tuy nhiên, mặc dù chúng tôi không phụ thuộc vào việc triển khai cụ thể, chúng tôi tùy thuộc vào một tính năng cụ thể, cụ thể là có thể quay lại được (Count()
hoặc gọi ICollection.Count hoặc liệt kê thông qua số đếm, sau đó tên- .. kiểm tra sẽ diễn ra
có người dù thấy kết quả bất động sản và cho rằng "hmm, đó là một chút lãng phí" Họ thay thế nó bằng:
public IEnumerable<T> Results
{
get
{
using(IDataReader rdr = GetReader())
while(rdr.Read())
yield return Build(rdr);
}
}
này một lần nữa là hoàn toàn hợp lý, và thực sự sẽ dẫn đến một đáng kể hiệu suất tăng trong nhiều trường hợp.Nếu CheckNames
không được nhấn trong "kiểm tra" ngay lập tức được thực hiện bởi bộ mã hóa được đề cập (có thể nó không được nhấn nhiều đường dẫn mã), thì thực tế là CheckNames sẽ lỗi (và có thể trả về kết quả sai trong trường hợp có hơn 1 tên, điều này thậm chí còn tệ hơn nếu nó mở ra một nguy cơ bảo mật).
Bất kỳ kiểm tra đơn vị nào truy cập trên CheckNames có kết quả nhiều hơn 0 sẽ bắt được nó.
Thay đổi tương tự (nếu phức tạp hơn) là lý do cho tính năng tương thích ngược trong NPGSQL. Không đơn giản như chỉ thay thế một List.Add() với một lợi nhuận trả về, nhưng một sự thay đổi theo cách mà ExecuteReader làm việc đã cho một sự thay đổi có thể so sánh từ O (n) đến O (1) để có được kết quả đầu tiên. Tuy nhiên, trước đó NpgsqlConnection cho phép người dùng có được một người đọc khác từ một kết nối trong khi người đầu tiên vẫn còn mở, và sau khi nó không. Các tài liệu cho IDbConnection cho biết bạn không nên làm điều này, nhưng điều đó không có nghĩa là không có mã chạy nào. May mắn là một đoạn mã chạy như vậy là một thử nghiệm NUnit, và một tính năng tương thích ngược được thêm vào để cho phép mã như vậy tiếp tục hoạt động chỉ với một thay đổi về cấu hình.
Ngôn ngữ câu hỏi này có bất khả tri không? – kbrimington
@kbrimington C#. –
C# được ưa thích, bởi vì đó là khán giả của tôi; Nhưng tôi có thể viết lại nó trong C#, đưa ra một ví dụ đơn giản, tốt. – dgiard