在PowerShell中使用带有重载算术运算符的自定义.NET类

use*_*593 5 .net c# powershell operators

我在C#中定义了一个类(称为类A)并为其重载了一些算术运算符.让我们关注加法运算符(虽然我希望其他运算符的行为类似).我已经设置了A类,以便我可以为它添加一个标量(即单个Double值),我可以将它添加到标量中,或者我可以将A的两个实例加在一起.

所以在C#中我有"+"运算符重载了三个不同的签名.签名明确地是:

  • A + Double
  • 双+ A
  • A + A.

当我在PowerShell中使用该类时,它只识别三个重载中的一个.因此在PowerShell中我可以执行A + Double但其他两个表达式会导致错误.

当我在A的实例上使用Get-Member Cmdlet时,看起来它"看到"了所有三个重载,但只是表示列表中的第一个重载.

我怀疑这是设计的.我喜欢PowerShell,但它与C#非常不同,我希望它只允许一个重载运算符的签名(基于我迄今为止所了解的内容),并且表达式的左手成员确定了添加的类型.执行.谁能确认一下?

我的工作是在C#中为类编写一些更详细的静态方法(如"AddScalar"和"AddA"方法).在PowerShell中,我会调用这些命名方法而不是使用"+"运算符.这应该可以正常工作,但让PowerShell根据添加的内容使用"+"的相应定义会很好.

有没有人使用具有不同签名的重载类运算符取得任何成功,或者这种行为会破坏PowerShell的基本设计目标吗?

更新: Dugas钉了它.但是我一路上学到了别的东西,想把它贴在这里.

当我为类AI定义添加时,定义它以便添加类A的两个实例将生成类A的新实例或生成NULL.(这对我来说设计很差,因为添加真的应该关闭.换句话说,理想情况下,添加应该总是产生一些可以被另一个添加运算符操作的东西.)在C#中,这不是问题,因为我从来没有添加更多一次检查两个对象,并在检查结果时检查NULL.

如果操作的结果为NULL,则不会返回NULL PowerShell将为op_Addition运算符抛出"Object reference not set ..."错误.我假设在PowerShell尝试使用错误的重载操作符并且执行类型转换时遇到问题时创建了NULL引用,从而误解了此错误.

我重新考虑了对象的A + A情况,当它们相加时,返回A类的另一个对象实例,一切都很好.

总而言之,如果a1,a2和a3都是A类的实例,d是Double,如果a1 + a2 = NULL且a1 + a3 = aX(其中aX是A类的新实例)那么...

  • d + a1#失败,因为PowerShell没有看到Double的运算符,而A类和A类都无法转换为Double.
  • a1 + d#按预期工作
  • a1 + a2#失败.抛出"对象引用未设置..."错误,因为结果为NULL.
  • a1 + a3#按预期工作.

谢谢你指导我正确的方向!

dug*_*gas 2

出于好奇我对此进行了测试。我创建了一个像这样的类:

namespace ClassLibrary1
{
 public class Class1
 {
  public static string operator +(Class1 class1, double d)
  {
   return "a";
  }

  public static string operator +(double d, Class1 class1)
  {
   return "b";
  }

  public static string operator +(Class1 class1, Class1 class12)
  {
   return "c";
  }
 }
}
Run Code Online (Sandbox Code Playgroud)

我能够调用以 Class1 作为第一个参数的两个重载,但无法调用以 double 作为第一个参数的重载。我不知道为什么你不能调用 A + A 的重载,也许除了分派正确的运算符重载之外还有其他原因?

$a = New-Object ClassLibrary1.Class1
($a + 0) -eq 'a' # Was True
($a + $a) -eq 'c' # Was True
Run Code Online (Sandbox Code Playgroud)

调用重载:

([double]0 + $a) -eq 'b'
Run Code Online (Sandbox Code Playgroud)

给出错误:

无法将“ClassLibrary1.Class1”类型的“ClassLibrary1.Class1”值转换为“System.Double”类型。

所以我假设您可以调用不同的运算符重载,只要第一个参数是运算符重载的类型?