覆盖显式接口实现?
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了覆盖显式接口实现?相关的知识,希望对你有一定的参考价值。
覆盖子类中接口的显式实现的正确方法是什么?
public interface ITest
{
string Speak();
}
public class ParentTest : ITest
{
string ITest.Speak()
{
return "Meow";
}
}
public class ChildTest : ParentTest
{
// causes compile time errors
override string ITest.Speak()
{
// Note: I'd also like to be able to call the base implementation
return "Mooo" + base.Speak();
}
}
以上是对语法的最佳猜测,但显然这是错误的。它会导致以下编译时错误:
error CS0621:
`ChildTest.ITest.Speak()':虚拟或抽象成员不能是私有的
error CS0540:
kazxsopoiITest“
error CS0106:
修饰符“覆盖”对此项无效
我实际上可以在不使用显式接口的情况下使用它,所以它实际上并没有阻止我,但我真的想知道,为了我自己的好奇心,如果想用显式接口做这个,那么正确的语法是什么?
显式接口实现不能是虚拟成员。请参阅ChildTest.ITest.Speak()': containing type does not implement
interface
的第13.4.1节(它已过时,但在C#6.0中这个逻辑似乎没有改变)。特别:
显式接口成员实现包含访问修饰符是编译时错误,包含修饰符abstract,virtual,override或static是编译时错误。
这意味着,您永远无法直接覆盖此成员。
您可以做的解决方法是从显式实现中调用另一个虚方法:
C# language specification
我还有一种情况,我认为我想覆盖一个显式的接口实现并调用基类,并发现这个问题的答案说“无法完成”。
首先要注意的是,为了覆盖显式接口实现而不调用基类非常简单。派生类只需要实现接口本身。
class Base : IBla
{
void IBla.DoSomething()
{
this.DoSomethingForIBla();
}
protected virtual void DoSomethingForIBla()
{
...
}
}
class Derived : Base
{
protected override void DoSomethingForIBla()
{
...
}
}
但是,现在没有“合法”的方法来调用public class ChildTest : ParentTest, ITest
{
string ITest.Speak()
{
return "Mooo";
}
// Note: any other interface functions will call ParentTest's implementation
}
在ParentTest
类型的对象上实现ITest.Speak
,因为任何使用该接口的尝试都会导致调用ChildTest
的实现。
因此,只有对基本实现的调用才会导致复杂化。为了满足我的好奇心,我证明了它可以做到,但实际上它不应该......
保持基类不变,以下实际上允许使用反射调用基类。
ChildTest
注意如果示例代码包含在命名空间中,则需要完全限定的接口名称。例如public class ChildTest : ParentTest, ITest
{
string ITest.Speak()
{
return "Mooo" + typeof(ParentTest).GetMethod("ITest.Speak", BindingFlags.Instance | BindingFlags.NonPublic).Invoke(this, new object[0]) as string;
}
}
如果将重复调用该函数和/或对于许多对象,则可以通过缓存方法信息和/或为基本调用创建委托来提高性能,例如:
"MyNamespace.ITest.Speak"
与其他答案相比,它的唯一优势是,如果您无法修改基类,它就有效。否则,这是一个可怕的解决方案,应该在基类中创建一个机制(如在其他答案中),以便为派生类提供调用基本实现的合法方法。
您可以使用public class ChildTest : ParentTest, ITest
{
static ChildTest()
{
baseSpeakMethodInfo = typeof(ParentTest).GetMethod("ITest.Speak", BindingFlags.Instance | BindingFlags.NonPublic);
}
static private MethodInfo baseSpeakMethodInfo;
public ChildTest()
{
baseSpeak = baseSpeakMethodInfo.CreateDelegate(typeof(Func<string>), this) as Func<string>;
}
private Func<string> baseSpeak;
string ITest.Speak()
{
return "Mooo" + baseSpeak();
}
}
方法,并将实现保持为非公共,因此您仍然具有显式接口实现,这只是实现的包装:
protected virtual
您无法覆盖显式接口实现。它们不能是虚拟的,因此无法直接覆盖它们。但是,您可以通过调用受保护的虚拟成员来间接地使它们成为虚拟成员:
public class ParentTest : ITest
{
protected virtual string Speak_Impl()
{
return "Meow";
}
string ITest.Speak()
{
return Speak_Impl();
}
}
public class ChildTest : ParentTest
{
protected override string Speak_Impl()
{
return "Mooo";
}
}
父母的public interface ITest
{
string Speak();
}
public class ParentTest : ITest
{
string ITest.Speak()
{
return Speak();
}
protected virtual string Speak()
{
return "Meow";
}
}
public class ChildTest : ParentTest
{
protected override string Speak()
{
return "Mooo";
}
}
和孩子的public virtual string Speak()
应该可以正常工作。您不能为此用例使用显式接口。您可以通过声明受保护的成员并在显式接口实现中调用它来解决它,如果您需要使用它们。
以上是关于覆盖显式接口实现?的主要内容,如果未能解决你的问题,请参考以下文章