Hãy nói rằng chúng tôi muốn tuyên bố
interface IPersonRepository : IRepository<Person> { }
Điều đó sẽ đòi hỏi rằng có một giao diện chung với một loại tham số IRepository<EntityType>
.
interface IRepository<EntityType> where EntityType : Entity<KeyType>
{
EntityType Get(KeyType id);
}
Ở cuối dòng đầu tiên, bạn tham chiếu đến một điều gọi là KeyType
, chưa được khai báo hay xác định. Không có loại được gọi là "KeyType".
này sẽ làm việc mặc dù:
interface IRepository<EntityType> where EntityType : Entity<int>
{
EntityType Get(int id);
}
Hoặc này:
interface IRepository<EntityType> where EntityType : Entity<string>
{
EntityType Get(string id);
}
Nhưng bạn không thể có cả hai định nghĩa mâu thuẫn cùng lúc tất nhiên. Rõ ràng, bạn không hài lòng với điều đó, bởi vì bạn muốn có thể xác định giao diện IRpository của bạn theo cách mà nó hoạt động với các loại khóa khác.
Vâng, bạn có thể, nếu bạn thực hiện nó chung chung trong các loại hình chính:
interface IRepository<KeyType, EntityType> where EntityType : Entity<KeyType>
{
EntityType Get(KeyType id);
}
Có một cách tiếp cận khác:
interface IRepository<KeyType>
{
EntityType<KeyType> Get(KeyType id);
}
Bây giờ bạn có thể định nghĩa
class PersonRepository : IRepository<int>
{
public EntityType<int> Get(int id) { ... }
}
Rõ ràng, bạn sẽ không hài lòng với điều đó, bởi vì bạn muốn nói rằng phương thức Get phải trả về một Person
, không chỉ bất kỳ Entity<int>
nào.
Giao diện chung với hai tham số loại trong giải pháp duy nhất. Và quả thực, có một mối quan hệ cần thiết giữa chúng, như thể hiện trong ràng buộc. Nhưng không có dự phòng ở đây: chỉ định int
cho thông số loại không mang đủ thông tin.
Nếu chúng ta nói
class PersonRepository : IRepository<int, Person>
{
public Person Get(int id) { ... }
}
Có thực sự là dư thừa: Ghi rõ các tham số kiểu int
là không cần thiết khi tham số kiểu Person
đã được xác định.
Nó sẽ có thể đến với op với một cú pháp mà làm cho nó có thể suy ra KeyType. Ví dụ, Patrick Hoffman gợi ý:
class PersonRepository : IRepository<EntityType: Person>.
{
public Person Get(int id) { ... }
}
Trong khi về mặt lý thuyết có thể, tôi sợ rằng điều này sẽ thêm rất nhiều phức tạp để đặc tả ngôn ngữ và trình biên dịch, vì rất ít lợi ích. Trong thực tế, có bất kỳ lợi ích nào cả? Bạn chắc chắn sẽ không lưu các tổ hợp phím! So sánh hai loại này:
// current syntax
class PersonRepository : IRepository<int, Person>
{
public Person Get(int id) { ... }
}
// proposed syntax
class PersonRepository : IRepository<EntityType: Person>
{
public Person Get(int id) { ... }
}
Ngôn ngữ là gì và nó không quá tệ với tôi.
Làm cách nào để có thể biết 'KeyType'? Bạn có thể hiển thị cú pháp đầy đủ về những gì bạn mong đợi không? Định nghĩa giao diện cuối cùng của bạn có vẻ không hoàn chỉnh. –
Tôi không nghĩ là có thể. Trình biên dịch không đủ "thông minh". Tôi sẽ không làm cho nó một câu trả lời mặc dù bởi vì "Tôi không thể nghĩ ra bất kỳ cách nào bạn có thể làm điều đó" là không đủ bằng chứng bạn không thể. – Falanwe
Tôi giả sử dòng cuối cùng của mã phải là 'giao diện IPersonRepository: IRepository {...}' –
Rawling