2009-04-27 83 views
21

我有這樣的C#代碼:抽象的顯式接口實現

abstract class MyList : IEnumerable<T> 
{ 
    public abstract IEnumerator<T> GetEnumerator(); 

    //abstract IEnumerator IEnumerable.GetEnumerator(); 
} 

原樣,我得到:

'類型' 未實現接口成員「System.Collections.IEnumerable.GetEnumerator ()」。

刪除評論,我得到:

修飾語「抽象」是無效的這個項目

如何使一個明確的執行摘要

+0

這是C#編譯器恕我直言的一個缺點。有很多用例需要添加一個虛擬實現「僅僅是因爲」。另外,如果您選擇使成員不是抽象的,編譯器將允許沒有實現的子類,從而暴露調用僞實現的風險。 – 2013-08-22 11:58:59

回答

29

有趣 - 我不確定你可以。但是,如果這是您的真實代碼,那麼您是否希望以任何方式實現非通用GetEnumerator()其他而不是通過調用通用的代碼?

我應該這樣做:

abstract class MyList<T> : IEnumerable<T> 
{ 
    public abstract IEnumerator<T> GetEnumerator(); 

    IEnumerator IEnumerable.GetEnumerator() 
    { 
     return GetEnumerator(); 
    } 
} 

這可以節省您不必實現它在每一個派生類的枯燥 - 這無疑都使用相同的實現。

+2

我沒有理由認爲它會得到任何其他方式實施...但你永遠不知道。 +1 – BCS 2009-04-27 20:25:31

+2

重新評論 - 我可能誤解了它...編輯修復它,並找到與您的代碼完全相同的代碼 - 已刪除;-p – 2009-04-27 20:26:49

14

雖然顯式接口成員可能不被抽象(或虛擬的),可以在一個抽象的(或虛擬的)成員1方面實現的:

public abstract class Foo: IEnumerable { 
    IEnumerator IEnumerable.GetEnumerator() { 
     return getEnumerator();  
    } 

    protected abstract IEnumerator getEnumerator(); 
} 

public class Foo<T>: Foo, IEnumerable<T> { 
    private IEnumerable<T> ie; 
    public Foo(IEnumerable<T> ie) { 
     this.ie = ie; 
    } 

    public IEnumerator<T> GetEnumerator() { 
     return ie.GetEnumerator(); 
    } 

    protected override IEnumerator getEnumerator() { 
     return GetEnumerator(); 
    } 

    //explicit IEnumerable.GetEnumerator() is "inherited" 
} 

我發現在這方面的需要強類型ASP.NET MVC 3部分視圖,它不支持泛型類型定義模型(據我所知)。

0

我有一個稍微複雜的情況,我希望基類顯式實現非泛型接口,並且派生類實現泛型接口。

接口:

public interface IIdentifiable<TKey> : IIdentifiable 
{ 
    TKey Id { get; } 
} 

public interface IIdentifiable 
{ 
    object Id { get; } 
} 

我解決它通過聲明在基類中的抽象getter方法,讓明確實施叫它:

public abstract class ModelBase : IIdentifiable 
{ 
    object IIdentifiable.Id 
    { 
     get { return GetId(); } 
    } 

    protected abstract object GetId(); 
} 

public class Product : ModelBase, IIdentifiable<int> 
{ 
    public int ProductID { get; set; } 

    public int Id 
    { 
     get { return ProductID; } 
    } 

    protected override object GetId() 
    { 
     return Id; 
    } 
} 

注意,基類不具備鍵入版本Id它可以調用。

1

實際上,你可以做到這一點,通過強制的一類,它從一個抽象類派生,以實現一個接口,並且還允許它選擇如何實現該接口 - 或明或暗地:

namespace Test 
{ 
    public interface IBase<T> 
    { 
     void Foo(); 
    } 

    public abstract class BaseClass<T> 
     where T : IBase<T> // Forcing T to derive from IBase<T> 
    { } 

    public class Sample : BaseClass<Sample>, IBase<Sample> 
    { 
     void IBase<Sample>.Foo() { } 
    } 

    class Program 
    { 
     static void Main(string[] args) 
     { 
      Sample sample = new Sample(); 

      // Error CS1061 'Sample' does not contain a definition for 'Foo' 
      // and no extension method 'Foo' accepting a first argument of type 'Sample' 
      // could be found(are you missing a using directive or an assembly reference ?) 
      sample.Foo(); 

      (sample as IBase<Sample>).Foo(); // No Error 
     } 
    } 
}