在下面的示例中,类“SomeClass”没有实现“ISomeInterface”。为什么我不能通过传递一个更派生的接口来实现这一点,该接口确实实现了基本要求。无论传递什么实例,它仍然会实现基础,我是否遗漏了什么?
namespace Test
{
public interface IBaseInterface
{
void DoBaseStuff();
}
public interface IChildInterface : IBaseInterface
{
void DoChildStuff();
}
public interface ISomeInterface
{
void DoSomething(IBaseInterface baseInterface);
}
public class SomeClass : ISomeInterface
{
public void DoSomething(IChildInterface baseInterface)
{
}
}
}
存在此限制是因为ISomeInterface
expects任何IBaseInterface
将满足合同。也就是说,如果您有以下情况:
public interface IBase {}
public interface IChildA : IBase {}
public interface IChildB : IBase {}
以及一个期望的界面IBase
:
public interface IFoo { void Bar(IBase val); }
然后根据需要在派生类中限制它:
public class Foo : IFoo { public void Bar(IChildA val) {} }
会产生以下问题:
IChildB something = new ChildB();
IFoo something = new Foo();
something.Bar(something); // This is an invalid call
因此,您没有履行您所说的合同。
在这种情况下,你有两个simple选项:
-
Adjust IFoo
是通用的,并接受T
这是一个推导IBase
:
public interface IFoo<T> where T : IBase { void Bar(T val); }
public class Foo : IFoo<IChildA> { public void Bar(IChildA val) {} }
当然,这意味着Foo
无法再接受any IBase
(包括IChildB
).
-
Adjust Foo
实施IFoo
,还有一个额外的实用方法void Bar(IChildA val)
:
public class Foo : IFoo
{
public void Bar(IBase val) {}
public void Bar(IChildA val) {}
}
这有一个有趣的副作用:每当你调用((IFoo)foo).Bar
它将期望IBase
,当你打电话时foo.Bar
它将期望IChildA
or IBase
。这意味着它满足合同,同时还具有特定于派生接口的方法。如果你想“隐藏”Bar(IBase)
方法更多,你可以实现IFoo
明确地:
void IFoo.Bar(IBase val) { }
这创造了更代码中的行为不一致,就像现在一样((IFoo)foo).Bar
is 完全地不同于foo.Bar
,但我把决定权留给你。
这意味着,在本节的第二个版本中,foo.Bar(new ChildB());
现在无效,因为IChildB
is not an IChildA
.
为什么我不能通过传递一个更派生的接口来实现这一点,该接口确实实现了基本要求。无论传递什么实例,它仍然会实现基础,我是否遗漏了什么?
由于我上面提到的原因,这是不允许的,IFoo.Bar
期望any IBase
,而你想要further将类型限制为IChildA
,即not一个超级接口IBase
,即使是,也不会被允许,因为它违反了接口实现,尽管您可以更容易此时定义第二个方法来执行您想要的操作。
请记住,当您实施interface
,您订阅了contract,而 C# 将not让你违反那个合同。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)