4

次の例を検討してください。

namespace Test
{
    interface IContract : IContract<object> { }

    interface IContract<T>
    {
        void Definition(T data);
    }

    public class SomeClass : IContract, IContract<SomeContractClass>
    {
        public void Definition(SomeContractClass data)
        {
            // ...
        }
    }

    public class SomeContractClass { }
}

MDSNDefinition(SomeContractClass data)に記載されているように、次のように指定することでインターフェイスを満足させることができると思いました。

C# の統一された型システムでは、定義済みおよびユーザー定義のすべての型、参照型、および値型は、Object から直接的または間接的に継承します。

しかし代わりに、コンパイラはそれを明示的に定義するように私に求めます:

エラー 1 'Test.SomeClass' はインターフェイス メンバー 'Test.IContract.Definition(object)' を実装していません

4

2 に答える 2

8

インターフェイスを実装していますIContract

継承階層をフラット化すると、IContract基本的に次のようになります。

interface IContract
{
    void Definition(object data);
}

署名に一致するメソッドを指定しません。代わりに、指定void Definition (object data)するメソッドを使用しますSomeContractClass。したがって、指定されたエラーメッセージが表示されます。

IContractただし、根本的な問題は、クラスがandの両方を実装していることだと思いますIContract<T>(これはandと同じです)。あなたのデザインにはいくつかの作業が必要だと思います...IContract<object>IContract<T>

于 2013-02-26T14:12:06.437 に答える
3

あなたの状況を少し例えます。

あなたは小型車を修理する小さな会社を経営しています。

あなたは、外交艦隊のあらゆる種類の車両 (飛行機、ボート、大型トラック、小型車) の修理サービスを必要とする政府と契約を結びます。

あなたは嘘をついた / あなたが一般化した瞬間に小さな間違いを犯した

1)実装に成功したため

void Repair(SmallCar vehicle) 

2) そしてその理由

class SmallCar : Vehicle { }
class Airplane : Vehicle { }
class Boat : Vehicle { }
class BigTruck : Vehicle { }

どういうわけか、ポイント(1 + 2)の組み合わせ=>ポイント3は次のように述べています:

3) 政府はあなたの小さな会社を安全に「何でも修理する人たち」と呼ぶことができます。

Airplane protocolPlane = new Airplane();
yourCompany.Repair(protocolPlane);

もちろん、これは正しくありません: (1 + 2) は (3) を意味しません。

これが実行時例外ではなく、コンパイラ エラーとして終わったのは良いことです。このようにして、アーキテクチャの小さな問題についてより早く知ることができます。

編集

コードで、 SomeClassクラスに両方のインターフェイスを実装する必要があると判断し、その方法がわからない場合は、次のように明示的なインターフェイス実装を使用できます。

public class SomeClass : IContract, IContract<SomeContractClass>
{
    // Method of IContract<SomeContractClass>
    public void Definition(SomeContractClass data)
    {
        Console.WriteLine("Processing a SomeContractClass instance");            
        // ...etc
    }
    // Method of IContract hence of IContract<object>
    void IContract<object>.Definition(object data)
    {
        if (data is SomeContractClass)
          this.Definition(data as SomeContractClass);
        else
        {
          string descriptor = (null == data) 
            ? "A null reference" 
            : "An instance of " + data.GetType().Name";
          Console.WriteLine("Processing something other than a SomeContractClass instance: " + descriptor);
          // ...etc
        }
    }

}

このようにして、次の結果が正常に得られます。

class Program {
     public static void Main(string[] args) {
         SomeClass someInstance = new SomeClass();
         IContract<SomeContractClass> first= someInstance;
         IContract second = someInstance;

         someInstance.Definition(new SomeContractClass()); 
         // prints out "Processing a SomeContractClass instance"

         first.Definition(new SomeContractClass());
         // prints out "Processing a SomeContractClass instance"

         second.Definition(new SomeContractClass());
         // prints out "Processing a SomeContractClass instance"

         second.Definition( "something else" );
         // prints "Processing something other 
         // than a SomeContractClass instance: An instance of String"

         second.Definition( 123 );
         // prints "Processing something other
         // than a SomeContractClass instance: An instance of Int32"

         first.Definition( true );
         // doesn't compile saying that bool can't be converted to SomeContractClass

     }
}

編集の終わり

于 2013-02-26T14:19:03.603 に答える