覆盖接口方法但使用派生类的参数

c#

我想创建一个服务结构,所有这些服务都源自IService具有唯一方法的接口Perform

为了允许派生类定义特定 Perform 实现需要的参数类型,我将这些参数封装在一个名为的接口中 IConfig

问题是我无法访问自定义 Perform 实现中的派生类属性,因为我被迫键入将参数为IConfig

有什么方法可以用接口方法的参数类的派生类的参数覆盖接口/抽象类方法吗?

例子:

interface IConfig {}

class Config : IConfig
{
    public int Property;
}

interface IService
{
    void Perform(IConfig config);
}

class Service : IService
{
    void IService.Perform(IConfig config)
    {
        config.Property;
    }
}

通过上面的Service实现,我得到了错误:

“IConfig”不包含“属性”的定义

如果我把它改成这样:

class Service : IService
{
    void IService.Perform(Config config)
    {
        config.Property;
    }
}

我收到错误:

'Service' 没有实现接口成员 'IService.Perform(IConfig)'

在可实现的接口成员中找不到显式接口声明中的“Service.Perform(Config)”

我想知道是否有类似的东西:

void IService.Perform((IConfig)Config config)

或者

void IService.Perform(Config config as IConfig)

或者

(Config)config.Property

回答

使用泛型

这是使用泛型的完美案例。

interface IConfig { }

class Config : IConfig
{
    public int Property;
}

interface IService<T> where T : IConfig
{
    void Perform(T config);
}

class Service : IService<Config>
{
    public void Perform(Config config)
    {
        config.Property;
    }
}

泛型参考 - https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/generics/

where参考 - https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/keywords/where-generic-type-constraint


请注意,通过使类或接口泛型,您不能将其简化为非泛型形式,例如IService不更改它,以便泛型形式从非泛型基础扩展,如下所示:

interface IService
{

}

interface IService<T> : IService where T : IConfig
{
    void Perform(T config);
}

这在强制转换为时移除了对泛型表单属性的访问IService(这在您考虑时很明显)。您必须将其转换回其正确的泛型类型 ( IService<Config>) 才能访问那些在处理List<IService>多个泛型类型的集合(例如)时可能会引起头痛的属性。

为了避免这种情况,您可以满足于使用简单的铸造。

使用铸造

如果您不关心对配置类型的编译时限制,并且确实关心上述List<IService>问题,则可以选择运行时替代方案,如下所示:

interface IConfig { }

class Config : IConfig
{
    public int Property;
}

interface IService
{
    void Perform(IConfig config);
}

class Service : IService
{
    void IService.Perform(IConfig config)
    {
        if (!(config is Config)) throw new ArgumentException("Expected config to be of type Config");

        Config castedConfig = (Config)config;
        castedConfig.Property;
    }
}

不会阻止您Perform通过编译时限制使用不正确类型的配置进行调用,但是ArgumentException如果您确实使用不正确类型的配置调用它,它会在运行时抛出一个。


以上是覆盖接口方法但使用派生类的参数的全部内容。
THE END
分享
二维码
< <上一篇
下一篇>>