我有一个用于我的几何图形的界面,如下所示:

public interface IGeometry
{
    T Translate<T>(in v2 vector) where T : IGeometry;
    T MoveTo<T>(in v2 vector) where T : IGeometry;
}

我对如何在我的 struct 中定义它感到困惑,在 struct 中我专门返回实现接口的 struct 类型.我在我的Circle : IGeometry struct 中有这个:

public readonly struct Circle : IGeometry
{
    public readonly v2 _o;
    public readonly double _r, _area, _circum;
    public v2 Origin => _o;
    public double Radius => _r;
    public double Circumference => _circum;

    public Circle(in v2 origin, in double radius)
    {
        _o = origin;
        _r = radius;
        _area = _r * _r * Math.PI;
        _circum = _r * 2 * Math.PI;
    }

    public T Translate<T>(in v2 translation) => new(_o + translation, _r);
    public T MoveTo<T>(in v2 position) => new(position, _r);
}

然而,我得到的错误是:

Error CS0425: The constraints for type parameter 'T' of method 'Circle.Translate<T>(in v2)' 
must match the constraints for type parameter 'T' of interface method 
'IGeometry.Translate<T>(in v2)'. Consider using an explicit interface implementation instead.

我不太清楚该怎么解决这个问题.

推荐答案

如果您需要具有成员的泛型版本的非泛型,那么您确实需要两个接口.这是需要阴影方法的情况之一.

试试这些:

public interface IGeometry
{
    IGeometry Translate(in v2 vector);
    IGeometry MoveTo(in v2 vector);
}

public interface IGeometry<T> : IGeometry where T : IGeometry<T>
{
    new T Translate(in v2 vector);
    new T MoveTo(in v2 vector);
}

现在可以隐式实现泛型接口,显式实现非泛型接口.

public readonly struct Circle : IGeometry<Circle>
{
    private readonly v2 _o;
    private readonly double _r, _area, _circum;
    public v2 Origin => _o;
    public double Radius => _r;
    public double Circumference => _circum;

    public Circle(in v2 origin, in double radius)
    {
        _o = origin;
        _r = radius;
        _area = _r * _r * Math.PI;
        _circum = _r * 2 * Math.PI;
    }

    public Circle Translate(in v2 translation) => new(_o + translation, _r);
    public Circle MoveTo(in v2 position) => new(position, _r);

    IGeometry IGeometry.Translate(in v2 vector) => this.Translate(vector);
    IGeometry IGeometry.MoveTo(in v2 vector) => this.MoveTo(vector);
}

现在,您可以执行以下操作:

Circle circle1 = new Circle();
Circle circle2 = circle1.Translate(new v2());
IGeometry geometry1 = circle1;
IGeometry geometry2 = geometry1.Translate(new v2());
Circle circle2a = (Circle)geometry2;

对非泛型接口方法的调用调用泛型版本以保持类型安全.

但是,请记住,您可以合法地实施以下操作:

public readonly struct Square : IGeometry<Circle>

你需要小心不要这样做.

Csharp相关问答推荐

将C#字符串转换为其UTF8编码字符的十六进制表示

在C# 11之前, struct 中的每个字段都必须显式分配?不能繁殖

我可以 suppress 规则CS 9035一次吗?

Blazor:类型或命名空间名称Components在命名空间中不存在''

此反射有什么问题.是否发送值转换委托?

如何删除文件的基础上嵌入的时间戳嵌入文件名

Polly使用泛型重试和重试包装函数

XUNIT是否使用测试数据的源生成器?

mocking对象的引发事件并作为用于调用方法的参数对象传递到那里

反序列化私有成员

如何在VS代码中为C#DotNet配置.json选项以调试内部终端的控制台应用程序

TagHelpers在新区域不起作用

当空判断结果赋给变量时,为什么会出现可能空异常警告的解引用?

正在从最小API-InvocationConext.Arguments中检索参数的FromBodyAttribute

在集成测试中可以在模拟InMemory数据库中设定数据种子

Blazor Server/.NET 8/在初始加载时调用异步代码是否冻结屏幕,直到第一次异步调用完成?

发布.NET 8 Blazor WebAssembly独立应用程序以进行静态站点部署

如何使用ODP.NET C#设置Oracle会话时间长度限制

C#使用相同内存的多个数组

如何在Cake脚本中设置MSBuild.exe的绝对路径