Recently one of my colleagues asked the team how to override a base class method that was declared as explicit. This is actually an interesting question. An there is a lengthy discussion on why you can’t override a explicit base class method from your derived class.
http://bytes.com/topic/c-sharp/answers/271737-how-can-i-call-base-interface-method
The first question is, can you call a base explicit method?
1: using System;
2: namespace CSharpCodeTest
3: {
4: interface IFoo { void Foo(); }
5:
6: class A : IFoo
7: {
8: void IFoo.Foo()
9: {
10: Console.WriteLine("A.Foo runs");
11: }
12: }
13:
14: class B : A
15: {
16: public void MyFoo()
17: {
18: IFoo mySelf = this;
19: mySelf.Foo();
20: }
21: }
22:
23: class Program
24: {
25: static void Main(string[] args)
26: {
27: B b = new B();
28: b.MyFoo();
29: }
30: }
31:
32: }
The compiler works, and I got my result. So, we are able to call our explicit base method through the use of “this”.
So, the next step is try to override B.Foo()
1: using System;
2: using NUnit.Framework;
3:
4: namespace CSharpCodeTest
5: {
6: interface IFoo
7: {
8: void Foo();
9: }
10:
11: class A : IFoo
12: {
13: void IFoo.Foo()
14: {
15: Console.WriteLine("A.Foo runs");
16: }
17: }
18:
19: class B : A, IFoo
20: {
21: void IFoo.Foo()
22: {
23: Console.WriteLine("B.Foo runs");
24: }
25: }
26:
27: [TestFixture]
28: public class TestCases
29: {
30: [Test]
31: public void Test1()
32: {
33: B b = new B();
34:
35: //Call by casting IFoo
36: ((IFoo)b).Foo();
37:
38: //Call by casting A, then by IFoo
39: A a = b;
40: ((IFoo) a).Foo();
41: }
42: }
43:
44: }
This is the result
So, in this sense, polymorphism still works. That means I am allow to create my own Foo() in the derived class.
How about I try to call base.Foo(), in my override Foo() that is non-explicit?
1: class A : IFoo
2: {
3: void IFoo.Foo()
4: {
5: Console.WriteLine("A.Foo runs");
6: }
7: }
8:
9: class B : A
10: {
11: public void Foo()
12: {
13: IFoo mySelf = this;
14: mySelf.Foo();
15: }
16: }
17:
18: class Program
19: {
20: static void Main(string[] args)
21: {
22: B b = new B();
23: b.Foo();
24: }
25: }
Hey, it works too, once I cast the “this” into IFoo, I can still access the base.Foo().
At last, what if I try to override this explicit Foo()? I changed the code from “public void” to “void IFoo.Foo”
1: class B : A, IFoo
2: {
3: void IFoo.Foo()
4: {
5: IFoo mySelf = this;
6: mySelf.Foo();
7: }
8: }
Ouch, infinite loop. In fact, I have to explicit declare class B with IFoo in order for the compiler to work. Even if I try casting to A:
1: class B : A, IFoo
2: {
3: void IFoo.Foo()
4: {
5: //IFoo mySelf = this;
6: IFoo myself = (IFoo)(A)this;
7: myself.Foo();
8: }
9: }
I believe this is a missing feature in C#. If C# allows you to call base.Foo() through the IFoo(this).Foo(), you should allow to call it when overriding the method.
To hack around the problem, in the forum, one suggested to use reflection:
InterfaceMapping map = GetType().BaseType.GetInterfaceMap(typeof(IFoo)); map.TargetMethods[0].Invoke(this, new object[]{});
I would suggest try to create a wrapper class if possible, instead of create a derive class.
In fact, there is a FXCop rule on this issue: http://msdn.microsoft.com/en-us/library/ms182153%28VS.80%29.aspx
2 comments:
I would suggest you should override correctly, use the override keyword.
interface ITest
{
void Do();
}
class Test : ITest
{
protected virtual void Do()
{
}
void ITest.Do()
{
Do();
}
}
class Test2 : Test, ITest
{
protected override void Do()
{
base.Do();
}
void ITest.Do()
{
Do();
}
}
Thank you for the useful post.
Post a Comment