【问题标题】:Using custom .NET classes with overloaded arithmetic operators in PowerShell在 PowerShell 中使用带有重载算术运算符的自定义 .NET 类
【发布时间】:2012-10-09 10:46:54
【问题描述】:

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

所以在 C# 中,“+”运算符重载了三个不同的签名。明确的签名是:

  • A + 双
  • 双+A
  • A + A

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

当我在 A 的实例上使用 Get-Member Cmdlet 时,它看起来好像“看到”了所有三个重载,但只尊重列表中的第一个重载。

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

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

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

更新: Dugas 搞定了。但我确实在此过程中学到了其他东西,并想在这里发布。

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

如果操作的结果为 NULL,PowerShell 会为 op_Addition 运算符抛出“未设置对象引用...”错误,而不是返回 NULL。当 PowerShell 尝试使用错误的重载运算符并且在执行类型转换时遇到问题时,我假设正在创建 NULL 引用,从而误解了这个错误。

我为对象重新运行了 A + A 案例,这些对象在求和时会返回 A 类的另一个对象实例,并且一切正常。

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

  • d + a1 # 失败,因为 PowerShell 没有看到使用 Class A 的 Double 运算符,并且 Class A 无法转换为 Double。
  • a1 + d # 按预期工作
  • a1 + a2 # 失败。由于结果为 NULL,因此引发“未设置对象引用 ...”错误。
  • a1 + a3 # 按预期工作。

感谢您引导我朝着正确的方向前进!

【问题讨论】:

  • 调用正确的操作符方法是 C# 编译器的一个特性,所以我一点也不奇怪,这在 PowerShell 中不能很好地工作。
  • 我很确定这是在 CLS 中标准化的。

标签: c# .net powershell operators


【解决方案1】:

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

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";
  }
 }
}

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

$a = New-Object ClassLibrary1.Class1
($a + 0) -eq 'a' # Was True
($a + $a) -eq 'c' # Was True

调用重载:

([double]0 + $a) -eq 'b'

报错:

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

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

【讨论】:

  • 在所有方面都正确。阅读您的帖子后,我回去尝试了更多示例。事实证明,我试图将两个特定的类实例加在一起返回 NULL。 PowerShell 在 op_Addition 方法中引发“对象引用未设置到实例...”错误。因为我知道两个输入都不是 NULL,所以我假设 NULL 对象错误是由于 PowerShell 应用了错误的重载并且未能将对象转换为兼容类型而引起的。
猜你喜欢
  • 1970-01-01
  • 2013-08-15
  • 1970-01-01
  • 2016-07-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-06-14
相关资源
最近更新 更多