Với này "IHandle" giao diện và hai lớp được xử lý:Odd C# hành vi khi thực hiện giao diện chung
interface IHandle<T>
{
void Handle(T m);
}
class M1
{
public int Id;
}
class MReset
{
}
Tôi muốn tạo ra một cơ sở chung mà sẽ chăm sóc của "thiết lập lại" cũng như quản lý các trường hợp M1 :
class HandlerBase<T> :
IHandle<MReset>,
IHandle<T> where T : M1
{
protected int Count;
void IHandle<T>.Handle(T m)
{
++Count;
Console.WriteLine("{0}: Count = {0}", m.Id, Count);
}
void IHandle<MReset>.Handle(MReset m)
{
Count = 0;
}
}
này không biên dịch từ trình biên dịch tin T có thể là "MReset" nên kết quả đầu ra:
lỗi CS0 695: 'HandlerBase' không thể thực hiện cả hai 'IHandle' và 'IHandle' bởi vì họ có thể thống nhất đối với một số tham số kiểu thay
Điều đó tự nó là hơi kỳ lạ kể từ khi tôi không thể nhìn thấy như thế nào T có thể có thể là loại MReset vì nó phải thuộc loại M1. Nhưng không sao, tôi có thể chấp nhận rằng trình biên dịch là thông minh hơn tôi :-)
Sửa: Trình biên dịch không phải là thông minh hơn tôi :-) Theo một bình luận trên Why does this result in CS0695? chúng ta có "tuyên bố Hạn chế không được xem xét khi xác định tất cả các loại có thể xây dựng ".
Bây giờ tôi trao đổi các tờ khai giao diện:
class HandlerBase<T> :
IHandle<T> where T : M1,
IHandle<MReset>
{
... same as before ..
}
Và đột nhiên tôi nhận được một thông báo lỗi khác nhau nói rằng tôi không thể thực hiện IHandle.Handle (MReset m) kể từ khi khai báo lớp không nêu rằng nó được thực hiện mà giao diện:
lỗi CS0540: '. HandlerBase.IHandle < ...> Xử lý (MReset): chứa loại không thực hiện giao diện 'IHandle'
Câu hỏi: tại sao thứ tự khai báo tạo sự khác biệt như vậy? Chuyện gì xảy ra trong ví dụ thứ hai?
Trong khi kết thúc nó quay ra rằng có một giải pháp:
class HandlerBase :
IHandle<MReset>
{
protected int Count;
void IHandle<MReset>.Handle(MReset m)
{
Count = 0;
}
}
class Handler<T> : HandlerBase,
IHandle<T> where T : M1
{
void IHandle<T>.Handle(T m)
{
++Count;
Console.WriteLine("{0}: Count = {0}", m.Id, Count);
}
}
Nhưng giải pháp duy nhất hoạt động nếu HandlerBase
cụ IHandle<MReset>
- không nếu giao diện chung IHandle<T>
được thực hiện trong HandlerBase
đầu tiên. Tại sao?
Sửa: Thực hiện IHandle<T>
trong HandlerBase
không làm việc (và nếu tôi đã cho thấy mã ai đó có thể đã nhìn thấy nó). Đây hoạt động:
class HandlerBase<T> :
IHandle<T> where T : M1
{
protected int Count;
void IHandle<T>.Handle(T m)
{
++Count;
Console.WriteLine("Type = {0}, Id = {1}, Count = {2}", GetType(), m.Id, Count);
}
}
class Handler<T> : HandlerBase<T>,
IHandle<MReset>
where T : M1
{
void IHandle<MReset>.Handle(MReset m)
{
Count = 0;
Console.WriteLine("RESET");
}
}
Đáng tiếc là khai báo lớp thứ hai của tôi là thế này:
class Handler<T> : HandlerBase<T> where T : M1,
IHandle<MReset>
{
void IHandle<MReset>.Handle(MReset m)
{
Count = 0;
Console.WriteLine("RESET");
}
}
Chú ý sự khác biệt tinh tế trong vị trí của where T : M1
:-) Ví dụ cuối cùng tuyên bố rằng T phải thực hiện IHandle<MReset>
(ngoài M1
). Duh!
[Liên quan/Nhân bản] (http://stackoverflow.com/questions/15316898/why-does-this-result-in-cs0695). Tôi không đóng như trùng lặp chỉ vì câu hỏi này "tại sao thứ tự khai báo lại tạo ra sự khác biệt như vậy?" không được trả lời ở đó. –
Đó thực sự là liên kết có liên quan. Tôi vừa chỉnh sửa câu trả lời được chấp nhận ở đó để làm cho thông tin quan trọng từ thông số C# hiển thị rõ hơn: ** "Khai báo hạn chế không được xem xét khi xác định tất cả các loại có thể có." ** –