简体   繁体   English

有没有办法在 C# 中生成 function 过载?

[英]Is there a way to generate function overloads in C#?

Context:语境:

I am implementing a BigRational struct in C# which requires various arithmetic and comparison overloads.我正在 C# 中实现一个 BigRational 结构,它需要各种算术和比较重载。 The code in many of the overloads look exactly the same because of the use of var .由于使用了var ,许多重载中的代码看起来完全相同。 On top of this I am getting a warning for CA2225 which states that various operators need a "friendly alternatively named" method.最重要的是,我收到了 CA2225 的警告,其中指出各种操作员需要一种“友好的替代命名”方法。 See https://docs.microsoft.com/en-us/dotnet/fundamentals/code-analysis/quality-rules/ca2225请参阅https://docs.microsoft.com/en-us/dotnet/fundamentals/code-analysis/quality-rules/ca2225

Since many arithmetic operators are overloaded for由于许多算术运算符被重载

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

and comparison operators for和比较运算符

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

this results in a significant amount of duplicate code and boilerplate.这会导致大量重复的代码和样板。

Question:问题:

Is there a simple way to use C# 9 style generators to implement this?有没有一种简单的方法来使用 C# 9 样式生成器来实现这个?

Side Thought:旁观:

It would be great if C# could get overload generation built into the language so that如果 C# 可以在语言中内置重载生成功能,那就太好了

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

is equivalent to相当于

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

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

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

This would also allow one to write a single function for types that do not share a base class or interface, but have very similar APIs.这也将允许为不共享基本 class 或接口但具有非常相似的 API 的类型编写单个 function。

Here's an idea for a source generator you could write, which would allow you to solve this problem in general.这是您可以编写的源代码生成器的想法,它可以让您在一般情况下解决这个问题。 I'm not going to write the source generator, as that would be quite a bit of work, but I'll highlight a design for it.我不打算编写源代码生成器,因为那将是相当多的工作,但我会重点介绍它的设计。

You would write your class like this:你会这样写你的 class :

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

Then the source generator would detect usages of GenerateOverloadsForAttribute and generate the following:然后源生成器将检测GenerateOverloadsForAttribute的用法并生成以下内容:

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

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

Whilst it's unlikely to be worth writing a source generator for this specific case, this solution should hopefully be generic enough to work for other use cases as well.虽然为这种特定情况编写源代码生成器不太值得,但希望该解决方案足够通用,也适用于其他用例。

To keep your source generator straightforward it would probably just copy the code straight over from the 'template' to the generated overloads.为了使您的源代码生成器简单明了,它可能只是将代码直接从“模板”复制到生成的重载中。 This means that you'll have to write your code carefully so that it works for all overloads, or else you'll get compile time errors.这意味着您必须仔细编写代码,以便它适用于所有重载,否则您将获得编译时错误。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM