基本 C# 接口问题
本文关键字:问题 接口 基本 | 更新日期: 2023-09-27 17:55:41
我想实现以下结构:
public interface IMyDbSet
{
IEnumerable<User> Users { get; }
}
public class ConcreteDbSet : IMyDbSet
{
DbSet<User> Users { get; set; }
}
虽然DbSet<T>
继承自IEnumerable<T>
但这是不可能的。
Visual Studio 错误消息:
....不实现接口 成员"...."。'...'无法实现 '....'因为它没有 匹配的返回类型为"...."。
有没有另一种方法来实现这样的结构,或者这根本不可能?
谢谢。
最简单的
方法是显式实现接口,并从显式Users
属性返回隐式Users
属性的值。
public interface IMyDbSet
{
IEnumerable<User> Users { get; }
}
public class ConcreteDbSet : IMyDbSet
{
IEnumerable<User> IMyDbSet.Users
{
get { return Users; }
}
DbSet<User> Users
{
get; set;
}
}
这
是不可能的,因为无论谁调用IMyDbSet.Users
都希望收到可能但不必DbSet<User>
IEnumerable<User>
。 DBSet<T>
是IEnumerable<T>
,但IEnumerable<T>
不是DbSet<T>
。
话虽如此,没有什么可以阻止您将实例DbSet<USer>
返回为IEnumerable<User>
您要使用的功能称为"返回类型协方差",这在 C# 编程语言中是不合法的(不幸的是)。
在其他一些语言中,如C++,Java或Eiffel(以及其他一些语言),您可以在覆盖虚拟方法或实现接口时使用更具体的类型。
如果你正在处理接口,你可以使用已知的习语(如Florian提到的):你可以显式实现你的接口,并添加另一个带有另一个签名的方法。
public interface IMyDbSet
{
IEnumerable<User> Users { get; }
}
public class ConcreteDbSet : IMyDbSet
{
IEnumerable<User> IMyDbSet.Users {get {return Users;}}
public DbSet<User> Users { get; set; }
}
另一个选项 - 用户泛型IMyDbSet<T>
类似于System.Object
和泛型类型安全接口[IEquatable<T>][2]
bool Equals(object rhs)
:
public interface IMyDbSet<T> where T : IEnumerable<User>
{
// Because T is IEnumerable<User> or one of it descendant
// this property is similar to IEnumerable<User> Users {get;}
T Users {get;}
}
// Now we're implementing not IMyDbSet interface itself
// but we're IMyDbSet<IList<User>> instead.
// Note you could use your own descendant for IEnumerable<User> here
public class ConcreteDbSet : IMyDbSet<IList<User>>
{
public IList<User> Users {get; set;}
}
//...
// and now you could use ConcreteDbSet following way:
var set = new ConcreteDbSet();
IList<User> users = set.Users;