如何为PowerShell的-ceq运算符实现区分大小写的Equals方法
自定义类实现PowerShell区分大小写比较(-ceq)的方法
问题背景
在PowerShell中,自定义类的Equals方法会被-eq运算符调用。以下示例中,-eq实现了不区分大小写的比较:
class TestClass { hidden [String] $_Value TestClass([String]$Value) { $this._Value = $Value } [Bool] Equals($Test, [StringComparison]$StringComparison) { return $this._Value.Equals([String]$Test._Value, $StringComparison) } [Bool] Equals($Test) { return $this.Equals($Test, [StringComparison]::CurrentCultureIgnoreCase) } } $a1Lower = [TestClass]'a' $b1Lower = [TestClass]'b' $a2Lower = [TestClass]'a' $a2Upper = [TestClass]'A' $a1Lower -eq $b1Lower # False $a1Lower -eq $a2Lower # True $a1Lower -eq $a2Upper # True
现在需要让-ceq运算符实现区分大小写的比较,期望执行以下代码时得到符合预期的结果:
$a1Lower -ceq $a2Lower # True $a1Lower -ceq $a2Upper # False (原返回True,需修正)
解决方案
可以通过实现System.IEquatable<T>接口并分别定义大小写敏感和不敏感的比较逻辑来实现需求。PowerShell的-ceq运算符会优先调用IEquatable<T>接口的Equals方法,而-eq默认调用重写的Object.Equals方法,这样就能区分两种运算符的行为。
完整实现代码
class TestClass : System.IEquatable[TestClass] { hidden [String] $_Value # 构造函数 TestClass([String]$Value) { $this._Value = $Value } # IEquatable<T>接口方法:区分大小写的比较(供-ceq调用) [Bool] Equals([TestClass]$other) { if ($null -eq $other) { return $false } # 使用Ordinal规则进行严格大小写敏感比较 return $this._Value.Equals($other._Value, [StringComparison]::Ordinal) } # 重写Object.Equals:不区分大小写的比较(供-eq调用) [Bool] Equals($obj) { if ($null -eq $obj -or $obj -isnot [TestClass]) { return $false } $other = [TestClass]$obj return $this._Value.Equals($other._Value, [StringComparison]::CurrentCultureIgnoreCase) } # 重写GetHashCode:与不区分大小写的Equals逻辑保持一致 [int] GetHashCode() { return $this._Value.ToLowerInvariant().GetHashCode() } # 重载==运算符:绑定到不区分大小写的比较(对应-eq) static [Bool] op_Equality([TestClass]$a, [TestClass]$b) { if ($null -eq $a) { return $null -eq $b } return $a.Equals($b) } # 重载!=运算符:绑定到不区分大小写的比较(对应-ne) static [Bool] op_Inequality([TestClass]$a, [TestClass]$b) { return -not ([TestClass]::op_Equality($a, $b)) } }
测试验证
$a1Lower = [TestClass]'a' $b1Lower = [TestClass]'b' $a2Lower = [TestClass]'a' $a2Upper = [TestClass]'A' # 验证-eq(不区分大小写) $a1Lower -eq $b1Lower # 输出: False $a1Lower -eq $a2Lower # 输出: True $a1Lower -eq $a2Upper # 输出: True # 验证-ceq(区分大小写) $a1Lower -ceq $a2Lower # 输出: True $a1Lower -ceq $a2Upper # 输出: False(符合预期)
代码说明
- 继承
IEquatable<TestClass>:实现接口的Equals方法,使用StringComparison::Ordinal执行严格的大小写敏感比较,供-ceq运算符调用。 - 重写
Object.Equals:使用CurrentCultureIgnoreCase实现不区分大小写的比较,作为-eq运算符的默认逻辑。 - 重载运算符:绑定
op_Equality和op_Inequality到不区分大小写的比较逻辑,确保-eq和-ne的行为符合预期。 - 重写
GetHashCode:确保哈希值的计算逻辑与Object.Equals一致,避免集合操作中出现不一致的问题。
内容的提问来源于stack exchange,提问作者iRon
相关产品推荐
相关产品推荐

