问题描述
假设我们有以下3个类:
Let's assume we have these 3 classes:
Class BaseClass : System.IComparable
{
[int] $Value
BaseClass([int] $v)
{
$this.Value = $v
}
[int] CompareTo($that)
{
If (-Not($that -is [BaseClass])) {
Throw "Not comparable!!"
}
return $this.Value - $that.Value
}
}
Class SubClassA : BaseClass
{
SubClassA([int] $v) : base($v)
{
}
}
Class SubClassB : BaseClass
{
SubClassB([int] $v) : base($v)
{
}
}
当我们比较BaseClass
的实例时,此实现效果很好:
This implementation works great when we compare instances of BaseClass
:
$base1 = [BaseClass]::new(1)
$base2 = [BaseClass]::new(2)
Write-Output ($base1 -lt $base2)
# Output: True
Write-Output ($base1 -gt $base2)
# Output: False
但是我找不到比较两个子类的两个实例的方法:
But I can't find a way to compare two instances of the two subclasses:
$subA1 = [SubClassA]::new(1)
$subB2 = [SubClassB]::new(2)
Write-Output (([BaseClass]$subA1) -lt ([BaseClass]$subB2))
PowerShell无法执行此代码,并引发以下错误:
PowerShell can't execute this code, throwing this error:
Impossibile confrontare "SubClassA" con "SubClassB".
Errore:
"Impossibile convertire il valore "SubClassB" di tipo "SubClassB" nel tipo "SubClassA"."
从意大利语翻译成英语,此错误消息听起来像:
Translated from Italian to English, this error message sounds like:
Unable to compare "SubClassA" with "SubClassB".
Error:
"Unable to convert the value "SubClassB" of type "SubClassB" to the type "SubClassA"."
为什么会出现此错误?如何将SubClassA
的实例与SubClassB
的实例进行比较,就好像它们是BaseClass
的两个实例一样?
Why this error?How can we compare an instance of SubClassA
with an instance of SubClassB
as if they were two instances of BaseClass
?
PS:$PSVersionTable
的输出:
PSVersion 5.1.17134.1
PSEdition Desktop
PSCompatibleVersions {1.0, 2.0, 3.0, 4.0...}
BuildVersion 10.0.17134.1
CLRVersion 4.0.30319.42000
WSManStackVersion 3.0
PSRemotingProtocolVersion 2.3
SerializationVersion 1.1.0.1
推荐答案
该行为的确令人惊讶,我发现您已打开一个GitHub问题进行讨论.
The behavior is indeed surprising and I see that you've opened a GitHub issue to discuss it.
一些其他想法:
-
PowerShell的运算符通常具有扩展的语义,通常不应假定它们在所有情况下都与C#对应语言一样工作-但是,在这种特定情况下,他们显然应该(请参见下文) ).
PowerShell's operators often have extended semantics and generally shouldn't be assumed to work the same as their C# counterparts in all cases - however, in this particular case they clearly should (see below).
-lt
实际上可以与 base-class 实例一起使用的事实已经指出了一个区别:等效的C#类将另外需要<
和运算符,以支持使用<
.
The fact that -lt
actually works with the base-class instances already points to a difference: the equivalent C# class would additionally require explicit overloading of the <
and >
operators in order to support to support use of <
.
接口实现由PowerShell和C#中的派生类继承,因此为了应用-lt
,无需强制转换为基类.
Interface implementations are inherited by derived classes in both PowerShell and C#, so there should be no need to cast to the base class in order to apply -lt
.
这里似乎正在发生的事情是,PowerShell盲目地尝试将RHS转换为LHS的类型,而不考虑它们的共享基类.
What seems to be happening here is that PowerShell blindly tries to convert the RHS to the type of the LHS without considering their shared base class.
如果RHS类型直接从LHS类型派生(但不是相反),则不会出现此问题;例如:
The problem does not arise if the RHS type directly derives from the LHS type (but not the other way around); e.g.:
$base1 -lt $subA1 # OK: SubClassA (RHS) derives from BaseClass (LHS)
$subA1 -lt $base1 # !! BREAKS: BaseClass (RHS) does NOT derive from SubClassA (LHS)
这篇关于PowerShell IComparable与子类的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!