30

2つのクラス(一方が他方から派生)の両方が同じインターフェイスを明示的に実装する状況があります。

interface I
{
  int M();
}

class A : I
{
  int I.M() { return 1; }
}

class B : A, I
{
  int I.M() { return 2; }
}

の派生クラスの実装からI.M()、基本クラスの実装を呼び出したいのですが、その方法がわかりません。私がこれまでに試したことはこれです(クラスBで):

int I.M() { return (base as I).M() + 2; }
// this gives a compile-time error
//error CS0175: Use of keyword 'base' is not valid in this context

int I.M() { return ((this as A) as I).M() + 2; }
// this results in an endless loop, since it calls B's implementation

別の(インターフェイスに明示されていない)ヘルパーメソッドを実装せずに、これを行う方法はありますか?


更新

派生クラスから呼び出すことができる「ヘルパー」メソッドで可能であることを私は知っています。例:

class A : I
{
    int I.M() { return M2(); }
    protected int M2 { return 1; }
}

また、インターフェイスを非明示的に実装するように変更することもできます。しかし、これらの回避策がなくても可能かどうか疑問に思っていました。

4

7 に答える 7

22

残念ながら、それは不可能です。
ヘルパーメソッドでもありません。ヘルパー メソッドには、2 回目の試行と同じ問題があります。基本クラスであってもthistypeであり、 inの実装を呼び出します。 BMB

interface I
{
  int M();
}
class A : I
{
  int I.M() { return 1; }
  protected int CallM() { return (this as I).M(); }
}
class B : A, I
{
  int I.M() { return CallM(); }
}

唯一の回避策は、の実装でA使用されるヘルパー メソッドです。 AM

interface I
{
  int M();
}
class A : I
{
  int I.M() { return CallM(); }
  protected int CallM() { return 1; }
}
class B : A, I
{
  int I.M() { return CallM(); }
}

Bただし、次のような場合にも、このようなメソッドを提供する必要がありclass C : B, Iます...

于 2011-05-12T09:57:54.747 に答える
10

リフレクションを使用することが可能です。
コードは次のとおりです。Delegate.CreateDelegate基本的な最適化としてキャッシュを追加しましたが、を使用してさらに最適化できますmethodInfo。また、パラメータカウントとタイプチェックは、を使用して追加できますmethodInfo.GetParameters()

interface I   
{   
    int M();   
} 

class A : I   
{   
    int I.M() { return 1; }   
} 

class B : A, I   
{   
    BaseClassExplicitInterfaceInvoker<B> invoker = new BaseClassExplicitInterfaceInvoker<B>();
    int I.M() { return invoker.Invoke<int>(this, "M") + 2; }   
}

public class BaseClassExplicitInterfaceInvoker<T>
{
    private Dictionary<string, MethodInfo> cache = new Dictionary<string, MethodInfo>();
    private Type baseType = typeof(T).BaseType;

    private MethodInfo FindMethod(string methodName)
    {
        MethodInfo method = null;
        if (!cache.TryGetValue(methodName, out method))
        {
            var methods = baseType.GetMethods(BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly);

            foreach (var methodInfo in methods)
            {
                if (methodInfo.IsFinal && methodInfo.IsPrivate) //explicit interface implementation
                {
                    if (methodInfo.Name == methodName || methodInfo.Name.EndsWith("." + methodName))
                    {
                        method = methodInfo;
                        break;
                    }
                }
            }   

            cache.Add(methodName, method);
        }

        return method;
    }

    public RT Invoke<RT>(T obj, string methodName)
    {            
        MethodInfo method = FindMethod(methodName);
        return (RT)method.Invoke(obj, null);
    }

}   //public static class BaseClassExplicitInterfaceInvoker<T>

これが私のインスピレーションの源です。

于 2012-08-20T19:38:11.427 に答える
0

明示的に必要ですか?... インターフェイスの代わりに抽象クラスまたはクラスを使用できますか?

interface ISample {}
class A : ISample {}
class B : A {}
...
base.fun();
...

http://msdn.microsoft.com/en-us/library/hfw7t1ce(v=vs.71).aspx

インターフェイスの実装に由来する場合、ベースメソッドを呼び出すことができないとは思いません。

于 2011-05-12T09:54:33.150 に答える
0
using System;

namespace SampleTest
{
    interface IInterface1
    {
        void Run();
    }

    interface IInterface2
    {
        void Run();
    }

    public class BaseClass : IInterface1, IInterface2
    {
        public void Interface1Run()
        {
            (this as IInterface1).Run();
        }

        public void Interface2Run()
        {
            (this as IInterface2).Run();
        }

        void IInterface2.Run()
        {
            Console.WriteLine("I am from interface 2");
        }

        void IInterface1.Run()
        {
            Console.WriteLine("I am from interface 1");
        }
    }

    public class ChildClass : BaseClass
    {
        public void ChildClassMethod()
        {
            Interface1Run();
            Interface2Run();      
        }
    }
    public class Program : ChildClass
    {
        static void Main(string[] args)
        {
            ChildClass childclass = new ChildClass();
            childclass.ChildClassMethod();
        }
    }
}
于 2016-09-04T03:39:46.387 に答える