tôi đã xác định các lớp và các phương pháp sau đây:Tại sao C# không ràng buộc đúng với phương pháp ghi đè chung?
using System;
using System.Linq.Expressions;
using System.Windows.Forms;
public class ReturnValue<T, S> {}
public class Something<T>
{
// Sorry about the odd formatting. Trying to get it to fit nicely...
public ReturnValue<T, C>
Do<C, S>(C control, Expression<Func<C, S>> controlProperty)
where C : Control
{
return new ReturnValue<T, C>();
}
public ReturnValue<T, ToolStripItem>
Do<S>(ToolStripItem control, Expression<Func<ToolStripItem, S>> controlProperty)
{
return new ReturnValue<T, ToolStripItem>();
}
}
này biên dịch tốt. Woo hoo! Nửa đường. Sau đó, tôi cố gắng sử dụng nó sau này với mã như thế này:
var toolStripItem = new ToolStripStatusLabel();
var something = new Something<string>();
something.Do(toolStripItem, t => t.Text); // Does not compile
này, tuy nhiên, chết với thông báo lỗi sau
Loại
ToolStripStatusLabel
không thể được sử dụng như loại tham sốC
trong các loại generic hoặc phương phápSomething<T>.Do<C,S>(C, Expression<Func<C,S>>)
. Không có chuyển đổi tham chiếu ngầm từToolStripStatusLabel
đếnControl
.
Dường như với tôi trình biên dịch C# đã thất bại trong trường hợp này mặc dù hai phương pháp không tạo ra một bộ khai báo phương thức không rõ ràng. Control
và ToolStripStatusLabel
tồn tại như anh chị em trong cây thừa kế của Component
. Tôi nghĩ rằng trình biên dịch sẽ có đủ thông tin để ràng buộc chính xác lời gọi phương thức trong mã máy khách.
Tuy nhiên, nếu tôi làm điều tương tự với các lớp anh chị em của riêng tôi, thì mọi thứ sẽ biên soạn tốt.
public class Parent {}
public class Child1 : Parent {}
public class Child2 : Parent {}
public class Something2<T>
{
public ReturnValue<T, C>
Do<C, S>(C control, Expression<Func<C, S>> controlProperty)
where C : Child1
{
return new ReturnValue<T, C>();
}
public ReturnValue<T, Child2>
Do<S>(Child2 control, Expression<Func<Child2, S>> controlProperty)
{
return new ReturnValue<T, Child2>();
}
}
var child2 = new Child2();
var something2 = new Something2<string>();
something2.Do(child2, c => c.GetType()); // Compiles just fine
Mọi người có thể làm sáng tỏ những gì tôi đã làm sai, nếu có gì không?
Jon, đó là một lời giải thích tuyệt vời. Cảm ơn bạn. – realistschuckle
Vậy tại sao ví dụ thứ hai lại biên dịch? –
BlueRaja (bên cạnh một tên tuyệt vời) viết chính xác, mà tôi đã nghĩ đến sau khi xem xét giải thích thêm. Có hiểu biết gì không, Jon? – realistschuckle