2011-05-10 55 views
2

我要實現以下結構:基本的C#接口問題

public interface IMyDbSet 
{ 
    IEnumerable<User> Users { get; } 
} 

public class ConcreteDbSet : IMyDbSet 
{ 
    DbSet<User> Users { get; set; } 
} 

雖然DbSet<T>IEnumerable<T>繼承這不是possbile。

Visual Studio中的錯誤信息:

....不實現接口 成員 '......'。 '...'不能執行 '....',因爲它沒有匹配返回類型'....'的 。

是否有另一種方法來實現這樣的結構,或者這是不可能的?

謝謝。

+2

你爲什麼要剪掉了錯誤信息的重要組成部分?這是告訴你到底是什麼問題。 – 2011-05-10 09:55:39

+0

Cody Gray,錯誤應該是'ConcreteDbSet不實現接口成員IMyDbSet.Users。 ConcreteDbSet.Users不能實現IMyDbSet.Users,因爲它沒有匹配的返回類型IEnumerable '。 – 2011-05-10 09:59:42

+0

@Cody:對不起,我沒有先檢查你的聲望。祝你有個好的一天。 – 2011-05-10 10:07:38

回答

8

最簡單的方法是明確實現接口並從明確的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; 
    } 
} 
2

這是不可能的,因爲誰調用IMyDbSet.Users預計將收到IEnumerable<User>這可能,但並不一定是DbSet<User>DBSet<T>IEnumerable<T>,但是IEnumerable<T>不是DbSet<T>

話雖這麼說,沒有什麼可以阻止您返回DbSet<USer>實例作爲IEnumerable<User>

1

要使用一個名爲「return type covariance」的功能,這是不合法的(不幸)在C#編程語言。

在C++,Java或Eiffel(以及其他)的某些其他語言中,您可以在覆蓋虛擬方法或實現接口時使用更具體的類型。

如果你正在處理接口,你可以使用已知的習慣用法(如弗洛裏安提到的):你可以明確地實現你的接口,並添加另一個簽名的方法。

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>類似bool Equals(object rhs)System.Object和泛型類型安全接口[IEquatable<T>][2]

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;