gpt4 book ai didi

c# - 推断或忽略嵌套 C# 接口(interface)中的嵌套泛型

转载 作者:行者123 更新时间:2023-11-30 21:27:02 27 4
gpt4 key购买 nike

假设我们有一个容器 IDevice包含 IDeviceTagBag对象,和 IDeviceTagBag本身就是IDeviceTag的容器对象。

现在我希望它们成为泛型类,同时保持上述约束。

Java 中,我会执行以下操作:

public interface IDeviceTag {}

public interface IDeviceTagBag<TDeviceTag extends IDeviceTag> {}

public interface IDevice<TDeviceTagBag extends IDeviceTagBag<?>> {}

编写一个返回 IDevice 的方法(Java 解决方案)现在看起来像这样:

public class DeviceService
{
// Compiler will infer the following covariant chain:
// -> ? extends IDeviceTagBag -> ? extends IDeviceTag
public IDevice<?> Get(string name)
{
return null;
}

// Or the invariant alternative:
// -> IDeviceTagBag -> IDeviceTag
public IDevice<IDeviceTagBag<IDeviceTag>> GetInvariant(string name)
{
return null;
}
}

我尝试使用 C#(不变或协变)实现同样的事情,但我最终得到了以下感觉像是一个大样板的解决方案:

// OK !
public interface IDeviceTag {}

// OK !
public interface IDeviceTagBag<TDeviceTag> where TDeviceTag : IDeviceTag {}

// Ouch, no substitute for wildcard "<?>"
public interface IDevice<TDeviceTagBag, TDeviceTag>
where TDeviceTagBag : IDeviceTagBag<TDeviceTag>
where TDeviceTag : IDeviceTag
{}

编写一个返回 IDevice 的方法(C# 解决方案)如下所示:

public class DeviceService
{
// So much to replace "<?>"
public IDevice<IDeviceTagBag<IDeviceTag>, IDeviceTag> Get(string name)
{
return null;
}
}

我的应用程序中实际上有第四个嵌套的通用接口(interface),它变得很讨厌。

我是否遗漏了一些可以简化它的东西,比如在带有 <?>Java 解决方案中?

找到那些帖子后...

...恐怕我对此无能为力。

还是我过度设计了这个东西?毕竟,如果我删除 where约束,我不再有这个样板问题;但开发人员可以实现 IDevice除了IDeviceTagBag以外的东西...


答案的结论(2019 年 10 月 19 日)

  • 如果您的接口(interface)是只读的,您可以使您的接口(interface)协变。请参阅@Alpha75 的回答。

  • 如果您的接口(interface)不是只读的,您可以创建非通用接口(interface),它们是通用接口(interface)的“兄弟”,以替代 Java <?>通配符泛型。请参阅@canton7 的回答。

两个答案都很好,但我只能接受一个...所以我接受最能复制我的 Java 解决方案的那个。 :(


附录:为什么我需要我的接口(interface)是通用的

我构建了一个库,提供与各种设备类型的通信功能。他们所有人的共同 Action 是接收和发送消息。然后,根据设备类型,还有其他功能。

使用该库的开发人员可以使用常见的 DeviceService访问任何类型的设备,但仅限于常见操作。

如果他们想使用特定的功能,他们可以说 SpecificDeviceService ,但如果底层设备类型发生变化,他们将不得不更新代码。

A SpecificDevice需要实现 IDevice如果我希望可以通过 DeviceService 访问它或 SpecificDeviceService :

public interface IDevice
{
IDeviceTagBag Tags
{
get;
}

// ...
}

public interface ISpecificDevice : IDevice
{
// Problem:
// - "Tags" still return "IDeviceTagBag" here and not "ISpecificDeviceTagBag"
// - End users will have to do explicit casts
}

为了防止评论中所说的“问题”,一个解决方案是使用泛型。

// New problem: "TDeviceTagBag" may be something else than "IDeviceTagBag"
public interface IDevice<TDeviceTagBag>
{
TDeviceTagBag Tags
{
get;
}

// ...
}

public interface ISpecificDevice : IDevice<ISpecificDeviceTagBag>
{
// First problem solved: "Tags" return "ISpecificDeviceTagBag"
}

但是,当用 where 约束通用类型时解决上述新问题的条件,我得到了上面问题中解释的“样板”代码,因为我总共有 4 层:

IDeviceService -> IDevice -> IDeviceTagBag -> IDeviceTag

最佳答案

在我看来,第三个接口(interface)不需要两个通用类型。你可以用一个 where 来解决它:

public interface IDeviceTag { }

public interface IDeviceTagBag<out TDeviceTag>
where TDeviceTag : IDeviceTag
{ }

public interface IDevice<TDeviceTagBag>
where TDeviceTagBag : IDeviceTagBag<IDeviceTag>
{ }

关于c# - 推断或忽略嵌套 C# 接口(interface)中的嵌套泛型,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58397612/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com