基本 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 错误消息:

....不实现接口 成员"...."。'...'无法实现 '....'因为它没有 匹配的返回类型为"...."。

有没有另一种方法来实现这样的结构,或者这根本不可能?

谢谢。

基本 C# 接口问题

最简单的

方法是显式实现接口,并从显式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;