以下のコードでは、親バージョンのmethodTwoにアクセスする方法を2つ試しましたが、結果は常に2でした。これら2つのクラスを変更せずにChildClassインスタンスから1結果を取得する方法はありますか?
class ParentClass
{
public int methodOne()
{
return methodTwo();
}
virtual public int methodTwo()
{
return 1;
}
}
class ChildClass : ParentClass
{
override public int methodTwo()
{
return 2;
}
}
class Program
{
static void Main(string[] args)
{
var a = new ChildClass();
Console.WriteLine("a.methodOne(): " + a.methodOne());
Console.WriteLine("a.methodTwo(): " + a.methodTwo());
Console.WriteLine("((ParentClass)a).methodTwo(): "
+ ((ParentClass)a).methodTwo());
Console.ReadLine();
}
}
更新ChrisWの投稿:
クラス外からはわかりません どんな簡単な方法でも。しかし、おそらく、私はしません 試したらどうなるか知っている リフレクション:Type.GetMethodを使う MethodInfoを見つけるためのメソッド のメソッドに関連付けられている ParentClassを呼び出してから呼び出す MethodInfo.Invoke
その答えは削除されました。私はそのハックが好奇心のためだけにうまくいくかどうか疑問に思います。
ILレベルでは、おそらくあなたはcall
ではなくcallvirt
そして、仕事を成し遂げる - しかし私達が自分達をC#に限定すれば;-p(編集するくそー!ランタイムはあなたを止めます:VerificationException
msgstr "操作によってランタイムが不安定になる可能性があります。"を削除virtual
そしてそれはうまくいきます。半分にしても巧妙すぎる...)
の中ChildClass
タイプ、あなたは使用することができますbase.methodTwo()
しかし、これは外部的には不可能です。また、あなたは1つ以上のレベルを下ることはできません - ありませんbase.base.Foo()
サポート。
ただし、メソッド隠蔽を使用して多態性を無効にすると、次のようになります。回答あなたは欲しいが、悪い理由で:
class ChildClass : ParentClass
{
new public int methodTwo() // bad, do not do
{
return 2;
}
}
これで、変数が変数として定義されているかどうかによって、同じオブジェクトから異なる答えを得ることができます。ChildClass
またはParentClass
。
new
このシナリオでは、型をより特殊化するためのものです。例えば、DbCommand
がありますpublic DbParameterCollection Parameters {get;}
- しかしSqlCommand : DbCommand
がありますpublic new SqlParameterCollection Parameters {get;}
。両方のAPIが同じを返す実例(別によって達成されるprotected abstract
財産、すなわちDbParameterCollection
- 値は常にあるあるSqlParameterCollection
) - しかしより具体的な型はより具体的な方法でそれを公開します - Marc Gravell♦
の中にChildClass.methodTwo()
電話できますbase.methodTwo()
。
クラス外、電話((ParentClass)a).methodTwo())
意志コールChildClass.methodTwo
。これが仮想メソッドが存在する全体的な理由です。
前述のように、PRODUCTIONコードで "base.base"を呼び出す必要がある場合は、クラス設計に問題があります。ただし、コンパイルできない外部ライブラリを使用しているときにデバッグまたは回避策を実行している場合は、この手法を使用することが正当です。 C#がこのオプションを直接提供していないのは不快です。それでも、あなたはILジェネレータとEmitでKenneth Xuソリューションを使うかもしれません。できます。
class A { public virtual string foo() { return "A"; } }
class B : A { public override string foo() { return "B"; } }
// now in class C
class C : B {}
// we can call virtual method "foo" from A using following code
MethodInfo fooA = typeof(A).GetMethod("foo", BindingFlags.Public | BindingFlags.Instance);
DynamicMethod baseBaseFoo = new DynamicMethod(
"foo_A",
typeof(string),
new[] { typeof(A) },
typeof(A));
ILGenerator il = baseBaseFoo.GetILGenerator();
il.Emit(OpCodes.Ldarg, 0);
il.EmitCall(OpCodes.Call, fooA, null);
il.Emit(OpCodes.Ret);
// call foo() from class A, it returns "A"
(string)baseBaseFoo.Invoke(null, new object[] { this });
参考資料と完全なサンプルについては、http://kennethxu.blogspot.cz/2009/05/cnet-calling-grandparent-virtual-method.html
Kenneth Xuありがとうございます。
Mark Gravellが言ったように、いいえ、外部ではありません。しかし、これが私が使ったもう一つのハックです。ChildClass
公開できるmethodTwo()
からParentClass
それ自身の使用または外部使用のために。あなたの場合:
class ChildClass : ParentClass {
override public int methodTwo() {
return 2;
}
public int ParentClass_methodTwo() {
return base.methodTwo();
}
}
// Now instead of
Console.WriteLine("ParentClass methodTwo: " + ((ParentClass)a).methodTwo());
// use
Console.WriteLine("ParentClass methodTwo: " + a.ParentClass_methodTwo());
私の場合、子クラスがPeerの概念を導入したので、それをオーバーライドする必要がありました。methodTwo()
ピアの基本バージョンを起動します。それをオーバーライドすることによって、それはそれを隠した...それともそれをしましたか?この技術は助けになりました。
class ChildClass : ParentClass {
ChildClass peer;
override public int methodTwo() {
return peer.ParentClass_methodTwo();
}
private int ParentClass_methodTwo() {
return base.methodTwo();
}
}
public class Parent
{
public string Method()
{
return "parent";
}
}
public class Child:Parent
{
public string Method()
{
return "child";
}
}
上記のコードは親メソッドを上書きしますが、親メソッドの値は変更されません。
Bothから値を返すことができます親クラスそして子どもクラス下記のコードを使用して -
Child child = new Child();
string result = (((Parent)child).Method()) + child.Method();
しかし、Visual Studioはコンパイル時に警告を表示します。
私の知る限りでは、メソッドがオーバーライドされると、親メソッドを呼び出すことはできません。
ParentClassのインスタンスを直接作らない限り不可能だと思います。 継承、ポリモーフィズムのまさしくその本質は…
私は助けを探してこれにつまずいたし、メソッドの先祖バージョンを呼び出すことへの私自身のアプローチで終わりました。これは、先祖クラスを編集できると仮定した場合の回避策です。
必要なパラメータを使用して、上位クラスの問題の機能を静的メソッドに配置します。そのクラスのメソッドはそれを呼び出すことができるので、機能を複製する必要はなく、子クラスは必要に応じて静的メソッドを介してその機能を呼び出すことができます。そうすることで、メソッド内でも実行でき、どの特定のクラスを呼び出したいのかを引用できます。また、それは単なる両親よりも遠い先祖にアクセスすることができます、それは使用 "base"の制限です。