0

语境:

我正在 C# 中实现一个 BigRational 结构,它需要各种算术和比较重载。许多重载中的代码看起来完全相同,因为使用了var. 最重要的是,我收到了 CA2225 的警告,其中指出各种操作员需要一种“友好的替代命名”方法。请参阅https://docs.microsoft.com/en-us/dotnet/fundamentals/code-analysis/quality-rules/ca2225

由于许多算术运算符被重载

  • (BigRational, BigRational) -> BigRational
  • (BigRational, BigInteger) -> BigRational
  • (BigInteger, BigRational) -> BigRational
  • (BigRational,长)-> BigRational
  • (长,BigRational)-> BigRational
  • (BigRational, ulong) -> BigRational
  • (ulong, BigRational) -> BigRational

和比较运算符

  • (BigRational, BigRational) -> bool
  • (BigRational, BigInteger) -> bool
  • (BigInteger, BigRational) -> bool
  • (BigRational, long) -> bool
  • (long, BigRational) -> bool
  • (BigRational, ulong) -> bool
  • (ulong, BigRational) -> bool

这会导致大量重复的代码和样板。

问题:

有没有一种简单的方法来使用 C# 9 样式生成器来实现这个?

旁观:

如果 C# 可以在语言中内置重载生成,那就太好了

public static BigRational Add<T>(BigRational augend, T addend)
    where T overloads: BigInteger, long, ulong
{
    // use var in code...
}

相当于

public static BigRational Add(BigRational augend, BigInteger addend)
{
}

public static BigRational Add(BigRational augend, long addend)
{
}

public static BigRational Add(BigRational augend, ulong addend)
{
}

这也将允许为不共享基类或接口但具有非常相似的 API 的类型编写单个函数。

4

1 回答 1

0

这是您可以编写的源代码生成器的想法,它可以让您在一般情况下解决这个问题。我不打算编写源代码生成器,因为那将是相当多的工作,但我会重点介绍它的设计。

你会这样写你的类:

public partial struct BigRational
{
    public static BigRational Add(BigRational augend, [GenerateOverloadsFor(typeof(long), typeof(ulong ))] BigInteger addend)
    {
    }
}

然后源生成器将检测使用GenerateOverloadsForAttribute并生成以下内容:

partial struct BigRational
{
    public static BigRational Add(BigRational augend, long addend)
    {
    }

    public static BigRational Add(BigRational augend, ulong addend)
    {
    }
}

虽然为这种特定情况编写源代码生成器不太值得,但希望该解决方案足够通用,也适用于其他用例。

为了使您的源代码生成器简单明了,它可能只是将代码直接从“模板”复制到生成的重载中。这意味着您必须仔细编写代码,以便它适用于所有重载,否则您将获得编译时错误。

于 2020-12-13T13:17:20.407 回答