Tôi có hai lớp hợp đồng kinh doanh:đại biểu Action, Generics, hiệp phương sai và contravariance
public BusinessContract
public Person : BusinessContract
Trong một lớp I có đoạn mã sau:
private Action<BusinessContract> _foo;
public void Foo<T>(Action<T> bar) where T : BusinessContract
{
_foo = bar;
}
Trên đây thậm chí sẽ không biên dịch, mà làm tôi bối rối một chút. Tôi đang ràng buộc T là BusinessContract, vậy tại sao trình biên dịch không biết thanh đó có thể được gán cho _foo?
Trong cố gắng để làm được việc này, chúng tôi đã cố gắng thay đổi nó như sau:
public void Foo<T>(Action<T> bar) where T : BusinessContract
{
_foo = (Action<BusinessContract>)bar;
}
Bây giờ trình biên dịch là hạnh phúc, vì vậy tôi viết đoạn mã sau ở nơi khác trong ứng dụng của tôi:
Foo<Person>(p => p.Name = "Joe");
Và các ứng dụng thổi lên với một InvalidCastException tại thời gian chạy.
Tôi không hiểu. Tôi có nên đưa loại cụ thể hơn của mình vào loại ít cụ thể hơn và chỉ định không?
CẬP NHẬT
Jon đã trả lời câu hỏi để nhận được cái gật đầu cho rằng, nhưng chỉ để đóng vòng lặp về vấn đề này, dưới đây là cách chúng tôi đã kết thúc giải quyết vấn đề.
private Action<BusinessContract> _foo;
public void Foo<T>(Action<T> bar) where T : BusinessContract
{
_foo = contract => bar((T)contract);
}
Tại sao chúng tôi làm việc này? Chúng tôi có một DAL Fake chúng tôi sử dụng để kiểm tra đơn vị. Với một trong các phương thức chúng ta cần cung cấp cho nhà phát triển thử nghiệm khả năng xác định phương thức nên làm khi nó được gọi trong quá trình thử nghiệm (đó là phương thức làm mới cập nhật một đối tượng được lưu trong bộ nhớ cache từ cơ sở dữ liệu). Mục đích của Foo là thiết lập những gì sẽ xảy ra khi refresh được gọi. IOW, ở những nơi khác trong lớp này chúng tôi có những điều sau đây.
public void Refresh(BusinessContract contract)
{
if(_foo != null)
{
_foo(contract);
}
}
Nhà phát triển thử nghiệm có thể, ví dụ, quyết định họ muốn đặt tên thành giá trị khác khi Làm mới được gọi.
Foo<Person>(p => p.Name = "New Name");
@MDeSchaepmeester: Không, tôi không ở trong mã đang hoạt động (nửa sau của bài đăng) Tôi chỉ định giá trị 'Action
Bạn nói đúng, sai lầm ngớ ngẩn, tôi đã không thực sự đọc mã đó và cho rằng bạn đang gọi Foo với _foo như một tham số (Tôi đến đây vì tôi đang làm * cái đó *) – MarioDS