2009-04-27 24 views
21

私はこのC#のコードを持って抽象明示的なインターフェイスの実装は

'種類' インターフェイスメンバを実装していません「System.Collections.IEnumerable.GetEnumerator () '。

コメントを削除し、私が手:

修飾子「抽象」はこの項目のために有効ではありません

どのように私は明示的な実装の抽象

+0

これをC#コンパイラIMHOの欠点です。ダミーの実装を追加する必要があるユースケースがたくさんあります。また、抽象メンバを抽象化しないことを選択した場合、コンパイラは実装なしでサブクラスを許可し、ダミー実装を呼び出すリスクを露呈させます。 –

答えて

29

興味深いを作るのですか - 私はあなたができるとは確信していません。しかし、これがあなたの実際のコードであれば、非汎用のGetEnumerator()を任意の方法で実装したいと思いますかより一般的なものを呼び出すよりもですか?

私はこれを行うだろう:

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

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

すべての派生クラスでそれを実装することの退屈からあなたを節約すること - 間違いなくすべて同じ実装を使用します。

+2

私はそれが他の方法を実装すると思う理由はありません...しかし、あなたは決して知りません。 +1 – BCS

+2

あなたのご意見をお聞かせください - 私はそれを誤読している可能性があります...それを修正するために編集し、あなたと同じコードを見つけました - 削除されました;-p –

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

私は自分自身もこの解決策を使用しなければならないことがわかりました。ありがとう! (Jon Skeetsの回答は、提供された例では意味がありますが、このような単純な関係がない場合、これは私が知っている限り最も良い解決策に見えます)。 – AnorZaken

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 
     } 
    } 
} 
関連する問題