15

リフレクションを介して調査する 2 つのインターフェイスと 2 つのクラスがあります。

  • IParent
  • IChild - IParent から派生
  • 子 - 親から派生

私にとって奇妙なことは、 IChild 型のリフレクションを調べたときに、 IParent メソッドが見つからないという事実です。

Child 型に適用された同じコードは期待どおりに機能します - リフレクションは Parent メソッドを示します。

interface IParent
{
     void ParentMethod();
}

interface IChild : IParent
{
     void ChildMethod();
}

class Parent 
{
     public void ParentMethod(){}
}

class Child : Parent
{
     public void ChildMethod(){}
}

void Main()
{
    //investigate derived interface
     Type t = typeof(IChild);
     var info = t.GetMethod("ChildMethod");//ok
     Console.WriteLine(info); 
     info = t.GetMethod("ParentMethod");//returns null!
     Console.WriteLine(info); 
     //investigate derived class
     t = typeof(Child);
     info = t.GetMethod("ChildMethod");//ok
     Console.WriteLine(info);
     info = t.GetMethod("ParentMethod");//ok
     Console.WriteLine(info);
}

そのような行動を説明してください。

派生インターフェイスの型から基本インターフェイスのメソッドを反映する回避策はありますか?

4

3 に答える 3

11

インターフェイスを扱っている場合は、使用します

t.GetInterfaces()

次に、上記で返された型のメソッドを確認できます。

名前によるインターフェイス メンバーの検索は信頼できません。C# インターフェイス メンバーは実装時に名前を変更できませんが、CLR では名前が変更される可能性があることに注意してください。(IDisposable.Dispose() は Close に名前が変更されることがあります)。il には、.implements名前を変更できるという命令があります。VB.Net にもこの機能があると思います。

于 2012-05-11T12:37:05.650 に答える
11

ただし、継承 (":") を使用するのと同じ方法でインターフェイスを使用します。インターフェイスは継承されません。それらは実装される予定です。このような場合には; 継承は同じ演算子 (":") を使用して定義されているため、実装と混同されます。

要約として; IA : IBおよびA:IA手段; IA を実装するすべてのクラスは、IB を実装する必要があります。この場合; A は IA および IB を実施するものとします。

A:BAクラスがBクラスを継承することを意味します。実装しません。

ここでの混乱は、同じ演算子 (":") を使用することに由来します。

このページのインターフェイスの継承を確認してください

于 2012-05-11T12:12:30.697 に答える
6

インターフェイスのベースインターフェイス(この場合IParentはのベースインターフェイスIChild)は、明示的なベースインターフェイスです。クラス、構造体、およびその他のインターフェースはインターフェースから継承しないため、継承はインターフェースの不幸な言葉です。これらは、基本インターフェースが定義するコントラクトを実装するだけです。

IChildあなたがから派生するときIParent(私が継承するとは言わなかったことに注意してください)、それはParentMethodメソッドを定義しません、それは単に私を実装するものは何でも言う、また実装しなければなりませんIParent

実際の型を反映するときに機能する理由は、インターフェイスを実装すると、型自体にそのメソッドシグネチャが実際に定義されるためですが、インターフェイスの場合はそうではありません。

これは、インターフェイスマッピングと呼ばれるコンパイラによって発生するプロセスが原因です。これは、実装クラスまたは構造体でインターフェイスメンバーを見つけるプロセスとして定義されますが、インターフェイス自体では発生しません。

インターフェイスを反映する場合、インターフェイスマッピングは行われないため、インターフェイス自体のみが反映されます。

Type t = typeof(IChild);

タイプ情報には、について明示的にタイプ情報のみが含まれますIChild

Type t = typeof(Child);

ここで、インターフェイスマッピングのプロセス発生します。Child、という名前のメソッドのタイプをParentMethod検討すると、一致するものが見つかるまで各ベースインターフェイスが調べられます。

言語設計のこの部分。詳細については、C#プログラミング言語(第4版)のセクション13.1.4またはECMA仕様のセクション20.1.2を参照してください。

インターフェイスの再実装を行うことである程度回避できますが、追加のコードが必要になります。

interface IParent
{
    void ParentMethod();
}

interface IChild
{
    new void ParentMethod(); // Reimplement IParent.ParentMethod()
    void ChildMethod();
}

これはうまくいくでしょう。

Type t = typeof(IChild);
MethodInfo mi = t.GetMethod("ParentMethod");

インターフェイスの再実装によりIChild、のメソッドシグネチャが含まれるようになりましたParentMethod

于 2012-05-11T12:19:08.223 に答える